From a12b843ec00d7c55cfe95ac7783556b7634bdecb Mon Sep 17 00:00:00 2001 From: Sk Niyaj Ali Date: Sat, 24 Aug 2024 01:17:35 +0530 Subject: [PATCH] Fix Gradle Error & Refactor Multiple Activity to Single Activity (#1750) * Fix Gradle Error & Refactor Multiple Activity to Single Activity * Fixed Build Error * Fixed CI Workflow Usage * Fixed CI Workflow Usage * Fixed CI Workflow * Fixing CI Workflow Usage * Fixing CI Workflow Usage * CI - Rename dependency check job to dependency guard * CI - Trigger workflow on pull requests * CI - Updated CI Workflow Usage --- .github/workflows/master_dev_ci.yml | 238 +- build.gradle.kts | 11 +- .../auth/AuthenticationUserRepository.kt | 8 +- .../repository/auth/UserDataRepository.kt | 2 + .../designsystem/component/LoadingWheel.kt | 4 +- .../designsystem/component/MifosTopBar.kt | 5 +- .../mifospay/core/designsystem/theme/Theme.kt | 3 - .../org/mifospay/core/ui/ExpiryDateInput.kt | 2 +- .../org/mifospay/core/ui/FaqItemScreen.kt | 4 +- .../org/mifospay/core/ui/MifosUserImage.kt | 2 +- desktop/build.gradle.kts | 2 +- feature/auth/build.gradle.kts | 10 - .../feature/auth/login/LoginActivity.kt | 28 - .../feature/auth/login/LoginScreen.kt | 31 +- .../feature/auth/login/LoginViewModel.kt | 15 +- .../auth/navigation/LoginScreenNavigation.kt | 9 +- .../feature/auth/signup/SignupScreen.kt | 132 +- .../org/mifospay/feature/home/HomeScreen.kt | 8 +- .../feature/home/navigation/HomeNavigation.kt | 2 +- .../mifospay/feature/kyc/KYCLevel2Screen.kt | 4 +- .../merchants/ui/MerchantTransferScreen.kt | 44 +- feature/passcode/build.gradle.kts | 5 - feature/passcode/src/main/AndroidManifest.xml | 2 +- .../feature/passcode/PassCodeActivity.kt | 128 -- .../feature/passcode/PassCodeScreen.kt | 242 ++ .../feature/passcode/PasscodeNavigation.kt | 39 + .../feature/passcode/component/MifosIcon.kt | 34 + .../passcode/component/PasscodeButton.kt | 71 + .../passcode/component/PasscodeHeader.kt | 121 + .../passcode/component/PasscodeKeys.kt | 198 ++ .../component/PasscodeMismatchedDialog.kt | 44 + .../component/PasscodeStepIndicator.kt | 59 + .../passcode/component/PasscodeToolbar.kt | 94 + .../feature/passcode/data/PasscodeManager.kt | 34 + .../passcode/data/PasscodeRepository.kt | 18 + .../passcode/data/PasscodeRepositoryImpl.kt | 29 + .../feature/passcode/di/ApplicationModule.kt | 37 + .../mifospay/feature/passcode/theme/Color.kt | 14 + .../mifospay/feature/passcode/theme/Font.kt | 34 + .../mifospay/feature/passcode/theme/Theme.kt | 49 + .../mifospay/feature/passcode/theme/Type.kt | 41 + .../feature/passcode/utility/Constants.kt | 16 + .../passcode/utility/PreferenceManager.kt | 39 + .../passcode/utility/ShakeAnimation.kt | 37 + .../mifospay/feature/passcode/utility/Step.kt | 15 + .../passcode/utility/VibrationFeedback.kt | 48 + .../passcode/viewmodels/PasscodeViewModel.kt | 151 ++ .../drawable/baseline_delete_forever_24.xml | 6 +- .../src/main/res/drawable/ic_delete.xml | 20 + .../src/main/res/drawable/mifos_logo.jpg | Bin 0 -> 75684 bytes .../passcode/src/main/res/font/lato_black.ttf | Bin 0 -> 69500 bytes .../passcode/src/main/res/font/lato_bold.ttf | Bin 0 -> 73332 bytes .../src/main/res/font/lato_regular.ttf | Bin 0 -> 75152 bytes .../passcode/src/main/res/values/strings.xml | 20 + .../feature/profile/edit/EditProfileScreen.kt | 102 +- .../feature/request/money/SetAmountDialog.kt | 12 +- .../feature/send/money/SendScreenRoute.kt | 32 +- gradle/libs.versions.toml | 19 +- mifospay/build.gradle.kts | 10 +- .../prodReleaseRuntimeClasspath.tree.txt | 2031 +++++++++++++++++ .../prodReleaseRuntimeClasspath.txt | 44 +- mifospay/prodRelease-badging.txt | 5 +- mifospay/src/main/AndroidManifest.xml | 39 +- .../main/java/org/mifospay/MainActivity.kt | 55 +- .../org/mifospay/MainActivityViewModel.kt | 12 +- .../src/main/java/org/mifospay/MifosPayApp.kt | 28 - .../java/org/mifospay/SplashScreenActivity.kt | 40 - .../java/org/mifospay/base/BaseActivity.kt | 170 -- .../org/mifospay/common/ui/SearchActivity.kt | 4 +- .../java/org/mifospay/di/ApplicationModule.kt | 12 - .../org/mifospay/navigation/LoginNavGraph.kt | 51 + .../org/mifospay/navigation/MifosNavGraph.kt | 17 + .../org/mifospay/navigation/MifosNavHost.kt | 342 ++- .../mifospay/navigation/PasscodeNavGraph.kt | 42 + .../org/mifospay/navigation/RootNavGraph.kt | 45 + .../src/main/java/org/mifospay/ui/MifosApp.kt | 84 +- .../java/org/mifospay/ui/MifosAppState.kt | 8 +- .../main/res/color/background_chip_state.xml | 14 - .../main/res/drawable/bg_et_round_border.xml | 19 - mifospay/src/main/res/drawable/bg_splash.xml | 9 +- .../main/res/drawable/button_round_black.xml | 20 - .../main/res/drawable/button_round_gray.xml | 20 - .../res/drawable/button_round_primary.xml | 20 - .../main/res/drawable/button_round_stroke.xml | 22 - .../res/drawable/button_round_stroke_gray.xml | 23 - .../drawable/button_round_stroke_primary.xml | 23 - .../main/res/drawable/cardview_round_blue.xml | 20 - .../res/drawable/cardview_round_green.xml | 20 - .../drawable/drawable_bottom_sheet_view.xml | 22 - .../drawable/drawable_editable_image_hint.xml | 27 - mifospay/src/main/res/drawable/et_search.xml | 14 - .../drawable/ic_account_balance_wallet.xml | 19 - .../src/main/res/drawable/ic_accounts.xml | 19 - mifospay/src/main/res/drawable/ic_add.xml | 19 - .../src/main/res/drawable/ic_add_white.xml | 19 - .../res/drawable/ic_arrow_back_black_24dp.xml | 19 - .../res/drawable/ic_arrow_back_white_24dp.xml | 20 - mifospay/src/main/res/drawable/ic_bank.xml | 28 - .../drawable/ic_baseline_content_copy_24.xml | 20 - .../drawable/ic_baseline_insert_photo_24.xml | 20 - .../res/drawable/ic_baseline_share_24.xml | 20 - mifospay/src/main/res/drawable/ic_camera.xml | 22 - mifospay/src/main/res/drawable/ic_cards.xml | 19 - .../drawable/ic_check_round_black_24dp.xml | 19 - mifospay/src/main/res/drawable/ic_close.xml | 19 - mifospay/src/main/res/drawable/ic_contact.xml | 44 - mifospay/src/main/res/drawable/ic_done.xml | 19 - mifospay/src/main/res/drawable/ic_edit.xml | 55 - mifospay/src/main/res/drawable/ic_email.xml | 15 - .../src/main/res/drawable/ic_empty_state.xml | 19 - .../src/main/res/drawable/ic_error_state.xml | 19 - .../src/main/res/drawable/ic_flash_off.xml | 17 - .../src/main/res/drawable/ic_flash_on.xml | 17 - mifospay/src/main/res/drawable/ic_history.xml | 19 - mifospay/src/main/res/drawable/ic_invoice.xml | 89 - .../src/main/res/drawable/ic_invoices.xml | 19 - .../src/main/res/drawable/ic_logo_outline.xml | 54 - .../src/main/res/drawable/ic_merchant.xml | 68 - .../src/main/res/drawable/ic_merchants.xml | 19 - mifospay/src/main/res/drawable/ic_mobile.xml | 15 - mifospay/src/main/res/drawable/ic_next.xml | 27 - .../src/main/res/drawable/ic_next_black.xml | 27 - .../src/main/res/drawable/ic_notification.xml | 27 - .../main/res/drawable/ic_photo_library.xml | 19 - mifospay/src/main/res/drawable/ic_remove.xml | 19 - .../ic_remove_circle_outline_black_24dp.xml | 19 - mifospay/src/main/res/drawable/ic_repeat.xml | 19 - .../main/res/drawable/ic_repeat_selector.xml | 14 - mifospay/src/main/res/drawable/ic_request.xml | 19 - .../main/res/drawable/ic_request_selector.xml | 13 - .../src/main/res/drawable/ic_right_arrow.xml | 26 - mifospay/src/main/res/drawable/ic_save.xml | 19 - .../src/main/res/drawable/ic_saved_cards.xml | 26 - mifospay/src/main/res/drawable/ic_search.xml | 19 - mifospay/src/main/res/drawable/ic_send.xml | 19 - .../main/res/drawable/ic_send_selector.xml | 13 - mifospay/src/main/res/drawable/ic_setting.xml | 91 - mifospay/src/main/res/drawable/ic_share.xml | 19 - mifospay/src/main/res/drawable/ic_tick.xml | 19 - .../src/main/res/drawable/ic_transaction.xml | 15 - mifospay/src/main/res/drawable/ic_verify.xml | 33 - .../main/res/drawable/layout_rounded_edge.xml | 24 - .../src/main/res/drawable/qrcode_black.xml | 18 - .../res/drawable/qrcode_black_selector.xml | 13 - .../src/main/res/drawable/qrcode_blue.xml | 18 - .../res/drawable/qrcode_blue_selector.xml | 13 - .../shape_bottom_sheet_dialog_grip.xml | 15 - .../main/res/drawable/sim_card_selected.xml | 48 - .../main/res/drawable/sim_card_unselected.xml | 42 - .../main/res/drawable/transfer_failure.xml | 32 - .../main/res/drawable/transfer_success.xml | 32 - mifospay/src/main/res/values/splash.xml | 5 +- mifospay/src/main/res/values/themes.xml | 5 +- settings.gradle.kts | 13 +- shared/build.gradle.kts | 2 +- 155 files changed, 4302 insertions(+), 2936 deletions(-) delete mode 100644 feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginActivity.kt delete mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PassCodeActivity.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PassCodeScreen.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PasscodeNavigation.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/MifosIcon.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeButton.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeHeader.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeKeys.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeMismatchedDialog.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeStepIndicator.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeToolbar.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeManager.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeRepository.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeRepositoryImpl.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/di/ApplicationModule.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Color.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Font.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Theme.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Type.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/Constants.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/PreferenceManager.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/ShakeAnimation.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/Step.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/VibrationFeedback.kt create mode 100644 feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/viewmodels/PasscodeViewModel.kt rename mifospay/src/main/res/drawable/ic_download.xml => feature/passcode/src/main/res/drawable/baseline_delete_forever_24.xml (52%) create mode 100644 feature/passcode/src/main/res/drawable/ic_delete.xml create mode 100644 feature/passcode/src/main/res/drawable/mifos_logo.jpg create mode 100644 feature/passcode/src/main/res/font/lato_black.ttf create mode 100644 feature/passcode/src/main/res/font/lato_bold.ttf create mode 100644 feature/passcode/src/main/res/font/lato_regular.ttf create mode 100644 mifospay/dependencies/prodReleaseRuntimeClasspath.tree.txt delete mode 100644 mifospay/src/main/java/org/mifospay/SplashScreenActivity.kt delete mode 100644 mifospay/src/main/java/org/mifospay/base/BaseActivity.kt create mode 100644 mifospay/src/main/java/org/mifospay/navigation/LoginNavGraph.kt create mode 100644 mifospay/src/main/java/org/mifospay/navigation/MifosNavGraph.kt create mode 100644 mifospay/src/main/java/org/mifospay/navigation/PasscodeNavGraph.kt create mode 100644 mifospay/src/main/java/org/mifospay/navigation/RootNavGraph.kt delete mode 100644 mifospay/src/main/res/color/background_chip_state.xml delete mode 100644 mifospay/src/main/res/drawable/bg_et_round_border.xml delete mode 100644 mifospay/src/main/res/drawable/button_round_black.xml delete mode 100644 mifospay/src/main/res/drawable/button_round_gray.xml delete mode 100644 mifospay/src/main/res/drawable/button_round_primary.xml delete mode 100644 mifospay/src/main/res/drawable/button_round_stroke.xml delete mode 100644 mifospay/src/main/res/drawable/button_round_stroke_gray.xml delete mode 100644 mifospay/src/main/res/drawable/button_round_stroke_primary.xml delete mode 100644 mifospay/src/main/res/drawable/cardview_round_blue.xml delete mode 100644 mifospay/src/main/res/drawable/cardview_round_green.xml delete mode 100644 mifospay/src/main/res/drawable/drawable_bottom_sheet_view.xml delete mode 100644 mifospay/src/main/res/drawable/drawable_editable_image_hint.xml delete mode 100644 mifospay/src/main/res/drawable/et_search.xml delete mode 100644 mifospay/src/main/res/drawable/ic_account_balance_wallet.xml delete mode 100644 mifospay/src/main/res/drawable/ic_accounts.xml delete mode 100644 mifospay/src/main/res/drawable/ic_add.xml delete mode 100644 mifospay/src/main/res/drawable/ic_add_white.xml delete mode 100644 mifospay/src/main/res/drawable/ic_arrow_back_black_24dp.xml delete mode 100644 mifospay/src/main/res/drawable/ic_arrow_back_white_24dp.xml delete mode 100644 mifospay/src/main/res/drawable/ic_bank.xml delete mode 100644 mifospay/src/main/res/drawable/ic_baseline_content_copy_24.xml delete mode 100644 mifospay/src/main/res/drawable/ic_baseline_insert_photo_24.xml delete mode 100644 mifospay/src/main/res/drawable/ic_baseline_share_24.xml delete mode 100644 mifospay/src/main/res/drawable/ic_camera.xml delete mode 100644 mifospay/src/main/res/drawable/ic_cards.xml delete mode 100644 mifospay/src/main/res/drawable/ic_check_round_black_24dp.xml delete mode 100644 mifospay/src/main/res/drawable/ic_close.xml delete mode 100644 mifospay/src/main/res/drawable/ic_contact.xml delete mode 100644 mifospay/src/main/res/drawable/ic_done.xml delete mode 100644 mifospay/src/main/res/drawable/ic_edit.xml delete mode 100644 mifospay/src/main/res/drawable/ic_email.xml delete mode 100644 mifospay/src/main/res/drawable/ic_empty_state.xml delete mode 100644 mifospay/src/main/res/drawable/ic_error_state.xml delete mode 100644 mifospay/src/main/res/drawable/ic_flash_off.xml delete mode 100644 mifospay/src/main/res/drawable/ic_flash_on.xml delete mode 100644 mifospay/src/main/res/drawable/ic_history.xml delete mode 100644 mifospay/src/main/res/drawable/ic_invoice.xml delete mode 100644 mifospay/src/main/res/drawable/ic_invoices.xml delete mode 100644 mifospay/src/main/res/drawable/ic_logo_outline.xml delete mode 100644 mifospay/src/main/res/drawable/ic_merchant.xml delete mode 100644 mifospay/src/main/res/drawable/ic_merchants.xml delete mode 100644 mifospay/src/main/res/drawable/ic_mobile.xml delete mode 100644 mifospay/src/main/res/drawable/ic_next.xml delete mode 100644 mifospay/src/main/res/drawable/ic_next_black.xml delete mode 100644 mifospay/src/main/res/drawable/ic_notification.xml delete mode 100644 mifospay/src/main/res/drawable/ic_photo_library.xml delete mode 100644 mifospay/src/main/res/drawable/ic_remove.xml delete mode 100644 mifospay/src/main/res/drawable/ic_remove_circle_outline_black_24dp.xml delete mode 100644 mifospay/src/main/res/drawable/ic_repeat.xml delete mode 100644 mifospay/src/main/res/drawable/ic_repeat_selector.xml delete mode 100644 mifospay/src/main/res/drawable/ic_request.xml delete mode 100644 mifospay/src/main/res/drawable/ic_request_selector.xml delete mode 100644 mifospay/src/main/res/drawable/ic_right_arrow.xml delete mode 100644 mifospay/src/main/res/drawable/ic_save.xml delete mode 100644 mifospay/src/main/res/drawable/ic_saved_cards.xml delete mode 100644 mifospay/src/main/res/drawable/ic_search.xml delete mode 100644 mifospay/src/main/res/drawable/ic_send.xml delete mode 100644 mifospay/src/main/res/drawable/ic_send_selector.xml delete mode 100644 mifospay/src/main/res/drawable/ic_setting.xml delete mode 100644 mifospay/src/main/res/drawable/ic_share.xml delete mode 100644 mifospay/src/main/res/drawable/ic_tick.xml delete mode 100644 mifospay/src/main/res/drawable/ic_transaction.xml delete mode 100644 mifospay/src/main/res/drawable/ic_verify.xml delete mode 100644 mifospay/src/main/res/drawable/layout_rounded_edge.xml delete mode 100644 mifospay/src/main/res/drawable/qrcode_black.xml delete mode 100644 mifospay/src/main/res/drawable/qrcode_black_selector.xml delete mode 100644 mifospay/src/main/res/drawable/qrcode_blue.xml delete mode 100644 mifospay/src/main/res/drawable/qrcode_blue_selector.xml delete mode 100644 mifospay/src/main/res/drawable/shape_bottom_sheet_dialog_grip.xml delete mode 100644 mifospay/src/main/res/drawable/sim_card_selected.xml delete mode 100644 mifospay/src/main/res/drawable/sim_card_unselected.xml delete mode 100644 mifospay/src/main/res/drawable/transfer_failure.xml delete mode 100644 mifospay/src/main/res/drawable/transfer_success.xml diff --git a/.github/workflows/master_dev_ci.yml b/.github/workflows/master_dev_ci.yml index 3c98cf461..52c415509 100644 --- a/.github/workflows/master_dev_ci.yml +++ b/.github/workflows/master_dev_ci.yml @@ -1,158 +1,144 @@ name: Mobile-Wallet CI[Master/Dev] on: - pull_request: push: - branches: - - 'dev' - - 'master' - - 'payment_hub' + branches: [ dev, master, payment_hub ] + pull_request: + +concurrency: + group: build-${{ github.ref }} + cancel-in-progress: true jobs: - build: - name: Build APK + setup: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - # Set up JDK - - name: Set Up JDK 17 - uses: actions/setup-java@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: + distribution: 'zulu' java-version: 17 + - uses: gradle/actions/setup-gradle@v4 - # 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 - -# Turing off detekt check until migration finished -# - name: Check Dependency Guard -# id: dependencyguard_verify -# continue-on-error: true -# run: ./gradlew dependencyGuard -# -# - name: Prevent updating Dependency Guard baselines if this is a fork -# id: checkfork_dependencyguard -# continue-on-error: false -# if: steps.dependencyguard_verify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository -# run: | -# echo "::error::Dependency Guard failed, please update baselines with: ./gradlew dependencyGuardBaseline" && exit 1 - - # Build App - - name: Build with Gradle - run: ./gradlew assemble - - # Upload Built APK - - name: Upload Build Artifacts - uses: actions/upload-artifact@v2.2.0 + - name: Cache Gradle and build outputs + uses: actions/cache@v4 with: - name: mobile-wallet - path: mifospay/build/outputs/apk/debug/ - -# Turing off detekt check until migration finished -# lintCheck: -# name: Static Analysis -# runs-on: ubuntu-latest -# steps: -# - uses: actions/checkout@v2 -# -# # Setup JDK 17 -# - name: Setup JDK 17 -# uses: actions/setup-java@v1 -# with: -# java-version: 17 -# -# - name: Detekt For All Modules -# run: ./gradlew detekt - - pmd: - name: PMD + path: | + ~/.gradle/caches + ~/.gradle/wrapper + build + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-gradle- + + checks: + needs: setup runs-on: ubuntu-latest + strategy: + matrix: + check: [ build_logic, spotless, detekt ] steps: - - uses: actions/checkout@v2 - - # Setup JDK 17 - - name: Setup JDK 17 - uses: actions/setup-java@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: + distribution: 'zulu' java-version: 17 - - - uses: actions/checkout@v4 - - name: PMD Check[MifosPay] - run: ./gradlew mifospay:pmd - - - name: Upload PMD Report[MifosPay] - uses: actions/upload-artifact@v3.1.3 - if: failure() + - name: Run ${{ matrix.check }} + id: run_check + run: | + if [ "${{ matrix.check }}" = "build_logic" ]; then + ./gradlew check -p build-logic + elif [ "${{ matrix.check }}" = "spotless" ]; then + ./gradlew spotlessCheck --no-configuration-cache --no-daemon + elif [ "${{ matrix.check }}" = "detekt" ]; then + ./gradlew detekt + fi + + - name: Upload Detekt Reports + if: ${{ matrix.check }} == 'detekt' && steps.run_check.outcome == 'success' + uses: actions/upload-artifact@v4 with: - name: PMD Report[MifosPay] - path: mifospay/build/reports/ - - - name: PMD Check[Core:Datastore] - run: ./gradlew core:datastore:pmd - - - name: PMD Check[Core:Data] - run: ./gradlew core:data:pmd - - - name: PMD Check[Core:DesignSystem] - run: ./gradlew core:designsystem:pmd - - - name: PMD Check[Core:Common] - run: ./gradlew core:common:pmd - - - name: PMD Check[Core:Network] - run: ./gradlew core:network:pmd - - - name: PMD Check[Core:Model] - run: ./gradlew core:model:pmd + name: detekt-reports + path: | + **/build/reports/detekt/detekt.md - - name: PMD Check[Feature:Auth] - run: ./gradlew feature:auth:pmd - checkstyle: - name: Checkstyle + dependency_guard: + needs: setup runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - # Setup JDK 17 - - name: Setup JDK 17 - uses: actions/setup-java@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 with: + distribution: 'zulu' java-version: 17 - - uses: actions/checkout@v2 - - name: Checkstyle[MifosPay] - run: ./gradlew mifospay:checkstyle - - - name: Upload Checkstyle Report[MifosPay] - uses: actions/upload-artifact@v2.2.0 - if: failure() + - name: Check Dependency Guard + id: dependencyguard_verify + continue-on-error: true + run: ./gradlew dependencyGuard + + - name: Prevent updating Dependency Guard baselines if this is a fork + id: checkfork_dependencyguard + continue-on-error: false + if: steps.dependencyguard_verify.outcome == 'failure' && github.event.pull_request.head.repo.full_name != github.repository + run: | + echo "::error::Dependency Guard failed, please update baselines with: ./gradlew dependencyGuardBaseline" && exit 1 + + # Runs if previous job failed + - name: Generate new Dependency Guard baselines if verification failed and it's a PR + id: dependencyguard_baseline + if: steps.dependencyguard_verify.outcome == 'failure' && github.event_name == 'pull_request' + run: | + ./gradlew dependencyGuardBaseline + + - name: Push new Dependency Guard baselines if available + uses: stefanzweifel/git-auto-commit-action@v5 + if: steps.dependencyguard_baseline.outcome == 'success' with: - name: Checkstyle Report[MifosPay] - path: mifospay/build/reports/ + file_pattern: '**/dependencies/*.txt' + disable_globbing: true + commit_message: "🤖 Updates baselines for Dependency Guard" - - name: Static Analysis[Core:Datastore] - run: ./gradlew core:datastore:checkstyle - - name: Static Analysis[Core:Data] - run: ./gradlew core:data:checkstyle + tests_and_lint: + needs: setup + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 17 + - name: Run tests + run: | + ./gradlew testDemoDebug + - name: Upload reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-and-lint-reports + path: | + **/build/test-results/test*UnitTest/**.xml - - name: Static Analysis[Core:DesignSystem] - run: ./gradlew core:designsystem:checkstyle + build: + needs: [ checks, tests_and_lint ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 17 - - name: Static Analysis[Core:Common] - run: ./gradlew core:common:checkstyle + - name: Build APKs + run: ./gradlew :app:assemble - - name: Static Analysis[Core:Network] - run: ./gradlew core:network:checkstyle + - name: Check badging + run: ./gradlew :app:checkProdReleaseBadging - - name: Static Analysis[Core:Model] - run: ./gradlew core:model:checkstyle + - name: Upload APKs + uses: actions/upload-artifact@v4 + with: + name: APKs + path: '**/build/outputs/apk/**/*.apk' - - name: Static Analysis[Feature:Auth] - run: ./gradlew feature:auth:checkstyle \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index c480a08d7..981f2fe68 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,9 +36,6 @@ val detektFormatting = libs.detekt.formatting val twitterComposeRules = libs.twitter.detekt.compose val ktlintVersion = "1.0.1" -val reportMerge by tasks.registering(io.gitlab.arturbosch.detekt.report.ReportMergeTask::class) { - output.set(rootProject.layout.buildDirectory.file("reports/detekt/merge.html")) // or "reports/detekt/merge.sarif" -} subprojects { apply { @@ -49,7 +46,7 @@ subprojects { tasks.withType().configureEach { config.from(rootProject.files("config/detekt/detekt.yml")) reports.xml.required.set(true) - finalizedBy(reportMerge) + reports.html.required.set(true) } extensions.configure { @@ -77,12 +74,6 @@ subprojects { } } - reportMerge { - input.from(tasks.withType().map { - it.htmlReportFile } - ) - } - dependencies { detektPlugins(detektFormatting) detektPlugins(twitterComposeRules) diff --git a/core/data/src/main/java/org/mifospay/core/data/repository/auth/AuthenticationUserRepository.kt b/core/data/src/main/java/org/mifospay/core/data/repository/auth/AuthenticationUserRepository.kt index 0f5774a03..266f7f9c4 100644 --- a/core/data/src/main/java/org/mifospay/core/data/repository/auth/AuthenticationUserRepository.kt +++ b/core/data/src/main/java/org/mifospay/core/data/repository/auth/AuthenticationUserRepository.kt @@ -16,17 +16,21 @@ import org.mifospay.core.datastore.PreferencesHelper import javax.inject.Inject class AuthenticationUserRepository @Inject constructor( - preferencesHelper: PreferencesHelper, + private val preferencesHelper: PreferencesHelper, ) : UserDataRepository { override val userData: Flow = flow { emit( UserData( - isAuthenticated = !preferencesHelper.token.isNullOrBlank(), + isAuthenticated = !preferencesHelper.token.isNullOrEmpty(), userName = preferencesHelper.username, // user = preferencesHelper.user, clientId = preferencesHelper.clientId, ), ) } + + override fun logOut() { + preferencesHelper.clear() + } } diff --git a/core/data/src/main/java/org/mifospay/core/data/repository/auth/UserDataRepository.kt b/core/data/src/main/java/org/mifospay/core/data/repository/auth/UserDataRepository.kt index 96fc5ad3a..5241ba9ab 100644 --- a/core/data/src/main/java/org/mifospay/core/data/repository/auth/UserDataRepository.kt +++ b/core/data/src/main/java/org/mifospay/core/data/repository/auth/UserDataRepository.kt @@ -17,4 +17,6 @@ interface UserDataRepository { * Stream of [UserData] */ val userData: Flow + + fun logOut(): Unit } diff --git a/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/component/LoadingWheel.kt b/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/component/LoadingWheel.kt index 9d35fac24..db89435de 100644 --- a/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/component/LoadingWheel.kt +++ b/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/component/LoadingWheel.kt @@ -97,8 +97,8 @@ fun MifosLoadingWheel( animationSpec = infiniteRepeatable( animation = keyframes { durationMillis = ROTATION_TIME / 2 - progressLineColor at ROTATION_TIME / NUM_OF_LINES / 2 with LinearEasing - baseLineColor at ROTATION_TIME / NUM_OF_LINES with LinearEasing + progressLineColor at ROTATION_TIME / NUM_OF_LINES / 2 using LinearEasing + baseLineColor at ROTATION_TIME / NUM_OF_LINES using LinearEasing }, repeatMode = RepeatMode.Restart, initialStartOffset = StartOffset(ROTATION_TIME / NUM_OF_LINES / 2 * index), diff --git a/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/component/MifosTopBar.kt b/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/component/MifosTopBar.kt index da6ff044e..63fa5ea20 100644 --- a/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/component/MifosTopBar.kt +++ b/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/component/MifosTopBar.kt @@ -10,8 +10,6 @@ package org.mifospay.core.designsystem.component import androidx.compose.foundation.layout.RowScope -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -22,6 +20,7 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import org.mifospay.core.designsystem.icon.MifosIcons @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -42,7 +41,7 @@ fun MifosTopBar( navigationIcon = { IconButton(onClick = { backPress.invoke() }) { Icon( - imageVector = Icons.Filled.ArrowBack, + imageVector = MifosIcons.ArrowBack, contentDescription = "Back", tint = MaterialTheme.colorScheme.onSurface, ) diff --git a/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/theme/Theme.kt b/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/theme/Theme.kt index 5fa7b0ae2..2562a413b 100644 --- a/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/theme/Theme.kt +++ b/core/designsystem/src/main/kotlin/org/mifospay/core/designsystem/theme/Theme.kt @@ -81,12 +81,9 @@ private val DarkDefaultColorScheme = darkColorScheme( scrim = md_theme_dark_scrim, ) -@Suppress("UnusedParameter") @Composable fun MifosTheme( darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, content: @Composable () -> Unit, ) { // Color scheme diff --git a/core/ui/src/main/kotlin/org/mifospay/core/ui/ExpiryDateInput.kt b/core/ui/src/main/kotlin/org/mifospay/core/ui/ExpiryDateInput.kt index 0fd2cc515..a758f3bc6 100644 --- a/core/ui/src/main/kotlin/org/mifospay/core/ui/ExpiryDateInput.kt +++ b/core/ui/src/main/kotlin/org/mifospay/core/ui/ExpiryDateInput.kt @@ -45,7 +45,7 @@ fun ExpiryDateInput( onDone: () -> Unit, modifier: Modifier = Modifier, ) { - val (a, b, c) = FocusRequester.createRefs() + val (b, c) = FocusRequester.createRefs() Row( modifier = modifier .fillMaxWidth() diff --git a/core/ui/src/main/kotlin/org/mifospay/core/ui/FaqItemScreen.kt b/core/ui/src/main/kotlin/org/mifospay/core/ui/FaqItemScreen.kt index 6072ad5fc..af565f2d6 100644 --- a/core/ui/src/main/kotlin/org/mifospay/core/ui/FaqItemScreen.kt +++ b/core/ui/src/main/kotlin/org/mifospay/core/ui/FaqItemScreen.kt @@ -21,7 +21,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowDropDown -import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -93,6 +93,6 @@ fun FaqItemScreen( ) } - Divider() + HorizontalDivider() } } diff --git a/core/ui/src/main/kotlin/org/mifospay/core/ui/MifosUserImage.kt b/core/ui/src/main/kotlin/org/mifospay/core/ui/MifosUserImage.kt index 47d265373..84f4ad55e 100644 --- a/core/ui/src/main/kotlin/org/mifospay/core/ui/MifosUserImage.kt +++ b/core/ui/src/main/kotlin/org/mifospay/core/ui/MifosUserImage.kt @@ -30,7 +30,7 @@ fun MifosUserImage( if (bitmap == null) { MifosTextUserImage( text = username?.firstOrNull()?.toString() ?: "J", - modifier = modifier + modifier = modifier, ) } else { Image( diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts index 4c039b97e..af6587d32 100644 --- a/desktop/build.gradle.kts +++ b/desktop/build.gradle.kts @@ -17,7 +17,7 @@ plugins { kotlin { jvm { - jvmToolchain(17) + jvmToolchain(21) withJava() } diff --git a/feature/auth/build.gradle.kts b/feature/auth/build.gradle.kts index 3914d6d07..ed63d8f61 100644 --- a/feature/auth/build.gradle.kts +++ b/feature/auth/build.gradle.kts @@ -23,7 +23,6 @@ apply(from = "${project.rootDir}/config/quality/quality.gradle") dependencies { implementation(projects.core.data) - implementation(projects.feature.passcode) implementation(libs.compose.country.code.picker) // TODO:: this should be removed @@ -36,14 +35,5 @@ dependencies { implementation(libs.androidx.credentials.play.services.auth) implementation(libs.googleid) - implementation(libs.mifosPasscode) - implementation(libs.play.services.auth) - - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) - implementation(libs.material) - testImplementation(libs.junit) - androidTestImplementation(libs.androidx.test.ext.junit) - androidTestImplementation(libs.espresso.core) } \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginActivity.kt b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginActivity.kt deleted file mode 100644 index 57e4d4e5b..000000000 --- a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginActivity.kt +++ /dev/null @@ -1,28 +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.feature.auth.login - -import android.os.Bundle -import androidx.activity.compose.setContent -import androidx.appcompat.app.AppCompatActivity -import dagger.hilt.android.AndroidEntryPoint -import org.mifospay.core.designsystem.theme.MifosTheme - -@AndroidEntryPoint -class LoginActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContent { - MifosTheme { - LoginScreen() - } - } - } -} diff --git a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginScreen.kt b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginScreen.kt index 6f253b7d0..03ae92473 100644 --- a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginScreen.kt +++ b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginScreen.kt @@ -9,7 +9,6 @@ */ package org.mifospay.feature.auth.login -import android.content.Context import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -19,6 +18,7 @@ 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.padding import androidx.compose.foundation.rememberScrollState @@ -48,10 +48,8 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.core.os.bundleOf import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.mifos.mobile.passcode.utils.PassCodeConstants import org.mifospay.core.designsystem.component.MfOverlayLoadingWheel import org.mifospay.core.designsystem.component.MifosOutlinedTextField import org.mifospay.core.designsystem.theme.MifosTheme @@ -59,10 +57,10 @@ import org.mifospay.core.designsystem.theme.grey import org.mifospay.core.designsystem.theme.styleNormal18sp import org.mifospay.feature.auth.R import org.mifospay.feature.auth.socialSignup.SocialSignupMethodContentScreen -import org.mifospay.feature.passcode.PassCodeActivity @Composable internal fun LoginScreen( + navigateToPasscodeScreen: () -> Unit, modifier: Modifier = Modifier, viewModel: LoginViewModel = hiltViewModel(), ) { @@ -70,10 +68,6 @@ internal fun LoginScreen( val showProgress by viewModel.showProgress.collectAsStateWithLifecycle() val isLoginSuccess by viewModel.isLoginSuccess.collectAsStateWithLifecycle() - if (viewModel.isPassCodeExist) { - startPassCodeActivity(context) - } - LoginScreenContent( modifier = modifier, showProgress = showProgress, @@ -89,7 +83,7 @@ internal fun LoginScreen( ) if (isLoginSuccess) { - startPassCodeActivity(context) + navigateToPasscodeScreen() } } @@ -120,11 +114,14 @@ private fun LoginScreenContent( } } - Box(modifier) { + Box( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.surface), + ) { Column( modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.surface) + .fillMaxSize() .verticalScroll(rememberScrollState()) .padding(top = 100.dp, start = 48.dp, end = 48.dp), horizontalAlignment = Alignment.Start, @@ -240,16 +237,6 @@ private fun LoginScreenContent( } } -/** - * Starts [PassCodeActivity] with `Constans.INTIAL_LOGIN` as true - */ -private fun startPassCodeActivity(context: Context) { - PassCodeActivity.startPassCodeActivity( - context = context, - bundle = bundleOf(Pair(PassCodeConstants.PASSCODE_INITIAL_LOGIN, true)), - ) -} - @Preview(showSystemUi = true, device = "id:pixel_5") @Composable private fun LoanScreenPreview() { diff --git a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginViewModel.kt b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginViewModel.kt index 509514d04..6ecde19a8 100644 --- a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginViewModel.kt +++ b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/login/LoginViewModel.kt @@ -11,7 +11,7 @@ package org.mifospay.feature.auth.login import android.util.Log import androidx.lifecycle.ViewModel -import com.mifos.mobile.passcode.utils.PasscodePreferencesHelper +import com.mifospay.core.model.domain.client.Client import com.mifospay.core.model.domain.user.User import com.mifospay.core.model.entity.UserWithRole import dagger.hilt.android.lifecycle.HiltViewModel @@ -28,12 +28,11 @@ import javax.inject.Inject @HiltViewModel class LoginViewModel @Inject constructor( - private val mUsecaseHandler: UseCaseHandler, + private val mUseCaseHandler: UseCaseHandler, private val authenticateUserUseCase: AuthenticateUser, private val fetchClientDataUseCase: FetchClientData, private val fetchUserDetailsUseCase: FetchUserDetails, private val preferencesHelper: PreferencesHelper, - private val passcodePreferencesHelper: PasscodePreferencesHelper, ) : ViewModel() { private val _showProgress = MutableStateFlow(false) @@ -42,8 +41,6 @@ class LoginViewModel @Inject constructor( private val _isLoginSuccess = MutableStateFlow(false) val isLoginSuccess: StateFlow = _isLoginSuccess - val isPassCodeExist = passcodePreferencesHelper.passCode.isNotEmpty() - fun updateProgressState(isVisible: Boolean) { _showProgress.update { isVisible } } @@ -68,7 +65,7 @@ class LoginViewModel @Inject constructor( AuthenticateUser.RequestValues(username, password) val requestValue = authenticateUserUseCase.walletRequestValues - mUsecaseHandler.execute( + mUseCaseHandler.execute( authenticateUserUseCase, requestValue, object : UseCaseCallback { @@ -91,7 +88,7 @@ class LoginViewModel @Inject constructor( * @param user */ private fun fetchUserDetails(user: User) { - mUsecaseHandler.execute( + mUseCaseHandler.execute( fetchUserDetailsUseCase, FetchUserDetails.RequestValues(user.userId), object : UseCaseCallback { @@ -113,7 +110,7 @@ class LoginViewModel @Inject constructor( * @param user */ private fun fetchClientData(user: User) { - mUsecaseHandler.execute( + mUseCaseHandler.execute( fetchClientDataUseCase, FetchClientData.RequestValues(user.clients.firstOrNull()), object : UseCaseCallback { @@ -154,7 +151,7 @@ class LoginViewModel @Inject constructor( /** * TODO remove name, clientId and mobileNo from pref and use from saved Client */ - private fun saveClientDetails(client: com.mifospay.core.model.domain.client.Client?) { + private fun saveClientDetails(client: Client?) { preferencesHelper.saveFullName(client?.name) preferencesHelper.clientId = client?.clientId!! preferencesHelper.saveMobile(client.mobileNo) diff --git a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/navigation/LoginScreenNavigation.kt b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/navigation/LoginScreenNavigation.kt index a4ec2ab35..3bf537c10 100644 --- a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/navigation/LoginScreenNavigation.kt +++ b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/navigation/LoginScreenNavigation.kt @@ -16,16 +16,11 @@ import org.mifospay.feature.auth.login.LoginScreen const val LOGIN_ROUTE = "login_route" -@Suppress("UnusedParameter") fun NavGraphBuilder.loginScreen( - onDismissSignUp: () -> Unit, - onNavigateToMobileVerificationScreen: (Int, String, String, String, String) -> Unit, + onNavigateToPasscodeScreen: () -> Unit, ) { composable(route = LOGIN_ROUTE) { - LoginScreen( -// onDismissSignUp = onDismissSignUp, -// onNavigateToMobileVerificationScreen = onNavigateToMobileVerificationScreen - ) + LoginScreen(navigateToPasscodeScreen = onNavigateToPasscodeScreen) } } diff --git a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/signup/SignupScreen.kt b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/signup/SignupScreen.kt index 2ea88eedb..76bc47ae9 100644 --- a/feature/auth/src/main/kotlin/org/mifospay/feature/auth/signup/SignupScreen.kt +++ b/feature/auth/src/main/kotlin/org/mifospay/feature/auth/signup/SignupScreen.kt @@ -140,19 +140,19 @@ private fun SignupScreenContent( fun validateAllFields() { val isAnyFieldEmpty = firstName.isEmpty() || - lastName.isEmpty() || - email.isEmpty() || - userName.isEmpty() || - addressLine1.isEmpty() || - addressLine2.isEmpty() || - pinCode.isEmpty() || - password.isEmpty() || - confirmPassword.isEmpty() || - selectedState == null + lastName.isEmpty() || + email.isEmpty() || + userName.isEmpty() || + addressLine1.isEmpty() || + addressLine2.isEmpty() || + pinCode.isEmpty() || + password.isEmpty() || + confirmPassword.isEmpty() || + selectedState == null val isNameOfBusinessEmpty = data.mifosSavingsProductId == MIFOS_MERCHANT_SAVINGS_PRODUCT_ID && - nameOfBusiness.isEmpty() + nameOfBusiness.isEmpty() if (!email.isValidEmail()) { Toast @@ -195,17 +195,17 @@ private fun SignupScreenContent( Box(modifier) { Column( modifier = - Modifier - .fillMaxSize() - .background(color = MaterialTheme.colorScheme.surface) - .verticalScroll(rememberScrollState()) - .focusable(!showProgressState), + Modifier + .fillMaxSize() + .background(color = MaterialTheme.colorScheme.surface) + .verticalScroll(rememberScrollState()) + .focusable(!showProgressState), ) { Column( modifier = - Modifier - .fillMaxWidth() - .background(color = MaterialTheme.colorScheme.primary), + Modifier + .fillMaxWidth() + .background(color = MaterialTheme.colorScheme.primary), verticalArrangement = Arrangement.Top, ) { Text( @@ -215,12 +215,12 @@ private fun SignupScreenContent( ) Text( modifier = - Modifier.padding( - top = 4.dp, - bottom = 32.dp, - start = 24.dp, - end = 24.dp, - ), + Modifier.padding( + top = 4.dp, + bottom = 32.dp, + start = 24.dp, + end = 24.dp, + ), text = stringResource(id = R.string.feature_auth_all_fields_are_mandatory), style = MaterialTheme.typography.bodySmall.copy(color = Color.White), ) @@ -228,16 +228,16 @@ private fun SignupScreenContent( Column( modifier = - Modifier - .fillMaxWidth() - .padding(horizontal = 32.dp) - .focusable(!showProgressState), + Modifier + .fillMaxWidth() + .padding(horizontal = 32.dp) + .focusable(!showProgressState), ) { UserInfoTextField( modifier = - Modifier - .fillMaxWidth() - .padding(top = 16.dp), + Modifier + .fillMaxWidth() + .padding(top = 16.dp), label = stringResource(id = R.string.feature_auth_first_name), value = firstName, ) { @@ -245,9 +245,9 @@ private fun SignupScreenContent( } UserInfoTextField( modifier = - Modifier - .fillMaxWidth() - .padding(top = 8.dp), + Modifier + .fillMaxWidth() + .padding(top = 8.dp), label = stringResource(id = R.string.feature_auth_last_name), value = lastName, ) { @@ -255,9 +255,9 @@ private fun SignupScreenContent( } UserInfoTextField( modifier = - Modifier - .fillMaxWidth() - .padding(top = 8.dp), + Modifier + .fillMaxWidth() + .padding(top = 8.dp), label = stringResource(id = R.string.feature_auth_username), value = userName, ) { @@ -277,9 +277,9 @@ private fun SignupScreenContent( ) UserInfoTextField( modifier = - Modifier - .fillMaxWidth() - .padding(top = 8.dp), + Modifier + .fillMaxWidth() + .padding(top = 8.dp), label = stringResource(id = R.string.feature_auth_email), value = email, ) { @@ -288,9 +288,9 @@ private fun SignupScreenContent( if (data.mifosSavingsProductId == MIFOS_MERCHANT_SAVINGS_PRODUCT_ID) { UserInfoTextField( modifier = - Modifier - .fillMaxWidth() - .padding(top = 8.dp), + Modifier + .fillMaxWidth() + .padding(top = 8.dp), label = stringResource(id = R.string.feature_auth_name_of_business), value = nameOfBusiness, ) { @@ -299,9 +299,9 @@ private fun SignupScreenContent( } UserInfoTextField( modifier = - Modifier - .fillMaxWidth() - .padding(top = 8.dp), + Modifier + .fillMaxWidth() + .padding(top = 8.dp), label = stringResource(id = R.string.feature_auth_address_line_1), value = addressLine1, ) { @@ -309,9 +309,9 @@ private fun SignupScreenContent( } UserInfoTextField( modifier = - Modifier - .fillMaxWidth() - .padding(top = 8.dp), + Modifier + .fillMaxWidth() + .padding(top = 8.dp), label = stringResource(id = R.string.feature_auth_address_line_2), value = addressLine2, ) { @@ -335,9 +335,9 @@ private fun SignupScreenContent( HorizontalDivider(thickness = 24.dp, color = Color.White) Button( modifier = - Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), + Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), enabled = true, onClick = { @@ -446,13 +446,13 @@ private fun PasswordAndConfirmPassword( onPasswordChange = onPasswordChange, modifier = Modifier.fillMaxWidth(), errorMessage = - if (password.isEmpty()) { - stringResource(id = R.string.feature_auth_password_cannot_be_empty) - } else if (password.length < 6) { - stringResource(id = R.string.feature_auth_password_must_be_least_6_characters) - } else { - null - }, + if (password.isEmpty()) { + stringResource(id = R.string.feature_auth_password_cannot_be_empty) + } else if (password.length < 6) { + stringResource(id = R.string.feature_auth_password_must_be_least_6_characters) + } else { + null + }, ) MfPasswordTextField( password = confirmPassword, @@ -463,13 +463,13 @@ private fun PasswordAndConfirmPassword( onPasswordChange = onConfirmPasswordChange, modifier = Modifier.fillMaxWidth(), errorMessage = - if (confirmPassword.isEmpty()) { - stringResource(id = R.string.feature_auth_confirm_password_cannot_empty) - } else if (password != confirmPassword) { - stringResource(id = R.string.feature_auth_passwords_do_not_match) - } else { - null - }, + if (confirmPassword.isEmpty()) { + stringResource(id = R.string.feature_auth_confirm_password_cannot_empty) + } else if (password != confirmPassword) { + stringResource(id = R.string.feature_auth_passwords_do_not_match) + } else { + null + }, ) if (password.length >= 6) { Text( diff --git a/feature/home/src/main/kotlin/org/mifospay/feature/home/HomeScreen.kt b/feature/home/src/main/kotlin/org/mifospay/feature/home/HomeScreen.kt index 419fd9f4a..d3ad4d895 100644 --- a/feature/home/src/main/kotlin/org/mifospay/feature/home/HomeScreen.kt +++ b/feature/home/src/main/kotlin/org/mifospay/feature/home/HomeScreen.kt @@ -16,9 +16,11 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -108,9 +110,9 @@ private fun HomeScreen( ) { LazyColumn( modifier = modifier - .fillMaxWidth() - .background(color = MaterialTheme.colorScheme.surface) - .padding(start = 32.dp, end = 32.dp), + .fillMaxSize() + .background(color = MaterialTheme.colorScheme.surface), + contentPadding = PaddingValues(start = 16.dp, end = 16.dp), ) { item { MifosWalletCardScreen(account = account) diff --git a/feature/home/src/main/kotlin/org/mifospay/feature/home/navigation/HomeNavigation.kt b/feature/home/src/main/kotlin/org/mifospay/feature/home/navigation/HomeNavigation.kt index aa44e66ae..ee30ef0b6 100644 --- a/feature/home/src/main/kotlin/org/mifospay/feature/home/navigation/HomeNavigation.kt +++ b/feature/home/src/main/kotlin/org/mifospay/feature/home/navigation/HomeNavigation.kt @@ -17,7 +17,7 @@ import org.mifospay.feature.home.HomeRoute const val HOME_ROUTE = "home_route" -fun NavController.navigateToHome(navOptions: NavOptions) = navigate(HOME_ROUTE, navOptions) +fun NavController.navigateToHome(navOptions: NavOptions? = null) = navigate(HOME_ROUTE, navOptions) fun NavGraphBuilder.homeScreen( onRequest: (String) -> Unit, diff --git a/feature/kyc/src/main/kotlin/org/mifospay/feature/kyc/KYCLevel2Screen.kt b/feature/kyc/src/main/kotlin/org/mifospay/feature/kyc/KYCLevel2Screen.kt index 99ec520f8..610dcef1e 100644 --- a/feature/kyc/src/main/kotlin/org/mifospay/feature/kyc/KYCLevel2Screen.kt +++ b/feature/kyc/src/main/kotlin/org/mifospay/feature/kyc/KYCLevel2Screen.kt @@ -139,13 +139,13 @@ private fun Kyc2Form( mutableStateOf( if (SDK_INT >= 33) { ContextCompat.checkSelfPermission(context, Manifest.permission.READ_MEDIA_IMAGES) == - PackageManager.PERMISSION_GRANTED + PackageManager.PERMISSION_GRANTED } else { ContextCompat.checkSelfPermission( context, Manifest.permission.READ_EXTERNAL_STORAGE, ) == - PackageManager.PERMISSION_GRANTED + PackageManager.PERMISSION_GRANTED }, ) } diff --git a/feature/merchants/src/main/kotlin/org/mifospay/feature/merchants/ui/MerchantTransferScreen.kt b/feature/merchants/src/main/kotlin/org/mifospay/feature/merchants/ui/MerchantTransferScreen.kt index 8d3cf269d..2f9f471dd 100644 --- a/feature/merchants/src/main/kotlin/org/mifospay/feature/merchants/ui/MerchantTransferScreen.kt +++ b/feature/merchants/src/main/kotlin/org/mifospay/feature/merchants/ui/MerchantTransferScreen.kt @@ -209,9 +209,9 @@ private fun MerchantBottomSheet( content = { Column( modifier = - Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 24.dp), + Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 24.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { Text( @@ -292,12 +292,12 @@ private fun MerchantInitialAvatar( Box( modifier = - modifier - .size(86.dp) - .background( - color = MaterialTheme.colorScheme.primary, - shape = CircleShape, - ), + modifier + .size(86.dp) + .background( + color = MaterialTheme.colorScheme.primary, + shape = CircleShape, + ), contentAlignment = Alignment.Center, ) { Text( @@ -346,11 +346,11 @@ private fun SpecificTransactionItem( ) Text( text = - when (transaction.transactionType) { - TransactionType.DEBIT -> stringResource(id = R.string.feature_merchants_debits) - TransactionType.CREDIT -> stringResource(id = R.string.feature_merchants_credits) - TransactionType.OTHER -> stringResource(id = R.string.feature_merchants_other) - }, + when (transaction.transactionType) { + TransactionType.DEBIT -> stringResource(id = R.string.feature_merchants_debits) + TransactionType.CREDIT -> stringResource(id = R.string.feature_merchants_credits) + TransactionType.OTHER -> stringResource(id = R.string.feature_merchants_other) + }, style = MaterialTheme.typography.bodyLarge, ) } @@ -359,11 +359,11 @@ private fun SpecificTransactionItem( text = "${transaction.currency.code}${transaction.amount}", style = MaterialTheme.typography.displaySmall, color = - when (transaction.transactionType) { - TransactionType.DEBIT -> debitTextColor - TransactionType.CREDIT -> creditTextColor - TransactionType.OTHER -> otherTextColor - }, + when (transaction.transactionType) { + TransactionType.DEBIT -> debitTextColor + TransactionType.CREDIT -> creditTextColor + TransactionType.OTHER -> otherTextColor + }, ) } } @@ -378,9 +378,9 @@ private fun SpecificTransactionAccountInfo( ) { Column( modifier = - modifier.clickable { - accountClicked(account.accountNo) - }, + modifier.clickable { + accountClicked(account.accountNo) + }, horizontalAlignment = Alignment.CenterHorizontally, ) { Icon(imageVector = MifosIcons.AccountCircle, contentDescription = null) diff --git a/feature/passcode/build.gradle.kts b/feature/passcode/build.gradle.kts index a97343107..9a6912f04 100644 --- a/feature/passcode/build.gradle.kts +++ b/feature/passcode/build.gradle.kts @@ -16,11 +16,6 @@ android { namespace = "org.mifos.mobilewallet.mifospay.feature.passcode" } -apply(from = "${project.rootDir}/config/quality/quality.gradle") - dependencies { - implementation(projects.core.data) implementation(libs.androidx.core.ktx) - implementation(libs.androidx.appcompat) - implementation(libs.mifosPasscode) } diff --git a/feature/passcode/src/main/AndroidManifest.xml b/feature/passcode/src/main/AndroidManifest.xml index 961389810..b9b046d65 100644 --- a/feature/passcode/src/main/AndroidManifest.xml +++ b/feature/passcode/src/main/AndroidManifest.xml @@ -9,5 +9,5 @@ See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md --> - + \ No newline at end of file diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PassCodeActivity.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PassCodeActivity.kt deleted file mode 100644 index 96371003a..000000000 --- a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PassCodeActivity.kt +++ /dev/null @@ -1,128 +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.feature.passcode - -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.view.View -import android.widget.Toast -import androidx.activity.OnBackPressedCallback -import androidx.appcompat.app.AlertDialog -import com.mifos.mobile.passcode.MifosPassCodeActivity -import com.mifos.mobile.passcode.utils.EncryptionUtil -import com.mifos.mobile.passcode.utils.PassCodeConstants -import com.mifos.mobile.passcode.utils.PasscodePreferencesHelper -import dagger.hilt.android.AndroidEntryPoint -import org.mifos.mobilewallet.mifospay.feature.passcode.R -import org.mifospay.common.Constants - -@AndroidEntryPoint -class PassCodeActivity : MifosPassCodeActivity() { - - private var deepLinkURI: String? = null - private var currPass: String? = "" - private var updatePassword = false - private var isInitialScreen = false - - companion object { - // We gonna remove it after implementing the Compose Passcode screen and compose navigation - const val MAIN_ACTIVITY = "org.mifospay.MainActivity" - const val LOGIN_ACTIVITY = "org.mifospay.feature.auth.login.LoginActivity" - const val RECEIPT_ACTIVITY = "org.mifospay.receipt.ui.ReceiptActivity" - - fun startPassCodeActivity(context: Context, bundle: Bundle) { - context.startActivity( - Intent(context, PassCodeActivity::class.java).apply { - putExtras(bundle) - }, - ) - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - isInitialScreen = intent.getBooleanExtra( - PassCodeConstants.PASSCODE_INITIAL_LOGIN, false, - ) - if (intent != null) { - currPass = intent.getStringExtra(Constants.CURRENT_PASSCODE) - updatePassword = intent.getBooleanExtra(Constants.UPDATE_PASSCODE, false) - } - - deepLinkURI = intent.getStringExtra("uri") - - onBackPressedDispatcher.addCallback( - this, - object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - saveCurrentPasscode() - finishAffinity() - } - }, - ) - } - - override fun getLogo(): Int { - return 0 - } - - override fun startNextActivity() { - // authenticate user with saved Preferences - if (deepLinkURI != null) { - val uri = Uri.parse(deepLinkURI) - val intent = Intent(this@PassCodeActivity, Class.forName(RECEIPT_ACTIVITY)) - intent.data = uri - startActivity(intent) - } else { - val intent = Intent(this@PassCodeActivity, Class.forName(MAIN_ACTIVITY)) - intent.addFlags( - Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK, - ) - startActivity(intent) - } - } - - override fun startLoginActivity() { - AlertDialog.Builder(this@PassCodeActivity) - .setTitle(R.string.feature_passcode_passcode_title) - .setPositiveButton(R.string.feature_passcode_yes) { _, _ -> - startActivity(Intent(this@PassCodeActivity, Class.forName(LOGIN_ACTIVITY))) - finish() - }.setNegativeButton(R.string.feature_passcode_cancel) { dialog, _ -> dialog.cancel() } - .create() - .show() - } - - override fun showToaster(view: View, msg: Int) { - Toast.makeText(applicationContext, getText(msg), Toast.LENGTH_SHORT).show() - } - - override fun getEncryptionType(): Int { - return EncryptionUtil.DEFAULT - } - - private fun saveCurrentPasscode() { - if (updatePassword && currPass?.isNotEmpty() == true) { - val helper = PasscodePreferencesHelper(this) - helper.savePassCode(currPass) - } - } - - override fun skip(v: View) { - saveCurrentPasscode() - if (isInitialScreen) { - startNextActivity() - } - finish() - } -} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PassCodeScreen.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PassCodeScreen.kt new file mode 100644 index 000000000..5c3edf3f6 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PassCodeScreen.kt @@ -0,0 +1,242 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode + +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.Animatable +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Visibility +import androidx.compose.material.icons.filled.VisibilityOff +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import org.mifospay.feature.passcode.component.MifosIcon +import org.mifospay.feature.passcode.component.PasscodeForgotButton +import org.mifospay.feature.passcode.component.PasscodeHeader +import org.mifospay.feature.passcode.component.PasscodeKeys +import org.mifospay.feature.passcode.component.PasscodeMismatchedDialog +import org.mifospay.feature.passcode.component.PasscodeSkipButton +import org.mifospay.feature.passcode.component.PasscodeToolbar +import org.mifospay.feature.passcode.theme.blueTint +import org.mifospay.feature.passcode.utility.Constants.PASSCODE_LENGTH +import org.mifospay.feature.passcode.utility.PreferenceManager +import org.mifospay.feature.passcode.utility.ShakeAnimation.performShakeAnimation +import org.mifospay.feature.passcode.utility.VibrationFeedback.vibrateFeedback +import org.mifospay.feature.passcode.viewmodels.PasscodeViewModel + +@Composable +internal fun PasscodeScreen( + onForgotButton: () -> Unit, + onSkipButton: () -> Unit, + onPasscodeConfirm: (String) -> Unit, + onPasscodeRejected: () -> Unit, + modifier: Modifier = Modifier, + viewModel: PasscodeViewModel = hiltViewModel(), +) { + val context = LocalContext.current + val preferenceManager = remember { PreferenceManager(context) } + + val activeStep by viewModel.activeStep.collectAsStateWithLifecycle() + val filledDots by viewModel.filledDots.collectAsStateWithLifecycle() + val passcodeVisible by viewModel.passcodeVisible.collectAsStateWithLifecycle() + val currentPasscode by viewModel.currentPasscodeInput.collectAsStateWithLifecycle() + + val xShake = remember { Animatable(initialValue = 0.0F) } + var passcodeRejectedDialogVisible by remember { mutableStateOf(false) } + + LaunchedEffect(key1 = viewModel.onPasscodeConfirmed) { + viewModel.onPasscodeConfirmed.collect { + onPasscodeConfirm(it) + } + } + + LaunchedEffect(key1 = viewModel.onPasscodeRejected) { + viewModel.onPasscodeRejected.collect { + passcodeRejectedDialogVisible = true + vibrateFeedback(context) + performShakeAnimation(xShake) + onPasscodeRejected() + } + } + + Scaffold( + modifier = modifier + .fillMaxSize(), + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .background(Color.White) + .padding(paddingValues), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + PasscodeToolbar(activeStep = activeStep, preferenceManager.hasPasscode) + + PasscodeSkipButton( + hasPassCode = preferenceManager.hasPasscode, + onSkipButton = onSkipButton, + ) + + MifosIcon(modifier = Modifier.fillMaxWidth()) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp, bottom = 24.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + PasscodeHeader( + activeStep = activeStep, + isPasscodeAlreadySet = preferenceManager.hasPasscode, + ) + PasscodeView( + restart = { viewModel.restart() }, + togglePasscodeVisibility = { viewModel.togglePasscodeVisibility() }, + filledDots = filledDots, + passcodeVisible = passcodeVisible, + currentPasscode = currentPasscode, + passcodeRejectedDialogVisible = passcodeRejectedDialogVisible, + onDismissDialog = { passcodeRejectedDialogVisible = false }, + xShake = xShake, + ) + } + + Spacer(modifier = Modifier.height(6.dp)) + + PasscodeKeys( + enterKey = viewModel::enterKey, + deleteKey = viewModel::deleteKey, + deleteAllKeys = viewModel::deleteAllKeys, + modifier = Modifier.padding(horizontal = 12.dp), + ) + + Spacer(modifier = Modifier.height(8.dp)) + + PasscodeForgotButton( + hasPassCode = preferenceManager.hasPasscode, + onForgotButton = onForgotButton, + ) + } + } +} + +@Composable +private fun PasscodeView( + restart: () -> Unit, + togglePasscodeVisibility: () -> Unit, + filledDots: Int, + passcodeVisible: Boolean, + currentPasscode: String, + passcodeRejectedDialogVisible: Boolean, + onDismissDialog: () -> Unit, + xShake: Animatable, + modifier: Modifier = Modifier, +) { + PasscodeMismatchedDialog( + visible = passcodeRejectedDialogVisible, + onDismiss = { + onDismissDialog.invoke() + restart() + }, + ) + + Row( + modifier = modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + Row( + modifier = Modifier.offset { IntOffset(xShake.value.toInt(), 0) }, + horizontalArrangement = Arrangement.spacedBy( + space = 26.dp, + alignment = Alignment.CenterHorizontally, + ), + verticalAlignment = Alignment.CenterVertically, + ) { + repeat(PASSCODE_LENGTH) { dotIndex -> + if (passcodeVisible && dotIndex < currentPasscode.length) { + Text( + text = currentPasscode[dotIndex].toString(), + color = blueTint, + ) + } else { + val isFilledDot = dotIndex + 1 <= filledDots + val dotColor = animateColorAsState( + if (isFilledDot) blueTint else Color.Gray, + label = "", + ) + + Box( + modifier = Modifier + .size(14.dp) + .background( + color = dotColor.value, + shape = CircleShape, + ), + ) + } + } + } + + IconButton( + onClick = togglePasscodeVisibility, + modifier = Modifier.padding(start = 10.dp), + ) { + Icon( + imageVector = if (passcodeVisible) { + Icons.Filled.Visibility + } else { + Icons.Filled.VisibilityOff + }, + contentDescription = null, + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun PasscodeScreenPreview() { + PasscodeScreen( + onForgotButton = {}, + onSkipButton = {}, + onPasscodeConfirm = {}, + onPasscodeRejected = {}, + ) +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PasscodeNavigation.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PasscodeNavigation.kt new file mode 100644 index 000000000..e35e0bfd2 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/PasscodeNavigation.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable + +const val PASSCODE_SCREEN = "passcode_screen" + +fun NavGraphBuilder.passcodeRoute( + onForgotButton: () -> Unit, + onSkipButton: () -> Unit, + onPasscodeConfirm: (String) -> Unit, + onPasscodeRejected: () -> Unit, +) { + composable( + route = PASSCODE_SCREEN, + ) { + PasscodeScreen( + onForgotButton = onForgotButton, + onSkipButton = onSkipButton, + onPasscodeConfirm = onPasscodeConfirm, + onPasscodeRejected = onPasscodeRejected, + ) + } +} + +fun NavController.navigateToPasscodeScreen(options: NavOptions? = null) { + navigate(PASSCODE_SCREEN, options) +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/MifosIcon.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/MifosIcon.kt new file mode 100644 index 000000000..bde6f14c9 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/MifosIcon.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import org.mifos.mobilewallet.mifospay.feature.passcode.R + +@Composable +internal fun MifosIcon(modifier: Modifier = Modifier) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.Center, + ) { + Image( + modifier = Modifier.size(180.dp), + painter = painterResource(id = R.drawable.mifos_logo), + contentDescription = null, + ) + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeButton.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeButton.kt new file mode 100644 index 000000000..4a99db737 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeButton.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import org.mifos.mobilewallet.mifospay.feature.passcode.R +import org.mifospay.feature.passcode.theme.forgotButtonStyle +import org.mifospay.feature.passcode.theme.skipButtonStyle + +@Composable +internal fun PasscodeSkipButton( + hasPassCode: Boolean, + onSkipButton: () -> Unit, + modifier: Modifier = Modifier, +) { + if (!hasPassCode) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(end = 16.dp), + horizontalArrangement = Arrangement.End, + ) { + TextButton( + onClick = { onSkipButton.invoke() }, + ) { + Text(text = stringResource(R.string.skip), style = skipButtonStyle) + } + } + } +} + +@Composable +internal fun PasscodeForgotButton( + hasPassCode: Boolean, + onForgotButton: () -> Unit, + modifier: Modifier = Modifier, +) { + if (hasPassCode) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(end = 16.dp), + horizontalArrangement = Arrangement.Center, + ) { + TextButton( + onClick = { onForgotButton.invoke() }, + ) { + Text( + text = stringResource(R.string.forgot_passcode_login_manually), + style = forgotButtonStyle, + ) + } + } + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeHeader.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeHeader.kt new file mode 100644 index 000000000..b30e128fd --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeHeader.kt @@ -0,0 +1,121 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.component + +import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.core.Transition +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.animateOffset +import androidx.compose.animation.core.rememberTransition +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.scale +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import org.mifos.mobilewallet.mifospay.feature.passcode.R +import org.mifospay.feature.passcode.utility.Step + +@Composable +internal fun PasscodeHeader( + activeStep: Step, + isPasscodeAlreadySet: Boolean, + modifier: Modifier = Modifier, +) { + val transitionState = remember { MutableTransitionState(activeStep) } + transitionState.targetState = activeStep + + val transition: Transition = rememberTransition( + transitionState = transitionState, + label = "Headers Transition", + ) + + val offset = 200.0F + val zeroOffset = Offset(x = 0.0F, y = 0.0F) + val negativeOffset = Offset(x = -offset, y = 0.0F) + val positiveOffset = Offset(x = offset, y = 0.0F) + + val xTransitionHeader1 by transition.animateOffset(label = "Transition Offset Header 1") { + if (it == Step.Create) zeroOffset else negativeOffset + } + val xTransitionHeader2 by transition.animateOffset(label = "Transition Offset Header 2") { + if (it == Step.Confirm) zeroOffset else positiveOffset + } + val alphaHeader1 by transition.animateFloat(label = "Transition Alpha Header 1") { + if (it == Step.Create) 1.0F else 0.0F + } + val alphaHeader2 by transition.animateFloat(label = "Transition Alpha Header 2") { + if (it == Step.Confirm) 1.0F else 0.0F + } + val scaleHeader1 by transition.animateFloat(label = "Transition Alpha Header 1") { + if (it == Step.Create) 1.0F else 0.5F + } + val scaleHeader2 by transition.animateFloat(label = "Transition Alpha Header 2") { + if (it == Step.Confirm) 1.0F else 0.5F + } + + Box( + modifier = modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + if (isPasscodeAlreadySet) { + Text( + modifier = Modifier + .offset(x = xTransitionHeader1.x.dp) + .alpha(alpha = alphaHeader1) + .scale(scale = scaleHeader1), + text = stringResource(id = R.string.enter_your_passcode), + style = TextStyle(fontSize = 20.sp), + ) + } else { + if (activeStep == Step.Create) { + Text( + modifier = Modifier + .offset(x = xTransitionHeader1.x.dp) + .alpha(alpha = alphaHeader1) + .scale(scale = scaleHeader1), + text = stringResource(id = R.string.create_passcode), + style = TextStyle(fontSize = 20.sp), + ) + } else if (activeStep == Step.Confirm) { + Text( + modifier = Modifier + .offset(x = xTransitionHeader2.x.dp) + .alpha(alpha = alphaHeader2) + .scale(scale = scaleHeader2), + text = stringResource(id = R.string.confirm_passcode), + style = TextStyle(fontSize = 20.sp), + ) + } + } + } + } +} + +@Preview +@Composable +private fun PasscodeHeaderPreview() { + PasscodeHeader(activeStep = Step.Create, isPasscodeAlreadySet = true) +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeKeys.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeKeys.kt new file mode 100644 index 000000000..e3b01c54b --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeKeys.kt @@ -0,0 +1,198 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.component + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.Backspace +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import org.mifos.mobilewallet.mifospay.feature.passcode.R +import org.mifospay.feature.passcode.theme.PasscodeKeyButtonStyle +import org.mifospay.feature.passcode.theme.blueTint + +@Composable +internal fun PasscodeKeys( + enterKey: (String) -> Unit, + deleteKey: () -> Unit, + deleteAllKeys: () -> Unit, + modifier: Modifier = Modifier, +) { + val onEnterKeyClick = { keyTitle: String -> + enterKey(keyTitle) + } + Column( + modifier = modifier + .fillMaxWidth() + .padding(16.dp), + ) { + Row(modifier = Modifier.fillMaxWidth()) { + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "1", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "2", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "3", + onClick = onEnterKeyClick, + ) + } + Row(modifier = Modifier.fillMaxWidth()) { + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "4", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "5", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "6", + onClick = onEnterKeyClick, + ) + } + Row(modifier = Modifier.fillMaxWidth()) { + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "7", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "8", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "9", + onClick = onEnterKeyClick, + ) + } + Row(modifier = Modifier.fillMaxWidth()) { + PasscodeKey(modifier = Modifier.weight(weight = 1.0F)) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyTitle = "0", + onClick = onEnterKeyClick, + ) + PasscodeKey( + modifier = Modifier.weight(weight = 1.0F), + keyIcon = ImageVector.vectorResource(id = R.drawable.ic_delete), + keyIconContentDescription = "Delete Passcode Key Button", + onClick = { + deleteKey() + }, + onLongClick = { + deleteAllKeys() + }, + ) + } + } +} + +@Composable +internal fun PasscodeKey( + modifier: Modifier = Modifier, + keyTitle: String = "", + keyIcon: ImageVector? = null, + keyIconContentDescription: String = "", + onClick: ((String) -> Unit)? = null, + onLongClick: (() -> Unit)? = null, +) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.Center, + ) { + CombinedClickableIconButton( + onClick = { + onClick?.invoke(keyTitle) + }, + onLongClick = { + onLongClick?.invoke() + }, + modifier = Modifier + .padding(all = 4.dp), + ) { + if (keyIcon == null) { + Text( + text = keyTitle, + style = PasscodeKeyButtonStyle.copy(color = blueTint), + ) + } else { + Icon( + imageVector = Icons.AutoMirrored.Filled.Backspace, + contentDescription = keyIconContentDescription, + tint = blueTint, + ) + } + } + } +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +internal fun CombinedClickableIconButton( + onClick: () -> Unit, + onLongClick: () -> Unit, + modifier: Modifier = Modifier, + size: Dp = 48.dp, + enabled: Boolean = true, + content: @Composable () -> Unit, +) { + Column( + modifier = modifier + .size(size = size) + .combinedClickable( + onClick = onClick, + onLongClick = onLongClick, + enabled = enabled, + role = Role.Button, + ), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + val contentAlpha = + if (enabled) LocalContentColor.current else LocalContentColor.current.copy(alpha = 0f) + CompositionLocalProvider(LocalContentColor provides contentAlpha, content = content) + } +} + +@Preview +@Composable +private fun PasscodeKeysPreview() { + PasscodeKeys({}, {}, {}) +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeMismatchedDialog.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeMismatchedDialog.kt new file mode 100644 index 000000000..e2c23becf --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeMismatchedDialog.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the 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.feature.passcode.component + +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import org.mifos.mobilewallet.mifospay.feature.passcode.R + +@Composable +internal fun PasscodeMismatchedDialog( + visible: Boolean, + onDismiss: () -> Unit, +) { + if (visible) { + AlertDialog( + shape = MaterialTheme.shapes.large, + containerColor = Color.White, + title = { + Text( + text = stringResource(R.string.passcode_do_not_match), + color = Color.Black, + ) + }, + confirmButton = { + TextButton(onClick = onDismiss) { + Text(text = stringResource(R.string.try_again), color = Color.Black) + } + }, + onDismissRequest = onDismiss, + ) + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeStepIndicator.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeStepIndicator.kt new file mode 100644 index 000000000..5716c5370 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeStepIndicator.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.component + +import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import org.mifospay.feature.passcode.theme.blueTint +import org.mifospay.feature.passcode.utility.Constants.STEPS_COUNT +import org.mifospay.feature.passcode.utility.Step + +@Composable +internal fun PasscodeStepIndicator( + activeStep: Step, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy( + space = 6.dp, + alignment = Alignment.CenterHorizontally, + ), + ) { + repeat(STEPS_COUNT) { step -> + val isActiveStep = step <= activeStep.index + val stepColor = + animateColorAsState(if (isActiveStep) blueTint else Color.Gray, label = "") + + Box( + modifier = Modifier + .size( + width = 72.dp, + height = 4.dp, + ) + .background( + color = stepColor.value, + shape = MaterialTheme.shapes.medium, + ), + ) + } + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeToolbar.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeToolbar.kt new file mode 100644 index 000000000..5f7120e5a --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/component/PasscodeToolbar.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.component + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import org.mifos.mobilewallet.mifospay.feature.passcode.R +import org.mifospay.feature.passcode.utility.Step + +@Composable +internal fun PasscodeToolbar( + activeStep: Step, + hasPasscode: Boolean, + modifier: Modifier = Modifier, +) { + var exitWarningDialogVisible by remember { mutableStateOf(false) } + + AnimatedVisibility(exitWarningDialogVisible) { + ExitWarningDialog( + visible = exitWarningDialogVisible, + onConfirm = {}, + onDismiss = { + exitWarningDialogVisible = false + }, + ) + } + + Row( + modifier = modifier + .fillMaxWidth() + .padding(top = 8.dp), + horizontalArrangement = Arrangement.Center, + ) { + if (!hasPasscode) { + PasscodeStepIndicator( + activeStep = activeStep, + ) + } + } +} + +@Composable +private fun ExitWarningDialog( + visible: Boolean, + onConfirm: () -> Unit, + onDismiss: () -> Unit, +) { + if (visible) { + AlertDialog( + shape = MaterialTheme.shapes.large, + containerColor = Color.White, + title = { + Text( + text = stringResource(R.string.are_you_sure_you_want_to_exit), + color = Color.Black, + ) + }, + confirmButton = { + TextButton(onClick = onConfirm) { + Text(text = stringResource(R.string.exit)) + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text(text = stringResource(R.string.cancel)) + } + }, + onDismissRequest = onDismiss, + ) + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeManager.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeManager.kt new file mode 100644 index 000000000..d8ad27b54 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeManager.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.data + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import org.mifospay.feature.passcode.utility.PreferenceManager +import javax.inject.Inject + +class PasscodeManager @Inject constructor( + @ApplicationContext + private val context: Context, +) { + private val passcodePreferencesHelper = PreferenceManager(context) + + val getPasscode = passcodePreferencesHelper.getSavedPasscode() + + val hasPasscode = passcodePreferencesHelper.hasPasscode + + fun savePasscode(passcode: String) { + passcodePreferencesHelper.savePasscode(passcode) + } + + fun clearPasscode() { + passcodePreferencesHelper.clearPasscode() + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeRepository.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeRepository.kt new file mode 100644 index 000000000..9bed3e4ae --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeRepository.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.data + +interface PasscodeRepository { + val hasPasscode: Boolean + + fun getSavedPasscode(): String + + fun savePasscode(passcode: String) +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeRepositoryImpl.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeRepositoryImpl.kt new file mode 100644 index 000000000..9f5681372 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/data/PasscodeRepositoryImpl.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.data + +import org.mifospay.feature.passcode.utility.PreferenceManager +import javax.inject.Inject + +class PasscodeRepositoryImpl @Inject constructor( + private val preferenceManager: PreferenceManager, +) : PasscodeRepository { + + override val hasPasscode: Boolean + get() = preferenceManager.hasPasscode + + override fun getSavedPasscode(): String { + return preferenceManager.getSavedPasscode() + } + + override fun savePasscode(passcode: String) { + preferenceManager.savePasscode(passcode) + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/di/ApplicationModule.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/di/ApplicationModule.kt new file mode 100644 index 000000000..8c034223a --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/di/ApplicationModule.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.di + +import android.content.Context +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import org.mifospay.feature.passcode.data.PasscodeRepository +import org.mifospay.feature.passcode.data.PasscodeRepositoryImpl +import org.mifospay.feature.passcode.utility.PreferenceManager +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object ApplicationModule { + @Provides + @Singleton + fun providePrefManager(@ApplicationContext context: Context): PreferenceManager { + return PreferenceManager(context) + } + + @Provides + @Singleton + fun providesPasscodeRepository(preferenceManager: PreferenceManager): PasscodeRepository { + return PasscodeRepositoryImpl(preferenceManager) + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Color.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Color.kt new file mode 100644 index 000000000..d618c6535 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Color.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.theme + +import androidx.compose.ui.graphics.Color + +internal val blueTint = Color(0xFF03A9F4) diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Font.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Font.kt new file mode 100644 index 000000000..fdf11a189 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Font.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.theme + +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import org.mifos.mobilewallet.mifospay.feature.passcode.R + +internal val LatoFonts = FontFamily( + Font( + resId = R.font.lato_regular, + weight = FontWeight.Normal, + style = FontStyle.Normal, + ), + Font( + resId = R.font.lato_bold, + weight = FontWeight.Bold, + style = FontStyle.Normal, + ), + Font( + resId = R.font.lato_black, + weight = FontWeight.Black, + style = FontStyle.Normal, + ), +) diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Theme.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Theme.kt new file mode 100644 index 000000000..ab7f3cb61 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Theme.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Color.Companion.Blue + +private val DarkColorPalette = darkColorScheme( + primary = Color.Cyan, + onPrimary = Color.Cyan, + secondary = Color.Black.copy(alpha = 0.2f), + background = Color.Black, +) +private val LightColorPalette = lightColorScheme( + primary = Blue, + onPrimary = Blue, + secondary = Color.Blue.copy(alpha = 0.4f), + background = Color.White, +) + +@Composable +internal fun MifosPasscodeTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable () -> Unit, +) { + val colors = if (darkTheme) { + DarkColorPalette + } else { + LightColorPalette + } + + MaterialTheme( + colorScheme = colors, + typography = Typography, + content = content, + ) +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Type.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Type.kt new file mode 100644 index 000000000..6502eef32 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/theme/Type.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +internal val Typography = Typography( + displayLarge = TextStyle( + fontFamily = LatoFonts, + fontWeight = FontWeight.Black, + fontSize = 34.sp, + ), +) + +internal val PasscodeKeyButtonStyle = TextStyle( + fontFamily = LatoFonts, + fontWeight = FontWeight.Bold, + fontSize = 24.sp, +) + +internal val skipButtonStyle = TextStyle( + color = blueTint, + fontSize = 20.sp, + fontFamily = LatoFonts, +) + +internal val forgotButtonStyle = TextStyle( + color = blueTint, + fontSize = 14.sp, + fontFamily = LatoFonts, +) diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/Constants.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/Constants.kt new file mode 100644 index 000000000..8aa501ecc --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/Constants.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.utility + +internal object Constants { + const val STEPS_COUNT = 2 + const val PASSCODE_LENGTH = 4 + const val VIBRATE_FEEDBACK_DURATION = 300L +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/PreferenceManager.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/PreferenceManager.kt new file mode 100644 index 000000000..02d592e25 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/PreferenceManager.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.utility + +import android.content.Context +import org.mifos.mobilewallet.mifospay.feature.passcode.R + +class PreferenceManager(context: Context) { + private val sharedPreference = context.getSharedPreferences( + R.string.pref_name.toString(), + Context.MODE_PRIVATE, + ) + + var hasPasscode: Boolean + get() = sharedPreference.getBoolean(R.string.has_passcode.toString(), false) + set(value) = sharedPreference.edit().putBoolean(R.string.has_passcode.toString(), value) + .apply() + + fun savePasscode(passcode: String) { + sharedPreference.edit().putString(R.string.passcode.toString(), passcode).apply() + hasPasscode = true + } + + fun getSavedPasscode(): String { + return sharedPreference.getString(R.string.passcode.toString(), "").toString() + } + + fun clearPasscode() { + sharedPreference.edit().clear().apply() + hasPasscode = false + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/ShakeAnimation.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/ShakeAnimation.kt new file mode 100644 index 000000000..068bc230d --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/ShakeAnimation.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.utility + +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.LinearOutSlowInEasing +import androidx.compose.animation.core.keyframes +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +internal object ShakeAnimation { + + fun CoroutineScope.performShakeAnimation(xShake: Animatable) { + launch { + xShake.animateTo( + targetValue = 0f, + animationSpec = keyframes { + durationMillis = 280 + 0f at 0 using LinearOutSlowInEasing + 20f at 80 using LinearOutSlowInEasing + 20f at 120 using LinearOutSlowInEasing + 10f at 160 using LinearOutSlowInEasing + 10f at 200 using LinearOutSlowInEasing + 5f at 240 using LinearOutSlowInEasing + 0f at 280 + }, + ) + } + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/Step.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/Step.kt new file mode 100644 index 000000000..bb26052df --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/Step.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.utility + +internal enum class Step(var index: Int) { + Create(0), + Confirm(1), +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/VibrationFeedback.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/VibrationFeedback.kt new file mode 100644 index 000000000..032edb0d6 --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/utility/VibrationFeedback.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.utility + +import android.content.Context +import android.os.Build +import android.os.CombinedVibration +import android.os.VibrationEffect +import android.os.Vibrator +import android.os.VibratorManager +import org.mifospay.feature.passcode.utility.Constants.VIBRATE_FEEDBACK_DURATION + +internal object VibrationFeedback { + + @Suppress("DEPRECATION") + internal fun vibrateFeedback(context: Context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + (context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager).vibrate( + CombinedVibration.createParallel( + VibrationEffect.createOneShot( + VIBRATE_FEEDBACK_DURATION, + VibrationEffect.DEFAULT_AMPLITUDE, + ), + ), + ) + } else { + (context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator).let { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + it.vibrate( + VibrationEffect.createOneShot( + VIBRATE_FEEDBACK_DURATION, + VibrationEffect.DEFAULT_AMPLITUDE, + ), + ) + } else { + it.vibrate(VIBRATE_FEEDBACK_DURATION) + } + } + } + } +} diff --git a/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/viewmodels/PasscodeViewModel.kt b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/viewmodels/PasscodeViewModel.kt new file mode 100644 index 000000000..c468de74c --- /dev/null +++ b/feature/passcode/src/main/kotlin/org/mifospay/feature/passcode/viewmodels/PasscodeViewModel.kt @@ -0,0 +1,151 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.feature.passcode.viewmodels + +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import org.mifospay.feature.passcode.data.PasscodeRepository +import org.mifospay.feature.passcode.utility.Constants.PASSCODE_LENGTH +import org.mifospay.feature.passcode.utility.Step +import javax.inject.Inject + +@HiltViewModel +internal class PasscodeViewModel @Inject constructor( + private val passcodeRepository: PasscodeRepository, +) : ViewModel() { + + private val mOnPasscodeConfirmed = MutableSharedFlow() + val onPasscodeConfirmed = mOnPasscodeConfirmed.asSharedFlow() + + private val mOnPasscodeRejected = MutableSharedFlow() + val onPasscodeRejected = mOnPasscodeRejected.asSharedFlow() + + private val mActiveStep = MutableStateFlow(Step.Create) + val activeStep = mActiveStep.asStateFlow() + + private val mFilledDots = MutableStateFlow(0) + val filledDots = mFilledDots.asStateFlow() + + private var createPasscode: StringBuilder = StringBuilder() + private var confirmPasscode: StringBuilder = StringBuilder() + + private val mPasscodeVisible = MutableStateFlow(false) + val passcodeVisible = mPasscodeVisible.asStateFlow() + + private val mCurrentPasscodeInput = MutableStateFlow("") + val currentPasscodeInput = mCurrentPasscodeInput.asStateFlow() + + private var mIsPasscodeAlreadySet = mutableStateOf(passcodeRepository.hasPasscode) + + init { + resetData() + } + + private fun emitActiveStep(activeStep: Step) = viewModelScope.launch { + mActiveStep.emit(activeStep) + } + + private fun emitFilledDots(filledDots: Int) = viewModelScope.launch { + mFilledDots.emit(filledDots) + } + + private fun emitOnPasscodeConfirmed(confirmPassword: String) = viewModelScope.launch { + mOnPasscodeConfirmed.emit(confirmPassword) + } + + private fun emitOnPasscodeRejected() = viewModelScope.launch { + mOnPasscodeRejected.emit(Unit) + } + + fun togglePasscodeVisibility() { + mPasscodeVisible.value = !mPasscodeVisible.value + } + + private fun resetData() { + emitActiveStep(Step.Create) + emitFilledDots(0) + + createPasscode.clear() + confirmPasscode.clear() + } + + fun enterKey(key: String) { + if (mFilledDots.value >= PASSCODE_LENGTH) { + return + } + + val currentPasscode = + if (mActiveStep.value == Step.Create) createPasscode else confirmPasscode + currentPasscode.append(key) + mCurrentPasscodeInput.value = currentPasscode.toString() + emitFilledDots(currentPasscode.length) + + if (mFilledDots.value == PASSCODE_LENGTH) { + if (mIsPasscodeAlreadySet.value) { + if (passcodeRepository.getSavedPasscode() == createPasscode.toString()) { + emitOnPasscodeConfirmed(createPasscode.toString()) + createPasscode.clear() + } else { + emitOnPasscodeRejected() + // logic for retires can be written here + } + mCurrentPasscodeInput.value = "" + } else if (mActiveStep.value == Step.Create) { + emitActiveStep(Step.Confirm) + emitFilledDots(0) + mCurrentPasscodeInput.value = "" + } else { + if (createPasscode.toString() == confirmPasscode.toString()) { + emitOnPasscodeConfirmed(confirmPasscode.toString()) + passcodeRepository.savePasscode(confirmPasscode.toString()) + mIsPasscodeAlreadySet.value = true + resetData() + } else { + emitOnPasscodeRejected() + resetData() + } + mCurrentPasscodeInput.value = "" + } + } + } + + fun deleteKey() { + val currentPasscode = + if (mActiveStep.value == Step.Create) createPasscode else confirmPasscode + + if (currentPasscode.isNotEmpty()) { + currentPasscode.deleteAt(currentPasscode.length - 1) + mCurrentPasscodeInput.value = currentPasscode.toString() + emitFilledDots(currentPasscode.length) + } + } + + fun deleteAllKeys() { + if (mActiveStep.value == Step.Create) { + createPasscode.clear() + } else { + confirmPasscode.clear() + } + mCurrentPasscodeInput.value = "" + emitFilledDots(0) + } + + fun restart() { + resetData() + mPasscodeVisible.value = false + } +} diff --git a/mifospay/src/main/res/drawable/ic_download.xml b/feature/passcode/src/main/res/drawable/baseline_delete_forever_24.xml similarity index 52% rename from mifospay/src/main/res/drawable/ic_download.xml rename to feature/passcode/src/main/res/drawable/baseline_delete_forever_24.xml index 5cc1a6fc4..cc0810db2 100644 --- a/mifospay/src/main/res/drawable/ic_download.xml +++ b/feature/passcode/src/main/res/drawable/baseline_delete_forever_24.xml @@ -8,8 +8,8 @@ See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md --> - - + diff --git a/feature/passcode/src/main/res/drawable/ic_delete.xml b/feature/passcode/src/main/res/drawable/ic_delete.xml new file mode 100644 index 000000000..a10936ea0 --- /dev/null +++ b/feature/passcode/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,20 @@ + + + + + diff --git a/feature/passcode/src/main/res/drawable/mifos_logo.jpg b/feature/passcode/src/main/res/drawable/mifos_logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a067a3c8edb0f19925c7f9ad7c5a72b27b5e5150 GIT binary patch literal 75684 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%0A9SW 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 X)1d#|GoGS{N^72R6+cvrokIHmv=>@H literal 0 HcmV?d00001 diff --git a/feature/passcode/src/main/res/font/lato_bold.ttf b/feature/passcode/src/main/res/font/lato_bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..016068b486e1bd1d73743185c2752b7b1b843701 GIT binary patch literal 73332 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 will be reset, are you sure? Cancel Yes + Passcode + hasPasscode + hasDragPasscode + passcode + drag_passcode + + Create Passcode + Confirm Passcode + Enter your Passcode + Forgot Passcode + Delete Passcode Key Button + Drag your finger here only in one direction. + Drag your Pattern + Exit + Cancel + Skip + Forgot Passcode, Login Manually + Try again + Passcode do not match! + Are you sure you want to exit? \ No newline at end of file diff --git a/feature/profile/src/main/kotlin/org/mifospay/feature/profile/edit/EditProfileScreen.kt b/feature/profile/src/main/kotlin/org/mifospay/feature/profile/edit/EditProfileScreen.kt index cf63bac3c..c355412b2 100644 --- a/feature/profile/src/main/kotlin/org/mifospay/feature/profile/edit/EditProfileScreen.kt +++ b/feature/profile/src/main/kotlin/org/mifospay/feature/profile/edit/EditProfileScreen.kt @@ -112,8 +112,8 @@ fun EditProfileScreen( Box( modifier = - modifier - .fillMaxSize(), + modifier + .fillMaxSize(), ) { MifosScaffold( topBarTitle = R.string.feature_profile_edit_profile, @@ -189,15 +189,15 @@ private fun EditProfileScreenContent( PermissionBox( requiredPermissions = - if (Build.VERSION.SDK_INT >= 33) { - listOf(Manifest.permission.CAMERA) - } else { - listOf( - Manifest.permission.CAMERA, - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE, - ) - }, + if (Build.VERSION.SDK_INT >= 33) { + listOf(Manifest.permission.CAMERA) + } else { + listOf( + Manifest.permission.CAMERA, + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + ) + }, title = R.string.feature_profile_permission_required, confirmButtonText = R.string.feature_profile_proceed, dismissButtonText = R.string.feature_profile_dismiss, @@ -244,16 +244,16 @@ private fun EditProfileScreenContent( ) Box( modifier = - modifier - .padding(contentPadding) - .fillMaxSize(), + modifier + .padding(contentPadding) + .fillMaxSize(), ) { Column( modifier = - Modifier - .fillMaxSize() - .background(color = MaterialTheme.colorScheme.surface) - .verticalScroll(rememberScrollState()), + Modifier + .fillMaxSize() + .background(color = MaterialTheme.colorScheme.surface) + .verticalScroll(rememberScrollState()), ) { EditProfileScreenImage( imageUri = imageUri, @@ -264,33 +264,33 @@ private fun EditProfileScreenContent( label = stringResource(id = R.string.feature_profile_username), onValueChange = { username = it }, modifier = - Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp), + Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp), ) MfOutlinedTextField( value = email, label = stringResource(id = R.string.feature_profile_email), onValueChange = { email = it }, modifier = - Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp), + Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp), ) MfOutlinedTextField( value = vpa, label = stringResource(id = R.string.feature_profile_vpa), onValueChange = { vpa = it }, modifier = - Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp), + Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp), ) Box( modifier = - Modifier - .fillMaxWidth() - .padding(start = 16.dp, end = 16.dp), + Modifier + .fillMaxWidth() + .padding(start = 16.dp, end = 16.dp), ) { val keyboardController = LocalSoftwareKeyboardController.current if (LocalInspectionMode.current) { @@ -302,9 +302,9 @@ private fun EditProfileScreenContent( autoDetectCode = true, shape = RoundedCornerShape(3.dp), colors = - TextFieldDefaults.outlinedTextFieldColors( - focusedBorderColor = MaterialTheme.colorScheme.onSurface, - ), + TextFieldDefaults.outlinedTextFieldColors( + focusedBorderColor = MaterialTheme.colorScheme.onSurface, + ), onValueChange = { (code, phone), isValid -> if (isValid) { mobile = code + phone @@ -356,16 +356,16 @@ fun EditProfileBottomSheetContent( ) { Column( modifier = - modifier - .background(MaterialTheme.colorScheme.surface) - .padding(top = 8.dp, bottom = 12.dp), + modifier + .background(MaterialTheme.colorScheme.surface) + .padding(top = 8.dp, bottom = 12.dp), ) { Row( modifier = - Modifier - .fillMaxWidth() - .padding(12.dp) - .clickable { onClickProfilePicture.invoke() }, + Modifier + .fillMaxWidth() + .padding(12.dp) + .clickable { onClickProfilePicture.invoke() }, horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { @@ -377,10 +377,10 @@ fun EditProfileBottomSheetContent( } Row( modifier = - Modifier - .fillMaxWidth() - .padding(12.dp) - .clickable { onChangeProfilePicture.invoke() }, + Modifier + .fillMaxWidth() + .padding(12.dp) + .clickable { onChangeProfilePicture.invoke() }, horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { @@ -392,10 +392,10 @@ fun EditProfileBottomSheetContent( } Row( modifier = - Modifier - .fillMaxWidth() - .padding(12.dp) - .clickable { onRemoveProfilePicture.invoke() }, + Modifier + .fillMaxWidth() + .padding(12.dp) + .clickable { onRemoveProfilePicture.invoke() }, horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { @@ -418,9 +418,9 @@ private fun EditProfileSaveButton( onClick = onClick, colors = ButtonDefaults.buttonColors(MaterialTheme.colorScheme.primary), modifier = - modifier - .fillMaxWidth() - .padding(16.dp), + modifier + .fillMaxWidth() + .padding(16.dp), shape = RoundedCornerShape(10.dp), contentPadding = PaddingValues(12.dp), ) { diff --git a/feature/request-money/src/main/kotlin/org/mifospay/feature/request/money/SetAmountDialog.kt b/feature/request-money/src/main/kotlin/org/mifospay/feature/request/money/SetAmountDialog.kt index 02ac1363a..eab98646c 100644 --- a/feature/request-money/src/main/kotlin/org/mifospay/feature/request/money/SetAmountDialog.kt +++ b/feature/request-money/src/main/kotlin/org/mifospay/feature/request/money/SetAmountDialog.kt @@ -135,9 +135,9 @@ internal fun SetAmountDialog( } }, keyboardOptions = - KeyboardOptions( - keyboardType = KeyboardType.Number, - ), + KeyboardOptions( + keyboardType = KeyboardType.Number, + ), ) MfOutlinedTextField( @@ -146,9 +146,9 @@ internal fun SetAmountDialog( onValueChange = { currency = it }, modifier = Modifier.fillMaxWidth(), keyboardOptions = - KeyboardOptions( - keyboardType = KeyboardType.Text, - ), + KeyboardOptions( + keyboardType = KeyboardType.Text, + ), ) Spacer(modifier = Modifier.height(8.dp)) diff --git a/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendScreenRoute.kt b/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendScreenRoute.kt index 871261664..1623c2f3e 100644 --- a/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendScreenRoute.kt +++ b/feature/send-money/src/main/kotlin/org/mifospay/feature/send/money/SendScreenRoute.kt @@ -200,9 +200,9 @@ internal fun SendMoneyScreen( Row( verticalAlignment = Alignment.CenterVertically, modifier = - Modifier - .fillMaxWidth() - .padding(top = 20.dp, bottom = 20.dp), + Modifier + .fillMaxWidth() + .padding(top = 20.dp, bottom = 20.dp), ) { VpaMobileChip( label = stringResource(id = R.string.feature_send_money_vpa), @@ -256,9 +256,9 @@ internal fun SendMoneyScreen( SendMethodType.MOBILE -> { EnterPhoneScreen( modifier = - Modifier - .fillMaxWidth() - .padding(bottom = 8.dp), + Modifier + .fillMaxWidth() + .padding(bottom = 8.dp), initialPhoneNumber = mobileNumber, onNumberUpdated = { _, fullPhone, valid -> if (valid) { @@ -273,10 +273,10 @@ internal fun SendMoneyScreen( Spacer(modifier = Modifier.height(16.dp)) MifosButton( modifier = - Modifier - .fillMaxWidth() - .padding(top = 16.dp) - .align(Alignment.CenterHorizontally), + Modifier + .fillMaxWidth() + .padding(top = 16.dp) + .align(Alignment.CenterHorizontally), color = MaterialTheme.colorScheme.onSurface, enabled = isValidInfo, onClick = { @@ -320,9 +320,9 @@ private fun EnterPhoneScreen( modifier = modifier, shape = RoundedCornerShape(8.dp), colors = - TextFieldDefaults.outlinedTextFieldColors( - focusedBorderColor = MaterialTheme.colorScheme.primary, - ), + TextFieldDefaults.outlinedTextFieldColors( + focusedBorderColor = MaterialTheme.colorScheme.primary, + ), initialPhoneNumber = initialPhoneNumber, onValueChange = { (code, phone), isValid -> onNumberUpdated(phone, code + phone, isValid) @@ -343,9 +343,9 @@ private fun VpaMobileChip( onClick = onClick, color = if (selected) MaterialTheme.colorScheme.primary else Color.LightGray, modifier = - modifier - .padding(4.dp) - .wrapContentSize(), + modifier + .padding(4.dp) + .wrapContentSize(), ) { Text( modifier = Modifier.padding(top = 4.dp, bottom = 4.dp), diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d8dfb79b3..d2dfd0fbf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,15 +4,15 @@ androidPdfViewerVersion = "2.8.2" appcompatVersion = "1.7.0" androidGradlePlugin = "8.4.0" checkstyleVersion = "10.16.0" -compileSdk = "34" constraintlayoutVersion = "2.1.4" swiperefreshLayoutVersion = "1.1.0" coreKtxVersion = "1.13.1" credentialsVersion = "1.2.2" googleidVersion = "1.1.1" materialNavigationVersion = "1.7.0-alpha04" -minSdk = "24" playServicesAuthVersion = "21.2.0" +compileSdk = "34" +minSdk = "24" targetSdk = "34" androidTools = "31.5.1" androidxActivity = "1.9.1" @@ -31,7 +31,6 @@ compose-plugin = "1.6.1" ksp = "1.9.22-1.0.18" firebaseCrashlyticsPlugin = "2.9.9" gmsPlugin = "4.4.1" -butterknifePlugin = "10.2.3" secrets = "2.0.1" lifecycleVersion = "2.8.4" lifecycleExtensionsVersion = "2.2.0" @@ -78,9 +77,7 @@ androidxBrowser = "1.8.0" playServicesCodeScanner = "16.1.0" moduleGraph = "2.5.0" composeMaterial = "1.6.0" -mifosPasscode = "0.3.0" -zxingAndroidEmbeddedVersion = "4.2.0" -zxingVersion = "1.9.13" +zxingVersion = "3.5.3" cameraViewVersion = "1.3.4" cameraLifecycleVersion = "1.3.4" spotlessVersion = "6.23.3" @@ -128,8 +125,6 @@ androidx-lifecycle-viewModelCompose = { group = "androidx.lifecycle", name = "li androidx-lifecycle-runtimeTesting = { group = "androidx.lifecycle", name = "lifecycle-runtime-testing", version.ref = "androidxLifecycle" } androidx-lifecycle-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleVersion" } androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycleExtensionsVersion" } -jakewharton-butterknife = { module = "com.jakewharton:butterknife", version.ref = "butterKnifeVersion" } -jakewharton-compiler = { module = "com.jakewharton:butterknife-compiler", version.ref = "butterKnifeVersion" } play-services-auth = { module = "com.google.android.gms:play-services-auth", version.ref = "playServicesAuthVersion" } squareup-retrofit2 = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofitVersion" } squareup-retrofit-adapter-rxjava = { module = "com.squareup.retrofit2:adapter-rxjava", version.ref = "retrofitVersion" } @@ -142,7 +137,6 @@ truth = { group = "com.google.truth", name = "truth", version.ref = "truth" } junit = { module = "junit:junit", version.ref = "junitVersion" } google-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "googleOss" } google-oss-licenses-plugin = { group = "com.google.android.gms", name = "oss-licenses-plugin", version.ref = "googleOssPlugin" } -jetbrains-kotlin-jdk7 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "kotlin" } firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebaseBom" } firebase-analytics = { group = "com.google.firebase", name = "firebase-analytics-ktx" } firebase-cloud-messaging = { group = "com.google.firebase", name = "firebase-messaging-ktx" } @@ -173,14 +167,11 @@ androidx-profileinstaller = { group = "androidx.profileinstaller", name = "profi androidx-tracing-ktx = { group = "androidx.tracing", name = "tracing-ktx", version.ref = "androidxTracing" } coil-kt = { group = "io.coil-kt", name = "coil", version.ref = "coil" } coil-kt-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } -coil-kt-svg = { group = "io.coil-kt", name = "coil-svg", version.ref = "coil" } androidx-metrics = { group = "androidx.metrics", name = "metrics-performance", version.ref = "androidxMetrics" } androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidxBrowser" } google-play-services-code-scanner = { group = "com.google.android.gms", name = "play-services-code-scanner", version.ref = "playServicesCodeScanner" } -mifosPasscode = { group = "com.mifos.mobile", name = "mifos-passcode", version.ref = "mifosPasscode" } #Detekt -detekt-gradlePlugin = { group = "io.gitlab.arturbosch.detekt", name = "detekt-gradle-plugin", version.ref = "detekt" } detekt-formatting = { group = "io.gitlab.arturbosch.detekt", name = "detekt-formatting", version.ref = "detekt" } twitter-detekt-compose = { group = "com.twitter.compose.rules", name = "detekt", version.ref = "twitter-detekt-compose" } @@ -192,8 +183,7 @@ firebase-performance-gradlePlugin = { group = "com.google.firebase", name = "per kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" } ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } room-gradlePlugin = { group = "androidx.room", name = "room-gradle-plugin", version.ref = "room" } -zxing = { module = "me.dm7.barcodescanner:zxing", version.ref = "zxingVersion" } -zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroidEmbeddedVersion" } +zxing = { module = "com.google.zxing:core", version.ref = "zxingVersion" } androidx-camera-view = { group = "androidx.camera", name = "camera-view", version.ref = "cameraViewVersion" } androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "cameraLifecycleVersion" } spotless-gradle = { group = "com.diffplug.spotless", name = "spotless-plugin-gradle", version.ref = "spotlessVersion" } @@ -213,7 +203,6 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } android-test = { id = "com.android.test", version.ref = "androidGradlePlugin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } diff --git a/mifospay/build.gradle.kts b/mifospay/build.gradle.kts index 219aa620d..febc5dba3 100644 --- a/mifospay/build.gradle.kts +++ b/mifospay/build.gradle.kts @@ -116,6 +116,7 @@ dependencies { implementation(libs.androidx.core.splashscreen) implementation(libs.androidx.hilt.navigation.compose) implementation(libs.androidx.lifecycle.runtimeCompose) + implementation(libs.androidx.lifecycle.viewModelCompose) implementation(libs.androidx.navigation.compose) implementation(libs.androidx.profileinstaller) implementation(libs.androidx.tracing.ktx) @@ -124,8 +125,6 @@ dependencies { implementation(libs.androidx.material.navigation) implementation(libs.accompanist.pager) - implementation(libs.mifosPasscode) - ksp(libs.hilt.compiler) // Google Bar code scanner @@ -148,8 +147,6 @@ dependencies { runtimeOnly(libs.androidx.compose.runtime) debugImplementation(libs.androidx.compose.ui.tooling) - implementation(libs.mifosPasscode) - kspTest(libs.hilt.compiler) testImplementation(libs.junit) @@ -161,5 +158,8 @@ dependencies { } dependencyGuard { - configuration("prodReleaseRuntimeClasspath") + configuration("prodReleaseRuntimeClasspath") { + modules = true + tree = true + } } diff --git a/mifospay/dependencies/prodReleaseRuntimeClasspath.tree.txt b/mifospay/dependencies/prodReleaseRuntimeClasspath.tree.txt new file mode 100644 index 000000000..c014197d5 --- /dev/null +++ b/mifospay/dependencies/prodReleaseRuntimeClasspath.tree.txt @@ -0,0 +1,2031 @@ ++--- com.google.android.material:material:1.0.0 -> 1.11.0 +| +--- org.jetbrains.kotlin:kotlin-bom:1.8.22 +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (c) +| | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.22 -> 1.9.23 (c) +| | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 -> 1.9.23 (c) +| | \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (c) +| +--- com.google.errorprone:error_prone_annotations:2.15.0 -> 2.26.0 +| +--- androidx.activity:activity:1.8.0 -> 1.9.1 +| | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 +| | | \--- androidx.annotation:annotation-jvm:1.8.0 +| | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.10 -> 1.9.23 +| | | +--- org.jetbrains:annotations:13.0 -> 23.0.0 +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.9.23 (c) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0 -> 1.9.23 (c) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0 -> 1.9.23 (c) +| | +--- androidx.collection:collection:1.0.0 -> 1.4.0 +| | | \--- androidx.collection:collection-jvm:1.4.0 +| | | +--- androidx.annotation:annotation:1.7.0 -> 1.8.0 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | +--- androidx.collection:collection-ktx:1.4.0 (c) +| | | \--- androidx.collection:collection-ktx:1.3.0 -> 1.4.0 (c) +| | +--- androidx.core:core:1.13.0 -> 1.13.1 +| | | +--- androidx.annotation:annotation:1.6.0 -> 1.8.0 (*) +| | | +--- androidx.annotation:annotation-experimental:1.4.0 +| | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.10 -> 1.9.23 (*) +| | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | +--- androidx.concurrent:concurrent-futures:1.0.0 -> 1.1.0 +| | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | \--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| | | +--- androidx.interpolator:interpolator:1.0.0 +| | | | \--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| | | +--- androidx.lifecycle:lifecycle-runtime:2.6.2 -> 2.8.4 +| | | | \--- androidx.lifecycle:lifecycle-runtime-android:2.8.4 +| | | | +--- androidx.annotation:annotation:1.8.0 (*) +| | | | +--- androidx.arch.core:core-common:2.2.0 +| | | | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- androidx.arch.core:core-runtime:2.2.0 +| | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | \--- androidx.arch.core:core-common:2.2.0 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 +| | | | | \--- androidx.lifecycle:lifecycle-common-jvm:2.8.4 +| | | | | +--- androidx.annotation:annotation:1.8.0 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 +| | | | | | \--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.1 +| | | | | | +--- org.jetbrains:annotations:23.0.0 +| | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.1 +| | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1 (c) +| | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.1 (c) +| | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (c) +| | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.8.1 (c) +| | | | | | | \--- org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.8.1 (c) +| | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 1.9.23 (*) +| | | | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | | | +--- androidx.profileinstaller:profileinstaller:1.3.1 +| | | | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | | | +--- androidx.concurrent:concurrent-futures:1.1.0 (*) +| | | | | +--- androidx.startup:startup-runtime:1.1.1 +| | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | | \--- androidx.tracing:tracing:1.0.0 -> 1.3.0-alpha02 +| | | | | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | | | | \--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (c) +| | | | | \--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (*) +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.1 (*) +| | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 1.9.23 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | | +--- androidx.versionedparcelable:versionedparcelable:1.1.1 +| | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | \--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | \--- androidx.core:core-ktx:1.13.1 (c) +| | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 -> 2.8.4 (*) +| | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 -> 2.8.4 +| | | \--- androidx.lifecycle:lifecycle-viewmodel-android:2.8.4 +| | | +--- androidx.annotation:annotation:1.8.0 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 (*) +| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 -> 2.8.4 +| | | +--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| | | +--- androidx.core:core-ktx:1.2.0 -> 1.13.1 +| | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- androidx.core:core:1.13.1 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | \--- androidx.core:core:1.13.1 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 +| | | | +--- androidx.arch.core:core-common:2.2.0 (*) +| | | | +--- androidx.arch.core:core-runtime:2.2.0 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (*) +| | | +--- androidx.savedstate:savedstate:1.2.1 +| | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- androidx.arch.core:core-common:2.1.0 -> 2.2.0 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 -> 2.8.4 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.9.23 (*) +| | | | \--- androidx.savedstate:savedstate-ktx:1.2.1 (c) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 (*) +| | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | +--- androidx.profileinstaller:profileinstaller:1.3.1 (*) +| | +--- androidx.savedstate:savedstate:1.2.1 (*) +| | +--- androidx.tracing:tracing:1.0.0 -> 1.3.0-alpha02 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- androidx.activity:activity-compose:1.9.1 (c) +| | \--- androidx.activity:activity-ktx:1.9.1 (c) +| +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| +--- androidx.appcompat:appcompat:1.6.1 -> 1.7.0 +| | +--- androidx.activity:activity:1.7.0 -> 1.9.1 (*) +| | +--- androidx.annotation:annotation:1.3.0 -> 1.8.0 (*) +| | +--- androidx.appcompat:appcompat-resources:1.7.0 +| | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | +--- androidx.core:core:1.6.0 -> 1.13.1 (*) +| | | +--- androidx.vectordrawable:vectordrawable:1.1.0 +| | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- androidx.core:core:1.1.0 -> 1.13.1 (*) +| | | | \--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | | +--- androidx.vectordrawable:vectordrawable-animated:1.1.0 +| | | | +--- androidx.vectordrawable:vectordrawable:1.1.0 (*) +| | | | +--- androidx.interpolator:interpolator:1.0.0 (*) +| | | | \--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | | \--- androidx.appcompat:appcompat:1.7.0 (c) +| | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | +--- androidx.core:core:1.13.0 -> 1.13.1 (*) +| | +--- androidx.core:core-ktx:1.13.0 -> 1.13.1 (*) +| | +--- androidx.cursoradapter:cursoradapter:1.0.0 +| | | \--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| | +--- androidx.drawerlayout:drawerlayout:1.0.0 -> 1.1.1 +| | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | +--- androidx.core:core:1.2.0 -> 1.13.1 (*) +| | | \--- androidx.customview:customview:1.1.0 +| | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | +--- androidx.core:core:1.3.0 -> 1.13.1 (*) +| | | \--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | +--- androidx.emoji2:emoji2:1.3.0 +| | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | +--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | | +--- androidx.core:core:1.3.0 -> 1.13.1 (*) +| | | +--- androidx.lifecycle:lifecycle-process:2.4.1 -> 2.8.4 +| | | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (*) +| | | | +--- androidx.startup:startup-runtime:1.1.1 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | | +--- androidx.startup:startup-runtime:1.0.0 -> 1.1.1 (*) +| | | \--- androidx.emoji2:emoji2-views-helper:1.3.0 (c) +| | +--- androidx.emoji2:emoji2-views-helper:1.2.0 -> 1.3.0 +| | | +--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | | +--- androidx.core:core:1.3.0 -> 1.13.1 (*) +| | | +--- androidx.emoji2:emoji2:1.3.0 (*) +| | | \--- androidx.emoji2:emoji2:1.3.0 (c) +| | +--- androidx.fragment:fragment:1.5.4 -> 1.6.2 +| | | +--- androidx.activity:activity:1.7.2 -> 1.9.1 (*) +| | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | +--- androidx.annotation:annotation-experimental:1.0.0 -> 1.4.0 (*) +| | | +--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | | +--- androidx.core:core-ktx:1.2.0 -> 1.13.1 (*) +| | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 -> 2.8.4 (*) +| | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 -> 2.8.4 (*) +| | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 -> 2.8.4 (*) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 -> 2.8.4 (*) +| | | +--- androidx.loader:loader:1.0.0 -> 1.1.0 +| | | | +--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| | | | +--- androidx.core:core:1.0.0 -> 1.13.1 (*) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.0.0 -> 2.8.4 (*) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 -> 2.8.4 (*) +| | | | \--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | +--- androidx.profileinstaller:profileinstaller:1.3.0 -> 1.3.1 (*) +| | | +--- androidx.savedstate:savedstate:1.2.1 (*) +| | | +--- androidx.viewpager:viewpager:1.0.0 +| | | | +--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| | | | +--- androidx.core:core:1.0.0 -> 1.13.1 (*) +| | | | \--- androidx.customview:customview:1.0.0 -> 1.1.0 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.20 -> 1.9.23 (*) +| | | \--- androidx.fragment:fragment-ktx:1.6.2 (c) +| | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 -> 2.8.4 (*) +| | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 -> 2.8.4 (*) +| | +--- androidx.profileinstaller:profileinstaller:1.3.1 (*) +| | +--- androidx.resourceinspection:resourceinspection-annotation:1.0.1 +| | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | +--- androidx.savedstate:savedstate:1.2.1 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | \--- androidx.appcompat:appcompat-resources:1.7.0 (c) +| +--- androidx.cardview:cardview:1.0.0 +| | \--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| +--- androidx.coordinatorlayout:coordinatorlayout:1.1.0 +| | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | +--- androidx.core:core:1.1.0 -> 1.13.1 (*) +| | +--- androidx.customview:customview:1.0.0 -> 1.1.0 (*) +| | \--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| +--- androidx.constraintlayout:constraintlayout:2.0.1 -> 2.1.4 +| | +--- androidx.appcompat:appcompat:1.2.0 -> 1.7.0 (*) +| | +--- androidx.core:core:1.3.2 -> 1.13.1 (*) +| | \--- androidx.constraintlayout:constraintlayout-core:1.0.4 +| +--- androidx.core:core:1.6.0 -> 1.13.1 (*) +| +--- androidx.drawerlayout:drawerlayout:1.1.1 (*) +| +--- androidx.dynamicanimation:dynamicanimation:1.0.0 +| | +--- androidx.core:core:1.0.0 -> 1.13.1 (*) +| | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | \--- androidx.legacy:legacy-support-core-utils:1.0.0 +| | +--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| | +--- androidx.core:core:1.0.0 -> 1.13.1 (*) +| | +--- androidx.documentfile:documentfile:1.0.0 +| | | \--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| | +--- androidx.loader:loader:1.0.0 -> 1.1.0 (*) +| | +--- androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 +| | | \--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| | \--- androidx.print:print:1.0.0 +| | \--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| +--- androidx.annotation:annotation-experimental:1.0.0 -> 1.4.0 (*) +| +--- androidx.fragment:fragment:1.2.5 -> 1.6.2 (*) +| +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.8.4 (*) +| +--- androidx.recyclerview:recyclerview:1.0.0 -> 1.3.2 +| | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | +--- androidx.core:core:1.7.0 -> 1.13.1 (*) +| | +--- androidx.customview:customview:1.0.0 -> 1.1.0 (*) +| | +--- androidx.customview:customview-poolingcontainer:1.0.0 +| | | +--- androidx.core:core-ktx:1.5.0 -> 1.13.1 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.6.21 -> 1.9.23 (*) +| | \--- androidx.viewpager2:viewpager2:1.1.0-beta02 (c) +| +--- androidx.resourceinspection:resourceinspection-annotation:1.0.1 (*) +| +--- androidx.transition:transition:1.2.0 +| | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | +--- androidx.core:core:1.0.1 -> 1.13.1 (*) +| | \--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| +--- androidx.vectordrawable:vectordrawable:1.1.0 (*) +| \--- androidx.viewpager2:viewpager2:1.0.0 -> 1.1.0-beta02 +| +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| +--- androidx.annotation:annotation-experimental:1.3.0 -> 1.4.0 (*) +| +--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| +--- androidx.core:core:1.3.2 -> 1.13.1 (*) +| +--- androidx.fragment:fragment:1.1.0 -> 1.6.2 (*) +| \--- androidx.recyclerview:recyclerview:1.3.1-rc01 -> 1.3.2 (*) ++--- androidx.databinding:databinding-common:8.4.0 ++--- androidx.databinding:databinding-runtime:8.4.0 +| +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| +--- androidx.databinding:databinding-common:8.4.0 +| +--- androidx.databinding:viewbinding:8.4.0 +| | \--- androidx.annotation:annotation:1.0.0 -> 1.8.0 (*) +| \--- androidx.lifecycle:lifecycle-runtime:2.6.1 -> 2.8.4 (*) ++--- androidx.databinding:databinding-adapters:8.4.0 +| +--- androidx.databinding:databinding-runtime:8.4.0 (*) +| \--- androidx.databinding:databinding-common:8.4.0 ++--- androidx.databinding:databinding-ktx:8.4.0 +| +--- androidx.databinding:databinding-runtime:8.4.0 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20 -> 1.9.23 +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.23 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.23 +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.23 (*) +| +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1 -> 1.8.1 (*) +| +--- androidx.lifecycle:lifecycle-runtime-ktx:2.6.1 -> 2.8.4 +| | \--- androidx.lifecycle:lifecycle-runtime-ktx-android:2.8.4 +| | +--- androidx.annotation:annotation:1.8.0 (*) +| | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 (*) +| | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| +--- androidx.lifecycle:lifecycle-livedata:2.6.1 -> 2.8.4 +| | +--- androidx.arch.core:core-common:2.2.0 (*) +| | +--- androidx.arch.core:core-runtime:2.2.0 (*) +| | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (*) +| | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 +| | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| +--- androidx.lifecycle:lifecycle-process:2.6.1 -> 2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-service:2.6.1 -> 2.8.4 +| | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| \--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 -> 2.8.4 (*) ++--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) ++--- androidx.compose:compose-bom:2024.06.00 +| +--- androidx.compose.material3:material3-window-size-class:1.2.1 (c) +| +--- androidx.compose.runtime:runtime:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-tooling-preview:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.foundation:foundation:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.foundation:foundation-layout:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material:material-icons-extended:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material3:material3:1.2.1 (c) +| +--- androidx.compose.ui:ui-util:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material:material:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.runtime:runtime-saveable:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.animation:animation:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.animation:animation-graphics:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material3:material3-window-size-class-android:1.2.1 (c) +| +--- androidx.compose.material:material-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material:material-icons-extended-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material3:material3-android:1.2.1 (c) +| +--- androidx.compose.ui:ui-unit:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.animation:animation-core:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material:material-icons-core:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material:material-ripple:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-text:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-graphics:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-geometry:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material:material-icons-core-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.material:material-ripple-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.foundation:foundation-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.animation:animation-core-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.runtime:runtime-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.animation:animation-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.foundation:foundation-layout-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-graphics-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-util-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.animation:animation-graphics-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.runtime:runtime-saveable-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-unit-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-geometry-android:1.6.8 -> 1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-text-android:1.6.8 -> 1.7.0-alpha04 (c) +| \--- androidx.compose.ui:ui-tooling-preview-android:1.6.8 -> 1.7.0-alpha04 (c) ++--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 +| \--- androidx.compose.ui:ui-tooling-preview-android:1.7.0-alpha04 +| +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| +--- androidx.compose.runtime:runtime:1.7.0-alpha04 +| | \--- androidx.compose.runtime:runtime-android:1.7.0-alpha04 +| | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | +--- androidx.collection:collection:1.4.0 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 +| | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.23 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | \--- androidx.compose.runtime:runtime-saveable:1.7.0-alpha04 (c) +| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| +--- androidx.compose.ui:ui:1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-geometry:1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-text:1.7.0-alpha04 (c) +| +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (c) +| \--- androidx.compose.ui:ui-util:1.7.0-alpha04 (c) ++--- com.google.dagger:hilt-android:2.51.1 +| +--- com.google.dagger:dagger:2.51.1 +| | \--- javax.inject:javax.inject:1 +| +--- com.google.dagger:dagger-lint-aar:2.51.1 +| +--- com.google.dagger:hilt-core:2.51.1 +| | +--- com.google.dagger:dagger:2.51.1 (*) +| | +--- com.google.code.findbugs:jsr305:3.0.2 +| | \--- javax.inject:javax.inject:1 +| +--- com.google.code.findbugs:jsr305:3.0.2 +| +--- androidx.activity:activity:1.5.1 -> 1.9.1 (*) +| +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| +--- androidx.annotation:annotation-experimental:1.3.1 -> 1.4.0 (*) +| +--- androidx.fragment:fragment:1.5.1 -> 1.6.2 (*) +| +--- androidx.lifecycle:lifecycle-common:2.5.1 -> 2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel:2.5.1 -> 2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.5.1 -> 2.8.4 (*) +| +--- androidx.savedstate:savedstate:1.2.0 -> 1.2.1 (*) +| +--- javax.inject:javax.inject:1 +| \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.20 -> 1.9.23 (*) ++--- com.google.firebase:firebase-bom:33.1.2 +| +--- com.google.firebase:firebase-perf-ktx:21.0.1 (c) +| +--- com.google.firebase:firebase-crashlytics-ktx:19.0.3 (c) +| +--- com.google.firebase:firebase-analytics-ktx:22.0.2 (c) +| +--- com.google.firebase:firebase-messaging-ktx:24.0.0 (c) +| +--- com.google.firebase:firebase-encoders:17.0.0 (c) +| +--- com.google.firebase:firebase-perf:21.0.1 (c) +| +--- com.google.firebase:firebase-common:21.0.0 (c) +| +--- com.google.firebase:firebase-common-ktx:21.0.0 (c) +| +--- com.google.firebase:firebase-crashlytics:19.0.3 (c) +| +--- com.google.firebase:firebase-analytics:22.0.2 (c) +| +--- com.google.firebase:firebase-messaging:24.0.0 (c) +| +--- com.google.firebase:firebase-config:22.0.0 (c) +| \--- com.google.firebase:firebase-installations:18.0.0 (c) ++--- com.google.firebase:firebase-analytics-ktx -> 22.0.2 +| +--- com.google.firebase:firebase-analytics:22.0.2 +| | +--- com.google.android.gms:play-services-measurement:22.0.2 +| | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | +--- androidx.legacy:legacy-support-core-utils:1.0.0 (*) +| | | +--- com.google.android.gms:play-services-ads-identifier:18.0.0 +| | | | \--- com.google.android.gms:play-services-basement:18.0.0 -> 18.4.0 +| | | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | | +--- androidx.core:core:1.2.0 -> 1.13.1 (*) +| | | | \--- androidx.fragment:fragment:1.1.0 -> 1.6.2 (*) +| | | +--- com.google.android.gms:play-services-basement:18.4.0 (*) +| | | +--- com.google.android.gms:play-services-measurement-base:22.0.2 +| | | | \--- com.google.android.gms:play-services-basement:18.4.0 (*) +| | | +--- com.google.android.gms:play-services-measurement-impl:22.0.2 +| | | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | | +--- androidx.core:core:1.9.0 -> 1.13.1 (*) +| | | | +--- androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 +| | | | | +--- androidx.annotation:annotation:1.6.0 -> 1.8.0 (*) +| | | | | +--- androidx.core:core-ktx:1.8.0 -> 1.13.1 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.21 -> 1.9.23 (*) +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1 -> 1.8.1 (*) +| | | | | \--- androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 (c) +| | | | +--- androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 +| | | | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | | | +--- androidx.concurrent:concurrent-futures:1.1.0 (*) +| | | | | +--- androidx.core:core-ktx:1.8.0 -> 1.13.1 (*) +| | | | | +--- androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 (*) +| | | | | +--- com.google.guava:guava:31.1-android +| | | | | | +--- com.google.guava:failureaccess:1.0.1 +| | | | | | +--- com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava +| | | | | | +--- com.google.code.findbugs:jsr305:3.0.2 +| | | | | | +--- org.checkerframework:checker-qual:3.12.0 +| | | | | | +--- com.google.errorprone:error_prone_annotations:2.11.0 -> 2.26.0 +| | | | | | \--- com.google.j2objc:j2objc-annotations:1.3 +| | | | | +--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.21 -> 1.9.23 (*) +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1 -> 1.8.1 (*) +| | | | | \--- androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 (c) +| | | | +--- com.google.android.gms:play-services-ads-identifier:18.0.0 (*) +| | | | +--- com.google.android.gms:play-services-basement:18.4.0 (*) +| | | | +--- com.google.android.gms:play-services-measurement-base:22.0.2 (*) +| | | | +--- com.google.android.gms:play-services-stats:17.0.2 +| | | | | +--- androidx.legacy:legacy-support-core-utils:1.0.0 (*) +| | | | | \--- com.google.android.gms:play-services-basement:18.0.0 -> 18.4.0 (*) +| | | | \--- com.google.guava:guava:31.1-android (*) +| | | \--- com.google.android.gms:play-services-stats:17.0.2 (*) +| | +--- com.google.android.gms:play-services-measurement-api:22.0.2 +| | | +--- com.google.android.gms:play-services-ads-identifier:18.0.0 (*) +| | | +--- com.google.android.gms:play-services-basement:18.4.0 (*) +| | | +--- com.google.android.gms:play-services-measurement-base:22.0.2 (*) +| | | +--- com.google.android.gms:play-services-measurement-sdk-api:22.0.2 +| | | | +--- com.google.android.gms:play-services-basement:18.4.0 (*) +| | | | \--- com.google.android.gms:play-services-measurement-base:22.0.2 (*) +| | | +--- com.google.android.gms:play-services-tasks:18.2.0 +| | | | \--- com.google.android.gms:play-services-basement:18.4.0 (*) +| | | +--- com.google.firebase:firebase-common:21.0.0 +| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.4 -> 1.8.1 +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (*) +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.1 (*) +| | | | | +--- com.google.android.gms:play-services-tasks:16.0.1 -> 18.2.0 (*) +| | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 1.9.23 (*) +| | | | +--- com.google.firebase:firebase-components:18.0.0 +| | | | | +--- com.google.firebase:firebase-annotations:16.2.0 +| | | | | | \--- javax.inject:javax.inject:1 +| | | | | +--- androidx.annotation:annotation:1.5.0 -> 1.8.0 (*) +| | | | | \--- com.google.errorprone:error_prone_annotations:2.26.0 +| | | | +--- com.google.firebase:firebase-annotations:16.2.0 (*) +| | | | +--- androidx.annotation:annotation:1.5.0 -> 1.8.0 (*) +| | | | +--- androidx.concurrent:concurrent-futures:1.1.0 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | +--- com.google.android.gms:play-services-basement:18.3.0 -> 18.4.0 (*) +| | | | \--- com.google.android.gms:play-services-tasks:18.1.0 -> 18.2.0 (*) +| | | +--- com.google.firebase:firebase-common-ktx:21.0.0 +| | | | +--- com.google.firebase:firebase-common:21.0.0 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 -> 1.9.23 (*) +| | | | +--- com.google.firebase:firebase-components:18.0.0 (*) +| | | | \--- com.google.firebase:firebase-annotations:16.2.0 (*) +| | | +--- com.google.firebase:firebase-components:18.0.0 (*) +| | | +--- com.google.firebase:firebase-installations:17.0.1 -> 18.0.0 +| | | | +--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| | | | +--- com.google.firebase:firebase-annotations:16.2.0 (*) +| | | | +--- com.google.firebase:firebase-common:21.0.0 (*) +| | | | +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| | | | +--- com.google.firebase:firebase-components:18.0.0 (*) +| | | | +--- com.google.firebase:firebase-installations-interop:17.1.1 -> 17.2.0 +| | | | | +--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| | | | | \--- com.google.firebase:firebase-annotations:16.2.0 (*) +| | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | +--- com.google.firebase:firebase-installations-interop:17.0.0 -> 17.2.0 (*) +| | | +--- com.google.firebase:firebase-measurement-connector:19.0.0 -> 20.0.1 +| | | | +--- com.google.android.gms:play-services-basement:18.0.0 -> 18.4.0 (*) +| | | | \--- com.google.firebase:firebase-annotations:16.0.0 -> 16.2.0 (*) +| | | +--- com.google.guava:guava:31.1-android (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.10 -> 1.9.23 (*) +| | \--- com.google.android.gms:play-services-measurement-sdk:22.0.2 +| | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | +--- com.google.android.gms:play-services-basement:18.4.0 (*) +| | +--- com.google.android.gms:play-services-measurement-base:22.0.2 (*) +| | \--- com.google.android.gms:play-services-measurement-impl:22.0.2 (*) +| +--- com.google.firebase:firebase-common:21.0.0 (*) +| +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| +--- com.google.firebase:firebase-components:18.0.0 (*) +| \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.10 -> 1.9.23 (*) ++--- com.google.firebase:firebase-perf-ktx -> 21.0.1 +| +--- com.google.firebase:firebase-perf:21.0.1 +| | +--- com.google.firebase:firebase-annotations:16.2.0 (*) +| | +--- com.google.firebase:firebase-installations-interop:17.1.0 -> 17.2.0 (*) +| | +--- com.google.firebase:protolite-well-known-types:18.0.0 +| | | \--- com.google.protobuf:protobuf-javalite:3.14.0 -> 3.25.2 +| | +--- com.google.firebase:firebase-common:21.0.0 (*) +| | +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| | +--- com.google.firebase:firebase-components:18.0.0 (*) +| | +--- com.google.firebase:firebase-config:21.5.0 -> 22.0.0 +| | | +--- com.google.firebase:firebase-config-interop:16.0.1 +| | | | +--- com.google.firebase:firebase-encoders-json:18.0.1 +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10 -> 1.9.23 (*) +| | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | \--- com.google.firebase:firebase-encoders:17.0.0 +| | | | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | \--- com.google.firebase:firebase-encoders:17.0.0 (*) +| | | +--- com.google.firebase:firebase-annotations:16.2.0 (*) +| | | +--- com.google.firebase:firebase-installations-interop:17.1.0 -> 17.2.0 (*) +| | | +--- com.google.firebase:firebase-abt:21.1.1 +| | | | +--- com.google.firebase:firebase-measurement-connector:18.0.0 -> 20.0.1 (*) +| | | | \--- com.google.android.gms:play-services-basement:18.1.0 -> 18.4.0 (*) +| | | +--- com.google.firebase:firebase-measurement-connector:18.0.0 -> 20.0.1 (*) +| | | +--- com.google.firebase:firebase-common:21.0.0 (*) +| | | +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| | | +--- com.google.firebase:firebase-components:18.0.0 (*) +| | | +--- com.google.firebase:firebase-installations:17.2.0 -> 18.0.0 (*) +| | | +--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | +--- com.google.firebase:firebase-installations:17.2.0 -> 18.0.0 (*) +| | +--- com.google.firebase:firebase-sessions:2.0.0 -> 2.0.3 +| | | +--- com.google.firebase:firebase-common:21.0.0 (*) +| | | +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| | | +--- com.google.firebase:firebase-components:18.0.0 (*) +| | | +--- com.google.firebase:firebase-installations-interop:17.2.0 (*) +| | | +--- com.google.firebase:firebase-annotations:16.2.0 (*) +| | | +--- com.google.firebase:firebase-encoders:17.0.0 (*) +| | | +--- com.google.firebase:firebase-encoders-json:18.0.1 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 -> 1.9.23 (*) +| | | +--- com.google.firebase:firebase-installations:18.0.0 (*) +| | | +--- com.google.firebase:firebase-datatransport:19.0.0 +| | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- com.google.android.datatransport:transport-api:3.1.0 -> 3.2.0 +| | | | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- com.google.android.datatransport:transport-backend-cct:3.2.0 -> 3.3.0 +| | | | | +--- com.google.android.datatransport:transport-api:3.2.0 (*) +| | | | | +--- com.google.android.datatransport:transport-runtime:3.3.0 +| | | | | | +--- com.google.android.datatransport:transport-api:3.2.0 (*) +| | | | | | +--- androidx.annotation:annotation:1.3.0 -> 1.8.0 (*) +| | | | | | +--- javax.inject:javax.inject:1 +| | | | | | +--- com.google.firebase:firebase-encoders:17.0.0 (*) +| | | | | | \--- com.google.firebase:firebase-encoders-proto:16.0.0 +| | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | | \--- com.google.firebase:firebase-encoders:17.0.0 (*) +| | | | | +--- com.google.firebase:firebase-encoders:17.0.0 (*) +| | | | | +--- com.google.firebase:firebase-encoders-json:18.0.0 -> 18.0.1 (*) +| | | | | \--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- com.google.android.datatransport:transport-runtime:3.2.0 -> 3.3.0 (*) +| | | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 -> 1.9.23 (*) +| | | +--- androidx.datastore:datastore-preferences:1.0.0 -> 1.1.1 +| | | | \--- androidx.datastore:datastore-preferences-android:1.1.1 +| | | | +--- androidx.datastore:datastore:1.1.1 +| | | | | \--- androidx.datastore:datastore-android:1.1.1 +| | | | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | | | +--- androidx.datastore:datastore-core:1.1.1 +| | | | | | \--- androidx.datastore:datastore-core-android:1.1.1 +| | | | | | +--- androidx.annotation:annotation:1.7.0 -> 1.8.0 (*) +| | | | | | +--- org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.22 +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | | | | | | \--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.9.22 +| | | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | | | | +--- androidx.datastore:datastore:1.1.1 (c) +| | | | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c) +| | | | | | +--- androidx.datastore:datastore-preferences:1.1.1 (c) +| | | | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c) +| | | | | +--- androidx.datastore:datastore-core-okio:1.1.1 +| | | | | | \--- androidx.datastore:datastore-core-okio-jvm:1.1.1 +| | | | | | +--- androidx.datastore:datastore-core:1.1.1 (*) +| | | | | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0 +| | | | | | | \--- com.squareup.okio:okio-jvm:3.8.0 +| | | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 1.9.23 (*) +| | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | | | | +--- androidx.datastore:datastore:1.1.1 (c) +| | | | | | +--- androidx.datastore:datastore-core:1.1.1 (c) +| | | | | | +--- androidx.datastore:datastore-preferences:1.1.1 (c) +| | | | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c) +| | | | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | | | +--- androidx.datastore:datastore-core:1.1.1 (c) +| | | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c) +| | | | | +--- androidx.datastore:datastore-preferences:1.1.1 (c) +| | | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c) +| | | | +--- androidx.datastore:datastore-preferences-core:1.1.1 +| | | | | \--- androidx.datastore:datastore-preferences-core-jvm:1.1.1 +| | | | | +--- androidx.datastore:datastore-core:1.1.1 (*) +| | | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (*) +| | | | | +--- com.squareup.okio:okio:3.4.0 -> 3.8.0 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | +--- androidx.datastore:datastore:1.1.1 (c) +| | | | | +--- androidx.datastore:datastore-core:1.1.1 (c) +| | | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c) +| | | | | \--- androidx.datastore:datastore-preferences:1.1.1 (c) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | | +--- androidx.datastore:datastore:1.1.1 (c) +| | | | +--- androidx.datastore:datastore-core:1.1.1 (c) +| | | | +--- androidx.datastore:datastore-core-okio:1.1.1 (c) +| | | | \--- androidx.datastore:datastore-preferences-core:1.1.1 (c) +| | | +--- com.google.android.datatransport:transport-api:3.2.0 (*) +| | | \--- androidx.annotation:annotation:1.5.0 -> 1.8.0 (*) +| | +--- com.google.firebase:firebase-datatransport:18.1.8 -> 19.0.0 (*) +| | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | +--- androidx.lifecycle:lifecycle-process:2.3.1 -> 2.8.4 (*) +| | +--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| | +--- com.google.protobuf:protobuf-javalite:3.21.11 -> 3.25.2 +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- androidx.appcompat:appcompat:1.2.0 -> 1.7.0 (*) +| | +--- com.google.android.datatransport:transport-api:3.0.0 -> 3.2.0 (*) +| | +--- com.google.dagger:dagger:2.27 -> 2.51.1 (*) +| | \--- com.squareup.okhttp3:okhttp:3.12.1 -> 4.12.0 +| | +--- com.squareup.okio:okio:3.6.0 -> 3.8.0 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21 -> 1.9.23 (*) +| +--- com.google.firebase:firebase-common:21.0.0 (*) +| +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 -> 1.9.23 (*) +| \--- com.google.firebase:firebase-components:18.0.0 (*) ++--- com.google.firebase:firebase-crashlytics-ktx -> 19.0.3 +| +--- com.google.firebase:firebase-crashlytics:19.0.3 +| | +--- com.google.firebase:firebase-sessions:2.0.3 (*) +| | +--- com.google.android.gms:play-services-tasks:18.1.0 -> 18.2.0 (*) +| | +--- com.google.firebase:firebase-annotations:16.2.0 (*) +| | +--- com.google.firebase:firebase-common:21.0.0 (*) +| | +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| | +--- com.google.firebase:firebase-components:18.0.0 (*) +| | +--- com.google.firebase:firebase-config-interop:16.0.1 (*) +| | +--- com.google.firebase:firebase-encoders:17.0.0 (*) +| | +--- com.google.firebase:firebase-encoders-json:18.0.1 (*) +| | +--- com.google.firebase:firebase-installations:18.0.0 (*) +| | +--- com.google.firebase:firebase-installations-interop:17.2.0 (*) +| | +--- com.google.firebase:firebase-measurement-connector:20.0.1 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 -> 1.9.23 (*) +| | +--- com.google.android.datatransport:transport-api:3.2.0 (*) +| | +--- com.google.android.datatransport:transport-backend-cct:3.3.0 (*) +| | +--- com.google.android.datatransport:transport-runtime:3.3.0 (*) +| | \--- androidx.annotation:annotation:1.5.0 -> 1.8.0 (*) +| +--- com.google.firebase:firebase-common:21.0.0 (*) +| +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 -> 1.9.23 (*) +| \--- com.google.firebase:firebase-components:18.0.0 (*) ++--- com.google.firebase:firebase-messaging-ktx -> 24.0.0 +| +--- com.google.firebase:firebase-messaging:24.0.0 +| | +--- com.google.firebase:firebase-common:21.0.0 (*) +| | +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| | +--- com.google.firebase:firebase-components:18.0.0 (*) +| | +--- com.google.firebase:firebase-datatransport:18.2.0 -> 19.0.0 (*) +| | +--- com.google.firebase:firebase-encoders:17.0.0 (*) +| | +--- com.google.firebase:firebase-encoders-json:18.0.0 -> 18.0.1 (*) +| | +--- com.google.firebase:firebase-encoders-proto:16.0.0 (*) +| | +--- com.google.firebase:firebase-iid-interop:17.1.0 +| | | +--- com.google.android.gms:play-services-basement:17.0.0 -> 18.4.0 (*) +| | | \--- com.google.android.gms:play-services-tasks:17.0.0 -> 18.2.0 (*) +| | +--- com.google.firebase:firebase-installations:17.2.0 -> 18.0.0 (*) +| | +--- com.google.firebase:firebase-installations-interop:17.1.0 -> 17.2.0 (*) +| | +--- com.google.firebase:firebase-measurement-connector:19.0.0 -> 20.0.1 (*) +| | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | +--- com.google.android.datatransport:transport-api:3.1.0 -> 3.2.0 (*) +| | +--- com.google.android.datatransport:transport-backend-cct:3.1.8 -> 3.3.0 (*) +| | +--- com.google.android.datatransport:transport-runtime:3.1.8 -> 3.3.0 (*) +| | +--- com.google.android.gms:play-services-base:18.0.1 -> 18.3.0 +| | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | +--- androidx.core:core:1.2.0 -> 1.13.1 (*) +| | | +--- androidx.fragment:fragment:1.0.0 -> 1.6.2 (*) +| | | +--- com.google.android.gms:play-services-basement:18.3.0 -> 18.4.0 (*) +| | | \--- com.google.android.gms:play-services-tasks:18.1.0 -> 18.2.0 (*) +| | +--- com.google.android.gms:play-services-basement:18.1.0 -> 18.4.0 (*) +| | +--- com.google.android.gms:play-services-cloud-messaging:17.2.0 +| | | +--- com.google.android.gms:play-services-basement:18.3.0 -> 18.4.0 (*) +| | | \--- com.google.android.gms:play-services-tasks:18.1.0 -> 18.2.0 (*) +| | +--- com.google.android.gms:play-services-stats:17.0.2 (*) +| | +--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| | +--- com.google.errorprone:error_prone_annotations:2.9.0 -> 2.26.0 +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| +--- com.google.firebase:firebase-common:21.0.0 (*) +| +--- com.google.firebase:firebase-common-ktx:21.0.0 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 -> 1.9.23 (*) +| \--- com.google.firebase:firebase-components:18.0.0 (*) ++--- project :core:data +| +--- project :core:common +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 +| | | +--- androidx.tracing:tracing:1.3.0-alpha02 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | \--- androidx.tracing:tracing:1.3.0-alpha02 (c) +| | +--- com.google.dagger:hilt-android:2.51.1 (*) +| | +--- androidx.core:core-ktx:1.13.1 (*) +| | +--- androidx.appcompat:appcompat:1.7.0 (*) +| | \--- com.google.android.material:material:1.11.0 (*) +| +--- project :core:model +| | +--- org.jetbrains.kotlinx:kotlinx-datetime:0.5.0 +| | | \--- org.jetbrains.kotlinx:kotlinx-datetime-jvm:0.5.0 +| | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| | +--- com.squareup.retrofit2:converter-gson:2.9.0 +| | | +--- com.squareup.retrofit2:retrofit:2.9.0 +| | | | \--- com.squareup.okhttp3:okhttp:3.14.9 -> 4.12.0 (*) +| | | \--- com.google.code.gson:gson:2.8.5 +| | +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3 +| | | \--- org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.6.3 +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | | +--- org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.3 +| | | | +--- org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.3 (c) +| | | | +--- org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.6.3 (c) +| | | | +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3 (c) +| | | | \--- org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.6.3 (c) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.9.22 -> 1.9.23 (*) +| | | \--- org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.3 +| | | \--- org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.6.3 +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | | +--- org.jetbrains.kotlinx:kotlinx-serialization-bom:1.6.3 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.9.22 -> 1.9.23 (*) +| | \--- org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.22 (*) +| +--- project :core:network +| | +--- org.jetbrains.kotlinx:kotlinx-datetime:0.5.0 (*) +| | +--- project :core:common (*) +| | +--- project :core:model (*) +| | +--- project :core:datastore +| | | +--- org.jetbrains.kotlinx:kotlinx-datetime:0.5.0 (*) +| | | +--- androidx.datastore:datastore:1.1.1 (*) +| | | +--- project :core:datastore-proto +| | | | +--- com.google.protobuf:protobuf-kotlin-lite:3.25.2 +| | | | | +--- com.google.protobuf:protobuf-javalite:3.25.2 +| | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.6.0 -> 1.9.23 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | | | \--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| | | +--- project :core:common (*) +| | | +--- project :core:model (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | | +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| | | +--- com.google.dagger:hilt-android:2.51.1 (*) +| | | \--- com.squareup.retrofit2:converter-gson:2.9.0 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| | +--- com.google.dagger:hilt-android:2.51.1 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3 (*) +| | +--- com.squareup.okhttp3:okhttp:4.12.0 (*) +| | +--- com.squareup.okhttp3:logging-interceptor:4.12.0 +| | | +--- com.squareup.okhttp3:okhttp:4.12.0 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21 -> 1.9.23 (*) +| | +--- com.squareup.retrofit2:retrofit:2.9.0 (*) +| | +--- com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0 +| | | +--- com.squareup.retrofit2:retrofit:2.9.0 (*) +| | | +--- org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.0 -> 1.6.3 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10 -> 1.9.23 (*) +| | +--- com.squareup.retrofit2:adapter-rxjava:2.9.0 +| | | +--- com.squareup.retrofit2:retrofit:2.9.0 (*) +| | | \--- io.reactivex:rxjava:1.3.8 +| | +--- com.squareup.retrofit2:converter-gson:2.9.0 (*) +| | +--- io.reactivex:rxandroid:1.1.0 +| | | \--- io.reactivex:rxjava:1.1.0 -> 1.3.8 +| | \--- io.reactivex:rxjava:1.3.8 +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- com.squareup.retrofit2:retrofit:2.9.0 (*) +| +--- com.squareup.retrofit2:adapter-rxjava:2.9.0 (*) +| +--- com.squareup.retrofit2:converter-gson:2.9.0 (*) +| +--- com.squareup.okhttp3:okhttp:4.12.0 (*) +| +--- com.squareup.okhttp3:logging-interceptor:4.12.0 (*) +| +--- io.reactivex:rxandroid:1.1.0 (*) +| +--- io.reactivex:rxjava:1.3.8 +| \--- org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.22 (*) ++--- androidx.constraintlayout:constraintlayout:2.1.4 (*) ++--- project :core:ui +| +--- project :core:designsystem +| | +--- androidx.compose.foundation:foundation -> 1.7.0-alpha04 +| | | \--- androidx.compose.foundation:foundation-android:1.7.0-alpha04 +| | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | +--- androidx.collection:collection:1.4.0 (*) +| | | +--- androidx.compose.animation:animation:1.7.0-alpha04 +| | | | \--- androidx.compose.animation:animation-android:1.7.0-alpha04 +| | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | +--- androidx.compose.animation:animation-core:1.7.0-alpha04 +| | | | | \--- androidx.compose.animation:animation-core-android:1.7.0-alpha04 +| | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | | +--- androidx.compose.ui:ui:1.6.0 -> 1.7.0-alpha04 +| | | | | | \--- androidx.compose.ui:ui-android:1.7.0-alpha04 +| | | | | | +--- androidx.activity:activity-ktx:1.7.0 -> 1.9.1 +| | | | | | | +--- androidx.activity:activity:1.9.1 (*) +| | | | | | | +--- androidx.core:core-ktx:1.13.0 -> 1.13.1 (*) +| | | | | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.6.1 -> 2.8.4 (*) +| | | | | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1 -> 2.8.4 +| | | | | | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (*) +| | | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 (*) +| | | | | | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | | | | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | | | | | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | | | | | | +--- androidx.savedstate:savedstate-ktx:1.2.1 +| | | | | | | | +--- androidx.savedstate:savedstate:1.2.1 (*) +| | | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.9.23 (*) +| | | | | | | | \--- androidx.savedstate:savedstate:1.2.1 (c) +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | | +--- androidx.activity:activity:1.9.1 (c) +| | | | | | | \--- androidx.activity:activity-compose:1.9.1 (c) +| | | | | | +--- androidx.annotation:annotation:1.6.0 -> 1.8.0 (*) +| | | | | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | | | | +--- androidx.autofill:autofill:1.0.0 +| | | | | | | \--- androidx.core:core:1.1.0 -> 1.13.1 (*) +| | | | | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | | | +--- androidx.compose.runtime:runtime-saveable:1.7.0-alpha04 +| | | | | | | \--- androidx.compose.runtime:runtime-saveable-android:1.7.0-alpha04 +| | | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | | | \--- androidx.compose.runtime:runtime:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-geometry:1.7.0-alpha04 +| | | | | | | \--- androidx.compose.ui:ui-geometry-android:1.7.0-alpha04 +| | | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 +| | | | | | | | \--- androidx.compose.ui:ui-util-android:1.7.0-alpha04 +| | | | | | | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | | | | +--- androidx.compose.ui:ui:1.7.0-alpha04 (c) +| | | | | | | | +--- androidx.compose.ui:ui-geometry:1.7.0-alpha04 (c) +| | | | | | | | +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 (c) +| | | | | | | | +--- androidx.compose.ui:ui-text:1.7.0-alpha04 (c) +| | | | | | | | +--- androidx.compose.ui:ui-tooling-preview:1.7.0-alpha04 (c) +| | | | | | | | \--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (c) +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | | | +--- androidx.compose.ui:ui:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-text:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-tooling-preview:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (c) +| | | | | | | \--- androidx.compose.ui:ui-util:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 +| | | | | | | \--- androidx.compose.ui:ui-graphics-android:1.7.0-alpha04 +| | | | | | | +--- androidx.annotation:annotation:1.7.0 -> 1.8.0 (*) +| | | | | | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | | | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | | | | +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 +| | | | | | | | \--- androidx.compose.ui:ui-unit-android:1.7.0-alpha04 +| | | | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | | | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | | | | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | | | | | +--- androidx.collection:collection-ktx:1.2.0 -> 1.4.0 +| | | | | | | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | | | | | | \--- androidx.collection:collection:1.4.0 (c) +| | | | | | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | | | | | +--- androidx.compose.ui:ui-geometry:1.7.0-alpha04 (*) +| | | | | | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (*) +| | | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | | | | +--- androidx.compose.ui:ui:1.7.0-alpha04 (c) +| | | | | | | | +--- androidx.compose.ui:ui-geometry:1.7.0-alpha04 (c) +| | | | | | | | +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 (c) +| | | | | | | | +--- androidx.compose.ui:ui-text:1.7.0-alpha04 (c) +| | | | | | | | +--- androidx.compose.ui:ui-tooling-preview:1.7.0-alpha04 (c) +| | | | | | | | \--- androidx.compose.ui:ui-util:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (*) +| | | | | | | +--- androidx.graphics:graphics-path:1.0.0-beta02 +| | | | | | | | +--- androidx.core:core:1.12.0 -> 1.13.1 (*) +| | | | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | | | +--- androidx.compose.ui:ui:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-geometry:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-text:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-tooling-preview:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (c) +| | | | | | | \--- androidx.compose.ui:ui-util:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-text:1.7.0-alpha04 +| | | | | | | \--- androidx.compose.ui:ui-text-android:1.7.0-alpha04 +| | | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | | | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | | | | +--- androidx.compose.runtime:runtime-saveable:1.6.0 -> 1.7.0-alpha04 (*) +| | | | | | | +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 (*) +| | | | | | | +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (*) +| | | | | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (*) +| | | | | | | +--- androidx.core:core:1.7.0 -> 1.13.1 (*) +| | | | | | | +--- androidx.emoji2:emoji2:1.2.0 -> 1.3.0 (*) +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | | | | | +--- androidx.compose.ui:ui:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-geometry:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-tooling-preview:1.7.0-alpha04 (c) +| | | | | | | +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (c) +| | | | | | | \--- androidx.compose.ui:ui-util:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (*) +| | | | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (*) +| | | | | | +--- androidx.core:core:1.12.0 -> 1.13.1 (*) +| | | | | | +--- androidx.customview:customview-poolingcontainer:1.0.0 (*) +| | | | | | +--- androidx.emoji2:emoji2:1.2.0 -> 1.3.0 (*) +| | | | | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 -> 2.8.4 (*) +| | | | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 -> 2.8.4 (*) +| | | | | | +--- androidx.profileinstaller:profileinstaller:1.3.0 -> 1.3.1 (*) +| | | | | | +--- androidx.savedstate:savedstate-ktx:1.2.1 (*) +| | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 (*) +| | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | | | | +--- androidx.compose.ui:ui-geometry:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-text:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-tooling-preview:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (c) +| | | | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (c) +| | | | | | \--- androidx.compose.foundation:foundation:1.4.0 -> 1.7.0-alpha04 (c) +| | | | | +--- androidx.compose.ui:ui-graphics:1.7.0-alpha04 (*) +| | | | | +--- androidx.compose.ui:ui-unit:1.6.0 -> 1.7.0-alpha04 (*) +| | | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | | | +--- androidx.compose.animation:animation:1.7.0-alpha04 (c) +| | | | | \--- androidx.compose.animation:animation-graphics:1.7.0-alpha04 (c) +| | | | +--- androidx.compose.foundation:foundation-layout:1.6.0 -> 1.7.0-alpha04 +| | | | | \--- androidx.compose.foundation:foundation-layout-android:1.7.0-alpha04 +| | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | | +--- androidx.compose.animation:animation-core:1.2.1 -> 1.7.0-alpha04 (*) +| | | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | | +--- androidx.compose.ui:ui:1.6.0 -> 1.7.0-alpha04 (*) +| | | | | +--- androidx.compose.ui:ui-unit:1.7.0-alpha04 (*) +| | | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (*) +| | | | | +--- androidx.core:core:1.7.0 -> 1.13.1 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | | \--- androidx.compose.foundation:foundation:1.7.0-alpha04 (c) +| | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | +--- androidx.compose.ui:ui:1.6.0 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.compose.ui:ui-geometry:1.6.0 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | +--- androidx.compose.animation:animation-core:1.7.0-alpha04 (c) +| | | | \--- androidx.compose.animation:animation-graphics:1.7.0-alpha04 (c) +| | | +--- androidx.compose.foundation:foundation-layout:1.7.0-alpha04 (*) +| | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui:1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-text:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-util:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.core:core:1.12.0 -> 1.13.1 (*) +| | | +--- androidx.emoji2:emoji2:1.3.0 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | \--- androidx.compose.foundation:foundation-layout:1.7.0-alpha04 (c) +| | +--- androidx.compose.foundation:foundation-layout -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.material:material-icons-extended -> 1.7.0-alpha04 +| | | \--- androidx.compose.material:material-icons-extended-android:1.7.0-alpha04 +| | | +--- androidx.compose.material:material-icons-core:1.7.0-alpha04 +| | | | \--- androidx.compose.material:material-icons-core-android:1.7.0-alpha04 +| | | | +--- androidx.compose.ui:ui:1.6.0 -> 1.7.0-alpha04 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | +--- androidx.compose.material:material:1.7.0-alpha04 (c) +| | | | +--- androidx.compose.material:material-icons-extended:1.7.0-alpha04 (c) +| | | | +--- androidx.compose.material:material-ripple:1.7.0-alpha04 (c) +| | | | \--- androidx.compose.material:material-navigation:1.7.0-alpha04 (c) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | +--- androidx.compose.material:material:1.7.0-alpha04 (c) +| | | +--- androidx.compose.material:material-icons-core:1.7.0-alpha04 (c) +| | | +--- androidx.compose.material:material-ripple:1.7.0-alpha04 (c) +| | | \--- androidx.compose.material:material-navigation:1.7.0-alpha04 (c) +| | +--- androidx.compose.material3:material3 -> 1.2.1 +| | | \--- androidx.compose.material3:material3-android:1.2.1 +| | | +--- androidx.activity:activity-compose:1.5.0 -> 1.9.1 +| | | | +--- androidx.activity:activity-ktx:1.9.1 (*) +| | | | +--- androidx.compose.runtime:runtime:1.0.1 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.compose.runtime:runtime-saveable:1.0.1 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.compose.ui:ui:1.0.1 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 -> 2.8.4 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | +--- androidx.activity:activity:1.9.1 (c) +| | | | \--- androidx.activity:activity-ktx:1.9.1 (c) +| | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | +--- androidx.collection:collection:1.4.0 (*) +| | | +--- androidx.compose.animation:animation-core:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.foundation:foundation:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.foundation:foundation-layout:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.material:material-icons-core:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.material:material-ripple:1.6.0 -> 1.7.0-alpha04 +| | | | \--- androidx.compose.material:material-ripple-android:1.7.0-alpha04 +| | | | +--- androidx.collection:collection:1.4.0 (*) +| | | | +--- androidx.compose.animation:animation:1.6.0 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.compose.foundation:foundation:1.6.0 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | | +--- androidx.compose.ui:ui-util:1.6.0 -> 1.7.0-alpha04 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | | +--- androidx.compose.material:material:1.7.0-alpha04 (c) +| | | | +--- androidx.compose.material:material-icons-core:1.7.0-alpha04 (c) +| | | | +--- androidx.compose.material:material-icons-extended:1.7.0-alpha04 (c) +| | | | \--- androidx.compose.material:material-navigation:1.7.0-alpha04 (c) +| | | +--- androidx.compose.runtime:runtime:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-graphics:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-text:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-util:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.lifecycle:lifecycle-common-java8:2.6.1 -> 2.8.4 +| | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | | \--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 -> 2.8.4 (*) +| | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 -> 2.8.4 (*) +| | | +--- androidx.savedstate:savedstate-ktx:1.2.1 (*) +| | | \--- androidx.compose.material3:material3-window-size-class:1.2.1 (c) +| | +--- androidx.compose.runtime:runtime:1.6.8 -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.ui:ui-util:1.6.8 -> 1.7.0-alpha04 (*) +| | +--- androidx.activity:activity-compose:1.9.1 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| | +--- androidx.compose:compose-bom:2024.06.00 (*) +| | +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| | \--- project :core:model (*) +| +--- project :core:model (*) +| +--- project :core:common (*) +| +--- androidx.metrics:metrics-performance:1.0.0-beta01 +| | +--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | +--- androidx.core:core:1.5.0 -> 1.13.1 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| +--- project :core:analytics +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| | +--- androidx.compose:compose-bom:2024.06.00 (*) +| | +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| | +--- com.google.dagger:hilt-android:2.51.1 (*) +| | +--- androidx.compose.runtime:runtime:1.6.8 -> 1.7.0-alpha04 (*) +| | +--- com.google.firebase:firebase-bom:33.1.2 (*) +| | \--- com.google.firebase:firebase-analytics-ktx -> 22.0.2 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- com.google.accompanist:accompanist-pager:0.34.0 +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4 -> 1.8.1 (*) +| | +--- androidx.compose.foundation:foundation:1.6.0 -> 1.7.0-alpha04 (*) +| | +--- dev.chrisbanes.snapper:snapper:0.2.2 -> 0.3.0 +| | | +--- androidx.compose.foundation:foundation:1.2.1 -> 1.7.0-alpha04 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21 -> 1.9.23 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.browser:browser:1.8.0 +| | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | +--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | +--- androidx.concurrent:concurrent-futures:1.0.0 -> 1.1.0 (*) +| | +--- androidx.core:core:1.1.0 -> 1.13.1 (*) +| | +--- androidx.interpolator:interpolator:1.0.0 (*) +| | \--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| +--- io.coil-kt:coil:2.6.0 +| | +--- io.coil-kt:coil-base:2.6.0 +| | | +--- androidx.annotation:annotation:1.7.1 -> 1.8.0 (*) +| | | +--- androidx.appcompat:appcompat-resources:1.6.1 -> 1.7.0 (*) +| | | +--- androidx.collection:collection:1.4.0 (*) +| | | +--- androidx.core:core-ktx:1.12.0 -> 1.13.1 (*) +| | | +--- androidx.exifinterface:exifinterface:1.3.7 +| | | | \--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | +--- androidx.profileinstaller:profileinstaller:1.3.1 (*) +| | | +--- androidx.lifecycle:lifecycle-runtime:2.7.0 -> 2.8.4 (*) +| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | | +--- com.squareup.okhttp3:okhttp:4.12.0 (*) +| | | \--- com.squareup.okio:okio:3.8.0 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| \--- io.coil-kt:coil-compose:2.6.0 +| +--- io.coil-kt:coil-compose-base:2.6.0 +| | +--- androidx.core:core-ktx:1.12.0 -> 1.13.1 (*) +| | +--- com.google.accompanist:accompanist-drawablepainter:0.32.0 +| | | +--- androidx.compose.ui:ui:1.5.0 -> 1.7.0-alpha04 (*) +| | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4 -> 1.8.1 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0 -> 1.9.23 (*) +| | +--- io.coil-kt:coil-base:2.6.0 (*) +| | +--- androidx.compose.foundation:foundation:1.6.1 -> 1.7.0-alpha04 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- io.coil-kt:coil:2.6.0 (*) +| \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) ++--- project :core:designsystem (*) ++--- androidx.appcompat:appcompat:1.7.0 (*) ++--- androidx.core:core-ktx:1.13.1 (*) ++--- androidx.activity:activity-ktx:1.9.1 (*) ++--- androidx.fragment:fragment-ktx:1.6.2 +| +--- androidx.activity:activity-ktx:1.5.1 -> 1.9.1 (*) +| +--- androidx.collection:collection-ktx:1.1.0 -> 1.4.0 (*) +| +--- androidx.core:core-ktx:1.2.0 -> 1.13.1 (*) +| +--- androidx.fragment:fragment:1.6.2 (*) +| +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.6.1 -> 2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1 -> 2.8.4 (*) +| +--- androidx.savedstate:savedstate-ktx:1.2.1 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.20 -> 1.9.23 (*) +| \--- androidx.fragment:fragment:1.6.2 (c) ++--- androidx.swiperefreshlayout:swiperefreshlayout:1.1.0 +| +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| +--- androidx.core:core:1.1.0 -> 1.13.1 (*) +| \--- androidx.interpolator:interpolator:1.0.0 (*) ++--- androidx.recyclerview:recyclerview:1.3.2 (*) ++--- project :feature:receipt +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | +--- org.jetbrains.compose.material:material:1.6.1 +| | | \--- androidx.compose.material:material:1.6.3 -> 1.7.0-alpha04 +| | | \--- androidx.compose.material:material-android:1.7.0-alpha04 +| | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | +--- androidx.compose.animation:animation:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.animation:animation-core:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.animation:animation-core:1.7.0-alpha04 (*) +| | | +--- androidx.compose.foundation:foundation:1.7.0-alpha04 (*) +| | | +--- androidx.compose.foundation:foundation-layout:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.material:material-icons-core:1.7.0-alpha04 (*) +| | | +--- androidx.compose.material:material-ripple:1.7.0-alpha04 (*) +| | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-text:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-util:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 -> 2.8.4 (*) +| | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 -> 2.8.4 (*) +| | | +--- androidx.savedstate:savedstate:1.2.1 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | +--- androidx.compose.material:material-icons-core:1.7.0-alpha04 (c) +| | | +--- androidx.compose.material:material-icons-extended:1.7.0-alpha04 (c) +| | | +--- androidx.compose.material:material-ripple:1.7.0-alpha04 (c) +| | | \--- androidx.compose.material:material-navigation:1.7.0-alpha04 (c) +| | \--- org.jetbrains.compose.material3:material3:1.6.1 +| | \--- androidx.compose.material3:material3:1.2.1 (*) +| +--- project :desktop +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| | +--- project :shared (*) +| | \--- org.jetbrains.compose.desktop:desktop-jvm-windows-x64:1.6.1 +| | +--- org.jetbrains.compose.desktop:desktop:1.6.1 +| | | \--- org.jetbrains.compose.desktop:desktop-jvm:1.6.1 +| | | +--- org.jetbrains.compose.foundation:foundation:1.6.1 +| | | | \--- androidx.compose.foundation:foundation:1.6.3 -> 1.7.0-alpha04 (*) +| | | +--- org.jetbrains.compose.material:material:1.6.1 (*) +| | | +--- org.jetbrains.compose.runtime:runtime:1.6.1 +| | | | \--- androidx.compose.runtime:runtime:1.6.3 -> 1.7.0-alpha04 (*) +| | | +--- org.jetbrains.compose.ui:ui:1.6.1 +| | | | \--- androidx.compose.ui:ui:1.6.3 -> 1.7.0-alpha04 (*) +| | | +--- org.jetbrains.compose.ui:ui-tooling-preview:1.6.1 +| | | | \--- androidx.compose.ui:ui-tooling-preview:1.6.3 -> 1.7.0-alpha04 (*) +| | | +--- org.jetbrains.compose.ui:ui-util:1.6.1 +| | | | \--- androidx.compose.ui:ui-util:1.6.3 -> 1.7.0-alpha04 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.23 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.9.23 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.23 (*) +| | | \--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0 -> 1.8.1 (*) +| | \--- org.jetbrains.skiko:skiko-awt-runtime-windows-x64:0.7.97 +| | \--- org.jetbrains.skiko:skiko-awt:0.7.97 +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.8.0 -> 1.8.1 (*) +| | \--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0 -> 1.8.1 (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 +| | +--- androidx.compose.material:material:1.7.0-alpha04 (*) +| | +--- androidx.navigation:navigation-compose:2.7.7 +| | | +--- androidx.activity:activity-compose:1.7.0 -> 1.9.1 (*) +| | | +--- androidx.compose.animation:animation:1.5.1 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.foundation:foundation-layout:1.5.1 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.runtime:runtime:1.5.1 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.runtime:runtime-saveable:1.5.1 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui:1.5.1 -> 1.7.0-alpha04 (*) +| | | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2 -> 2.8.4 +| | | | \--- androidx.lifecycle:lifecycle-viewmodel-compose-android:2.8.4 +| | | | +--- androidx.annotation:annotation:1.8.0 (*) +| | | | +--- androidx.compose.runtime:runtime:1.6.0 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.compose.ui:ui:1.6.0 -> 1.7.0-alpha04 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (*) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (*) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | | | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| | | +--- androidx.navigation:navigation-runtime-ktx:2.7.7 +| | | | +--- androidx.navigation:navigation-common-ktx:2.7.7 +| | | | | +--- androidx.navigation:navigation-common:2.7.7 +| | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | | | | +--- androidx.collection:collection-ktx:1.1.0 -> 1.4.0 (*) +| | | | | | +--- androidx.core:core-ktx:1.1.0 -> 1.13.1 (*) +| | | | | | +--- androidx.lifecycle:lifecycle-common:2.6.2 -> 2.8.4 (*) +| | | | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.6.2 -> 2.8.4 (*) +| | | | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2 -> 2.8.4 (*) +| | | | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.2 -> 2.8.4 (*) +| | | | | | +--- androidx.profileinstaller:profileinstaller:1.3.0 -> 1.3.1 (*) +| | | | | | +--- androidx.savedstate:savedstate-ktx:1.2.1 (*) +| | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | | +--- androidx.navigation:navigation-common-ktx:2.7.7 (c) +| | | | | | +--- androidx.navigation:navigation-compose:2.7.7 (c) +| | | | | | +--- androidx.navigation:navigation-runtime:2.7.7 (c) +| | | | | | \--- androidx.navigation:navigation-runtime-ktx:2.7.7 (c) +| | | | | +--- androidx.navigation:navigation-common:2.7.7 (c) +| | | | | +--- androidx.navigation:navigation-compose:2.7.7 (c) +| | | | | +--- androidx.navigation:navigation-runtime:2.7.7 (c) +| | | | | \--- androidx.navigation:navigation-runtime-ktx:2.7.7 (c) +| | | | +--- androidx.navigation:navigation-runtime:2.7.7 +| | | | | +--- androidx.activity:activity-ktx:1.7.1 -> 1.9.1 (*) +| | | | | +--- androidx.annotation:annotation-experimental:1.1.0 -> 1.4.0 (*) +| | | | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | | | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.6.2 -> 2.8.4 (*) +| | | | | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2 -> 2.8.4 (*) +| | | | | +--- androidx.navigation:navigation-common:2.7.7 (*) +| | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | | | +--- androidx.navigation:navigation-common:2.7.7 (c) +| | | | | +--- androidx.navigation:navigation-common-ktx:2.7.7 (c) +| | | | | +--- androidx.navigation:navigation-compose:2.7.7 (c) +| | | | | \--- androidx.navigation:navigation-runtime-ktx:2.7.7 (c) +| | | | +--- androidx.navigation:navigation-common-ktx:2.7.7 (c) +| | | | +--- androidx.navigation:navigation-compose:2.7.7 (c) +| | | | +--- androidx.navigation:navigation-runtime:2.7.7 (c) +| | | | \--- androidx.navigation:navigation-common:2.7.7 (c) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | +--- androidx.navigation:navigation-runtime-ktx:2.7.7 (c) +| | | +--- androidx.navigation:navigation-runtime:2.7.7 (c) +| | | +--- androidx.navigation:navigation-common-ktx:2.7.7 (c) +| | | \--- androidx.navigation:navigation-common:2.7.7 (c) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- androidx.compose.material:material:1.7.0-alpha04 (c) +| | +--- androidx.compose.material:material-icons-extended:1.7.0-alpha04 (c) +| | +--- androidx.compose.material:material-icons-core:1.7.0-alpha04 (c) +| | \--- androidx.compose.material:material-ripple:1.7.0-alpha04 (c) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 +| | +--- androidx.compose.runtime:runtime:1.0.1 -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.ui:ui:1.0.1 -> 1.7.0-alpha04 (*) +| | +--- androidx.hilt:hilt-navigation:1.2.0 +| | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | +--- androidx.navigation:navigation-runtime:2.5.1 -> 2.7.7 (*) +| | | +--- com.google.dagger:hilt-android:2.49 -> 2.51.1 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1 -> 2.8.4 (*) +| | +--- androidx.navigation:navigation-compose:2.5.1 -> 2.7.7 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 +| | \--- androidx.lifecycle:lifecycle-runtime-compose-android:2.8.4 +| | +--- androidx.annotation:annotation:1.8.0 (*) +| | +--- androidx.compose.runtime:runtime:1.6.5 -> 1.7.0-alpha04 (*) +| | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (*) +| | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (*) +| | +--- androidx.lifecycle:lifecycle-common:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata-core:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-livedata-core-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-process:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-runtime-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-service:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (c) +| | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 (c) +| | \--- androidx.lifecycle:lifecycle-common-java8:2.8.4 (c) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- com.squareup.okhttp3:okhttp:4.12.0 (*) +| \--- project :core:data (*) ++--- project :feature:profile +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| +--- com.github.jump-sdk:jetpack_compose_country_code_picker_emoji:2.2.8 +| | +--- androidx.core:core-ktx:1.12.0 -> 1.13.1 (*) +| | +--- androidx.lifecycle:lifecycle-runtime-compose:2.7.0 -> 2.8.4 (*) +| | +--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0 -> 2.8.4 (*) +| | +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0 -> 2.8.4 (*) +| | +--- androidx.activity:activity-compose:1.8.2 -> 1.9.1 (*) +| | +--- androidx.compose.material:material:1.6.0 -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.ui:ui-tooling-preview:1.6.0 -> 1.7.0-alpha04 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7 +| | | \--- org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm:0.3.7 +| | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 1.9.23 (*) +| | +--- io.michaelrocks:libphonenumber-android:8.13.28 +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.compose.material:material:1.6.0 -> 1.7.0-alpha04 (*) +| \--- io.coil-kt:coil-compose:2.6.0 (*) ++--- project :feature:auth +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| +--- com.github.jump-sdk:jetpack_compose_country_code_picker_emoji:2.2.8 (*) +| +--- androidx.compose.material:material:1.6.0 -> 1.7.0-alpha04 (*) +| +--- androidx.credentials:credentials:1.2.2 -> 1.3.0-beta01 +| | +--- androidx.annotation:annotation:1.5.0 -> 1.8.0 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | \--- androidx.credentials:credentials-play-services-auth:1.3.0-beta01 (c) +| +--- androidx.credentials:credentials-play-services-auth:1.2.2 -> 1.3.0-beta01 +| | +--- androidx.credentials:credentials:1.3.0-beta01 (*) +| | +--- com.google.android.gms:play-services-auth:21.1.1 -> 21.2.0 +| | | +--- androidx.fragment:fragment:1.5.7 -> 1.6.2 (*) +| | | +--- androidx.loader:loader:1.1.0 (*) +| | | +--- com.google.android.gms:play-services-auth-api-phone:18.0.2 +| | | | +--- com.google.android.gms:play-services-base:18.0.1 -> 18.3.0 (*) +| | | | +--- com.google.android.gms:play-services-basement:18.0.2 -> 18.4.0 (*) +| | | | \--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| | | +--- com.google.android.gms:play-services-auth-base:18.0.10 +| | | | +--- androidx.collection:collection:1.0.0 -> 1.4.0 (*) +| | | | +--- com.google.android.gms:play-services-base:18.0.1 -> 18.3.0 (*) +| | | | +--- com.google.android.gms:play-services-basement:18.2.0 -> 18.4.0 (*) +| | | | \--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| | | +--- com.google.android.gms:play-services-base:18.3.0 (*) +| | | +--- com.google.android.gms:play-services-basement:18.3.0 -> 18.4.0 (*) +| | | +--- com.google.android.gms:play-services-fido:20.0.1 -> 21.0.0 +| | | | +--- com.google.android.gms:play-services-base:18.3.0 (*) +| | | | +--- com.google.android.gms:play-services-basement:18.3.0 -> 18.4.0 (*) +| | | | +--- com.google.android.gms:play-services-tasks:18.1.0 -> 18.2.0 (*) +| | | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0 -> 1.9.23 (*) +| | | | \--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3 -> 1.8.1 (*) +| | | \--- com.google.android.gms:play-services-tasks:18.1.0 -> 18.2.0 (*) +| | +--- com.google.android.gms:play-services-fido:21.0.0 (*) +| | +--- com.google.android.libraries.identity.googleid:googleid:1.1.0 -> 1.1.1 +| | | +--- androidx.credentials:credentials:1.3.0-beta01 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.0 -> 1.9.23 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | \--- androidx.credentials:credentials:1.3.0-beta01 (c) +| +--- com.google.android.libraries.identity.googleid:googleid:1.1.1 (*) +| \--- com.google.android.gms:play-services-auth:21.2.0 (*) ++--- project :feature:passcode +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- androidx.core:core-ktx:1.13.1 (*) ++--- project :feature:make-transfer +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- project :core:data (*) ++--- project :feature:faq +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| \--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) ++--- project :feature:editpassword +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- project :core:data (*) ++--- project :feature:notification +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| +--- androidx.appcompat:appcompat:1.7.0 (*) +| \--- androidx.compose.material:material:1.6.0 -> 1.7.0-alpha04 (*) ++--- project :feature:request-money +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| +--- com.google.zxing:core:3.5.3 +| \--- io.coil-kt:coil-compose:2.6.0 (*) ++--- project :feature:upi-setup +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- project :core:data (*) ++--- project :feature:settings +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- project :core:data (*) ++--- project :feature:savedcards +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- project :core:data (*) ++--- project :feature:qr +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- com.google.zxing:core:3.5.3 +| +--- project :core:data (*) +| +--- androidx.camera:camera-view:1.3.4 +| | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | +--- androidx.annotation:annotation-experimental:1.3.1 -> 1.4.0 (*) +| | +--- androidx.appcompat:appcompat:1.1.0 -> 1.7.0 (*) +| | +--- androidx.camera:camera-core:1.3.4 +| | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | +--- androidx.annotation:annotation-experimental:1.1.0 -> 1.4.0 (*) +| | | +--- androidx.concurrent:concurrent-futures:1.0.0 -> 1.1.0 (*) +| | | +--- androidx.core:core:1.1.0 -> 1.13.1 (*) +| | | +--- androidx.exifinterface:exifinterface:1.3.2 -> 1.3.7 (*) +| | | +--- androidx.lifecycle:lifecycle-common:2.1.0 -> 2.8.4 (*) +| | | +--- androidx.lifecycle:lifecycle-livedata:2.1.0 -> 2.8.4 (*) +| | | +--- com.google.auto.value:auto-value-annotations:1.6.3 +| | | +--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | | +--- androidx.camera:camera-lifecycle:1.3.4 (c) +| | | +--- androidx.camera:camera-video:1.3.4 (c) +| | | \--- androidx.camera:camera-view:1.3.4 (c) +| | +--- androidx.camera:camera-lifecycle:1.3.4 +| | | +--- androidx.camera:camera-core:1.3.4 (*) +| | | +--- androidx.concurrent:concurrent-futures:1.0.0 -> 1.1.0 (*) +| | | +--- androidx.core:core:1.1.0 -> 1.13.1 (*) +| | | +--- androidx.lifecycle:lifecycle-common:2.1.0 -> 2.8.4 (*) +| | | +--- com.google.auto.value:auto-value-annotations:1.6.3 +| | | +--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| | | +--- androidx.camera:camera-core:1.3.4 (c) +| | | +--- androidx.camera:camera-video:1.3.4 (c) +| | | \--- androidx.camera:camera-view:1.3.4 (c) +| | +--- androidx.camera:camera-video:1.3.4 +| | | +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| | | +--- androidx.camera:camera-core:1.3.4 (*) +| | | +--- androidx.concurrent:concurrent-futures:1.0.0 -> 1.1.0 (*) +| | | +--- androidx.core:core:1.1.0 -> 1.13.1 (*) +| | | +--- com.google.auto.value:auto-value-annotations:1.6.3 +| | | +--- androidx.camera:camera-core:1.3.4 (c) +| | | +--- androidx.camera:camera-lifecycle:1.3.4 (c) +| | | \--- androidx.camera:camera-view:1.3.4 (c) +| | +--- androidx.concurrent:concurrent-futures:1.0.0 -> 1.1.0 (*) +| | +--- androidx.core:core:1.3.2 -> 1.13.1 (*) +| | +--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.8.4 (*) +| | +--- com.google.auto.value:auto-value-annotations:1.6.3 +| | +--- com.google.guava:listenablefuture:1.0 -> 9999.0-empty-to-avoid-conflict-with-guava +| | +--- androidx.camera:camera-core:1.3.4 (c) +| | +--- androidx.camera:camera-lifecycle:1.3.4 (c) +| | \--- androidx.camera:camera-video:1.3.4 (c) +| +--- androidx.camera:camera-lifecycle:1.3.4 (*) +| \--- com.google.guava:guava:27.0.1-android -> 31.1-android (*) ++--- project :feature:invoices +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- project :core:data (*) ++--- project :feature:merchants +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| \--- androidx.compose.material:material:1.6.0 -> 1.7.0-alpha04 (*) ++--- project :feature:history +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- project :core:data (*) ++--- project :feature:kyc +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| +--- androidx.compose.material:material:1.6.0 -> 1.7.0-alpha04 (*) +| +--- com.maxkeppeler.sheets-compose-dialogs:core:1.3.0 +| | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.10 -> 1.9.23 (*) +| | +--- androidx.core:core-ktx:1.9.0 -> 1.13.1 (*) +| | +--- androidx.compose:compose-bom:2024.02.00 -> 2024.06.00 (*) +| | +--- androidx.compose.ui:ui -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.animation:animation -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.animation:animation-graphics -> 1.7.0-alpha04 +| | | \--- androidx.compose.animation:animation-graphics-android:1.7.0-alpha04 +| | | +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| | | +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| | | +--- androidx.collection:collection:1.4.0 (*) +| | | +--- androidx.compose.animation:animation:1.7.0-alpha04 (*) +| | | +--- androidx.compose.foundation:foundation-layout:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.runtime:runtime:1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-geometry:1.6.0 -> 1.7.0-alpha04 (*) +| | | +--- androidx.compose.ui:ui-util:1.7.0-alpha04 (*) +| | | +--- androidx.core:core-ktx:1.5.0 -> 1.13.1 (*) +| | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| | | +--- androidx.compose.animation:animation:1.7.0-alpha04 (c) +| | | \--- androidx.compose.animation:animation-core:1.7.0-alpha04 (c) +| | +--- androidx.compose.runtime:runtime -> 1.7.0-alpha04 (*) +| | \--- androidx.compose.material3:material3 -> 1.2.1 (*) +| +--- com.maxkeppeler.sheets-compose-dialogs:calendar:1.3.0 +| | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.10 -> 1.9.23 (*) +| | +--- androidx.core:core-ktx:1.9.0 -> 1.13.1 (*) +| | +--- androidx.compose:compose-bom:2024.02.00 -> 2024.06.00 (*) +| | +--- androidx.compose.ui:ui -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.animation:animation -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.animation:animation-graphics -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.runtime:runtime -> 1.7.0-alpha04 (*) +| | +--- androidx.compose.material3:material3 -> 1.2.1 (*) +| | +--- dev.chrisbanes.snapper:snapper:0.3.0 (*) +| | \--- com.maxkeppeler.sheets-compose-dialogs:core:1.3.0 (*) +| +--- com.github.jump-sdk:jetpack_compose_country_code_picker_emoji:2.2.8 (*) +| \--- com.squareup.okhttp3:okhttp:4.12.0 (*) ++--- project :feature:home +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- project :core:data (*) ++--- project :feature:accounts +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| +--- androidx.compose.material:material:1.6.0 -> 1.7.0-alpha04 (*) +| \--- project :feature:upi-setup (*) ++--- project :feature:finance +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| \--- com.google.accompanist:accompanist-pager:0.34.0 (*) ++--- project :feature:payments +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| \--- com.google.accompanist:accompanist-pager:0.34.0 (*) ++--- project :feature:send-money +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| +--- androidx.compose.material:material:1.6.0 -> 1.7.0-alpha04 (*) +| +--- com.github.jump-sdk:jetpack_compose_country_code_picker_emoji:2.2.8 (*) +| \--- com.google.android.gms:play-services-code-scanner:16.1.0 +| +--- androidx.activity:activity:1.3.1 -> 1.9.1 (*) +| +--- com.google.android.datatransport:transport-api:2.2.1 -> 3.2.0 (*) +| +--- com.google.android.datatransport:transport-backend-cct:2.3.3 -> 3.3.0 (*) +| +--- com.google.android.datatransport:transport-runtime:2.2.6 -> 3.3.0 (*) +| +--- com.google.android.gms:play-services-base:18.1.0 -> 18.3.0 (*) +| +--- com.google.android.gms:play-services-basement:18.1.0 -> 18.4.0 (*) +| +--- com.google.android.gms:play-services-tasks:18.0.2 -> 18.2.0 (*) +| +--- com.google.firebase:firebase-components:16.1.0 -> 18.0.0 (*) +| +--- com.google.firebase:firebase-encoders:16.1.0 -> 17.0.0 (*) +| +--- com.google.firebase:firebase-encoders-json:17.1.0 -> 18.0.1 (*) +| +--- com.google.mlkit:barcode-scanning-common:17.0.0 +| | +--- com.google.android.gms:play-services-basement:18.0.0 -> 18.4.0 (*) +| | \--- com.google.mlkit:vision-common:17.0.0 +| | +--- androidx.exifinterface:exifinterface:1.0.0 -> 1.3.7 (*) +| | +--- com.google.android.datatransport:transport-api:2.2.1 -> 3.2.0 (*) +| | +--- com.google.android.datatransport:transport-backend-cct:2.3.3 -> 3.3.0 (*) +| | +--- com.google.android.datatransport:transport-runtime:2.2.6 -> 3.3.0 (*) +| | +--- com.google.android.gms:play-services-base:18.0.1 -> 18.3.0 (*) +| | +--- com.google.android.gms:play-services-basement:18.0.0 -> 18.4.0 (*) +| | +--- com.google.android.gms:play-services-tasks:18.0.1 -> 18.2.0 (*) +| | +--- com.google.android.odml:image:1.0.0-beta1 +| | +--- com.google.firebase:firebase-components:16.1.0 -> 18.0.0 (*) +| | +--- com.google.firebase:firebase-encoders:16.1.0 -> 17.0.0 (*) +| | +--- com.google.firebase:firebase-encoders-json:17.1.0 -> 18.0.1 (*) +| | \--- com.google.mlkit:common:18.0.0 -> 18.9.0 +| | +--- androidx.core:core:1.0.0 -> 1.13.1 (*) +| | +--- com.google.android.datatransport:transport-api:2.2.1 -> 3.2.0 (*) +| | +--- com.google.android.datatransport:transport-backend-cct:2.3.3 -> 3.3.0 (*) +| | +--- com.google.android.datatransport:transport-runtime:2.2.6 -> 3.3.0 (*) +| | +--- com.google.android.gms:play-services-base:18.1.0 -> 18.3.0 (*) +| | +--- com.google.android.gms:play-services-basement:18.1.0 -> 18.4.0 (*) +| | +--- com.google.android.gms:play-services-tasks:18.0.2 -> 18.2.0 (*) +| | +--- com.google.firebase:firebase-components:16.1.0 -> 18.0.0 (*) +| | +--- com.google.firebase:firebase-encoders:16.1.0 -> 17.0.0 (*) +| | \--- com.google.firebase:firebase-encoders-json:17.1.0 -> 18.0.1 (*) +| \--- com.google.mlkit:common:18.9.0 (*) ++--- project :feature:standing-instruction +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.9.22 -> 1.9.23 (*) +| +--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) +| +--- com.google.dagger:hilt-android:2.51.1 (*) +| +--- project :core:ui (*) +| +--- project :core:designsystem (*) +| +--- project :shared (*) +| +--- project :desktop (*) +| +--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) +| +--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) +| +--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) +| +--- androidx.compose:compose-bom:2024.06.00 (*) +| +--- androidx.compose.ui:ui-tooling-preview -> 1.7.0-alpha04 (*) +| +--- project :core:data (*) +| \--- com.google.android.gms:play-services-code-scanner:16.1.0 (*) ++--- androidx.activity:activity-compose:1.9.1 (*) ++--- androidx.compose.material3.adaptive:adaptive:1.0.0-alpha08 +| \--- androidx.compose.material3.adaptive:adaptive-android:1.0.0-alpha08 +| +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| +--- androidx.compose.foundation:foundation:1.6.0 -> 1.7.0-alpha04 (*) +| +--- androidx.compose.ui:ui-util:1.6.0 -> 1.7.0-alpha04 (*) +| +--- androidx.window:window:1.2.0 -> 1.3.0-alpha02 +| | +--- androidx.annotation:annotation:1.3.0 -> 1.8.0 (*) +| | +--- androidx.collection:collection:1.1.0 -> 1.4.0 (*) +| | +--- androidx.core:core:1.8.0 -> 1.13.1 (*) +| | +--- androidx.window.extensions.core:core:1.0.0 +| | | +--- androidx.annotation:annotation:1.6.0 -> 1.8.0 (*) +| | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.20 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 -> 1.8.1 (*) +| | \--- androidx.window:window-core:1.3.0-alpha02 (c) +| +--- androidx.window:window-core:1.3.0-alpha02 +| | \--- androidx.window:window-core-android:1.3.0-alpha02 +| | +--- androidx.annotation:annotation:1.7.0 -> 1.8.0 (*) +| | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| | \--- androidx.window:window:1.3.0-alpha02 (c) +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| +--- androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha08 (c) +| \--- androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha08 (c) ++--- androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha08 +| \--- androidx.compose.material3.adaptive:adaptive-layout-android:1.0.0-alpha08 +| +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| +--- androidx.compose.foundation:foundation:1.6.0-rc01 -> 1.7.0-alpha04 (*) +| +--- androidx.compose.foundation:foundation-layout:1.6.0-rc01 -> 1.7.0-alpha04 (*) +| +--- androidx.compose.material3.adaptive:adaptive:1.0.0-alpha08 (*) +| +--- androidx.compose.ui:ui-util:1.6.0-rc01 -> 1.7.0-alpha04 (*) +| +--- androidx.window:window-core:1.3.0-alpha02 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| +--- androidx.compose.material3.adaptive:adaptive:1.0.0-alpha08 (c) +| \--- androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha08 (c) ++--- androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha08 +| \--- androidx.compose.material3.adaptive:adaptive-navigation-android:1.0.0-alpha08 +| +--- androidx.annotation:annotation:1.1.0 -> 1.8.0 (*) +| +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| +--- androidx.compose.foundation:foundation:1.6.0-rc01 -> 1.7.0-alpha04 (*) +| +--- androidx.compose.foundation:foundation-layout:1.6.0-rc01 -> 1.7.0-alpha04 (*) +| +--- androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha08 (*) +| +--- androidx.compose.ui:ui-util:1.6.0-rc01 -> 1.7.0-alpha04 (*) +| +--- androidx.window:window-core:1.3.0-alpha02 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| +--- androidx.compose.material3.adaptive:adaptive:1.0.0-alpha08 (c) +| \--- androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha08 (c) ++--- androidx.compose.material3:material3-window-size-class -> 1.2.1 +| \--- androidx.compose.material3:material3-window-size-class-android:1.2.1 +| +--- androidx.annotation:annotation-experimental:1.4.0 (*) +| +--- androidx.compose.runtime:runtime:1.6.0 -> 1.7.0-alpha04 (*) +| +--- androidx.compose.ui:ui:1.6.0 -> 1.7.0-alpha04 (*) +| +--- androidx.compose.ui:ui-unit:1.6.0 -> 1.7.0-alpha04 (*) +| +--- androidx.compose.ui:ui-util:1.6.0 -> 1.7.0-alpha04 (*) +| +--- androidx.window:window:1.0.0 -> 1.3.0-alpha02 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 -> 1.9.23 (*) +| \--- androidx.compose.material3:material3:1.2.1 (c) ++--- androidx.compose.runtime:runtime-tracing:1.0.0-beta01 +| +--- androidx.annotation:annotation:1.3.0 -> 1.8.0 (*) +| +--- androidx.compose.runtime:runtime:1.3.3 -> 1.7.0-alpha04 (*) +| +--- androidx.startup:startup-runtime:1.1.1 (*) +| +--- androidx.tracing:tracing-perfetto:1.0.0 +| | +--- androidx.annotation:annotation:1.3.0 -> 1.8.0 (*) +| | +--- androidx.startup:startup-runtime:1.1.1 (*) +| | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) +| \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 1.9.23 (*) ++--- androidx.core:core-splashscreen:1.0.1 +| +--- androidx.annotation:annotation:1.2.0 -> 1.8.0 (*) +| \--- org.jetbrains.kotlin:kotlin-stdlib:1.6.21 -> 1.9.23 (*) ++--- androidx.hilt:hilt-navigation-compose:1.2.0 (*) ++--- androidx.lifecycle:lifecycle-runtime-compose:2.8.4 (*) ++--- androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4 (*) ++--- androidx.navigation:navigation-compose:2.7.7 (*) ++--- androidx.profileinstaller:profileinstaller:1.3.1 (*) ++--- androidx.tracing:tracing-ktx:1.3.0-alpha02 (*) ++--- org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.8.1 +| +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (*) +| +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.8.1 (*) +| +--- com.google.guava:guava:31.0.1-jre -> 31.1-android (*) +| \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.21 -> 1.9.23 (*) ++--- io.coil-kt:coil:2.6.0 (*) ++--- androidx.compose.material:material-navigation:1.7.0-alpha04 (*) ++--- com.google.accompanist:accompanist-pager:0.34.0 (*) ++--- com.google.android.gms:play-services-code-scanner:16.1.0 (*) ++--- com.maxkeppeler.sheets-compose-dialogs:core:1.3.0 (*) ++--- com.maxkeppeler.sheets-compose-dialogs:calendar:1.3.0 (*) ++--- androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4 (*) ++--- androidx.lifecycle:lifecycle-extensions:2.2.0 +| +--- androidx.lifecycle:lifecycle-runtime:2.2.0 -> 2.8.4 (*) +| +--- androidx.arch.core:core-common:2.1.0 -> 2.2.0 (*) +| +--- androidx.arch.core:core-runtime:2.1.0 -> 2.2.0 (*) +| +--- androidx.fragment:fragment:1.2.0 -> 1.6.2 (*) +| +--- androidx.lifecycle:lifecycle-common:2.2.0 -> 2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-livedata:2.2.0 -> 2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-process:2.2.0 -> 2.8.4 (*) +| +--- androidx.lifecycle:lifecycle-service:2.2.0 -> 2.8.4 (*) +| \--- androidx.lifecycle:lifecycle-viewmodel:2.2.0 -> 2.8.4 (*) ++--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (*) ++--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1 (*) +\--- androidx.compose.runtime:runtime:1.6.8 -> 1.7.0-alpha04 (*) diff --git a/mifospay/dependencies/prodReleaseRuntimeClasspath.txt b/mifospay/dependencies/prodReleaseRuntimeClasspath.txt index 730d11403..4fc05ac36 100644 --- a/mifospay/dependencies/prodReleaseRuntimeClasspath.txt +++ b/mifospay/dependencies/prodReleaseRuntimeClasspath.txt @@ -1,3 +1,37 @@ +:core:analytics +:core:common +:core:data +:core:datastore +:core:datastore-proto +:core:designsystem +:core:model +:core:network +:core:ui +:desktop +:feature:accounts +:feature:auth +:feature:editpassword +:feature:faq +:feature:finance +:feature:history +:feature:home +:feature:invoices +:feature:kyc +:feature:make-transfer +:feature:merchants +:feature:notification +:feature:passcode +:feature:payments +:feature:profile +:feature:qr +:feature:receipt +:feature:request-money +:feature:savedcards +:feature:send-money +:feature:settings +:feature:standing-instruction +:feature:upi-setup +:shared androidx.activity:activity-compose:1.9.1 androidx.activity:activity-ktx:1.9.1 androidx.activity:activity:1.9.1 @@ -8,7 +42,6 @@ androidx.appcompat:appcompat-resources:1.7.0 androidx.appcompat:appcompat:1.7.0 androidx.arch.core:core-common:2.2.0 androidx.arch.core:core-runtime:2.2.0 -androidx.asynclayoutinflater:asynclayoutinflater:1.0.0 androidx.autofill:autofill:1.0.0 androidx.browser:browser:1.8.0 androidx.camera:camera-core:1.3.4 @@ -107,9 +140,7 @@ androidx.graphics:graphics-path:1.0.0-beta02 androidx.hilt:hilt-navigation-compose:1.2.0 androidx.hilt:hilt-navigation:1.2.0 androidx.interpolator:interpolator:1.0.0 -androidx.legacy:legacy-support-core-ui:1.0.0 androidx.legacy:legacy-support-core-utils:1.0.0 -androidx.legacy:legacy-support-v4:1.0.0 androidx.lifecycle:lifecycle-common-java8:2.8.4 androidx.lifecycle:lifecycle-common-jvm:2.8.4 androidx.lifecycle:lifecycle-common:2.8.4 @@ -133,7 +164,6 @@ androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.4 androidx.lifecycle:lifecycle-viewmodel:2.8.4 androidx.loader:loader:1.1.0 androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 -androidx.media:media:1.0.0 androidx.metrics:metrics-performance:1.0.0-beta01 androidx.navigation:navigation-common-ktx:2.7.7 androidx.navigation:navigation-common:2.7.7 @@ -148,7 +178,6 @@ androidx.recyclerview:recyclerview:1.3.2 androidx.resourceinspection:resourceinspection-annotation:1.0.1 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 -androidx.slidingpanelayout:slidingpanelayout:1.0.0 androidx.startup:startup-runtime:1.1.1 androidx.swiperefreshlayout:swiperefreshlayout:1.1.0 androidx.tracing:tracing-ktx:1.3.0-alpha02 @@ -233,11 +262,10 @@ com.google.mlkit:common:18.9.0 com.google.mlkit:vision-common:17.0.0 com.google.protobuf:protobuf-javalite:3.25.2 com.google.protobuf:protobuf-kotlin-lite:3.25.2 -com.google.zxing:core:3.3.3 +com.google.zxing:core:3.5.3 com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0 com.maxkeppeler.sheets-compose-dialogs:calendar:1.3.0 com.maxkeppeler.sheets-compose-dialogs:core:1.3.0 -com.mifos.mobile:mifos-passcode:0.3.0 com.squareup.okhttp3:logging-interceptor:4.12.0 com.squareup.okhttp3:okhttp:4.12.0 com.squareup.okio:okio-jvm:3.8.0 @@ -254,8 +282,6 @@ io.michaelrocks:libphonenumber-android:8.13.28 io.reactivex:rxandroid:1.1.0 io.reactivex:rxjava:1.3.8 javax.inject:javax.inject:1 -me.dm7.barcodescanner:core:1.9.13 -me.dm7.barcodescanner:zxing:1.9.13 org.checkerframework:checker-qual:3.12.0 org.jetbrains.compose.desktop:desktop-jvm-windows-x64:1.6.1 org.jetbrains.compose.desktop:desktop-jvm:1.6.1 diff --git a/mifospay/prodRelease-badging.txt b/mifospay/prodRelease-badging.txt index 206563104..f11f488a2 100644 --- a/mifospay/prodRelease-badging.txt +++ b/mifospay/prodRelease-badging.txt @@ -7,6 +7,7 @@ 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.ACCESS_NETWORK_STATE' +uses-permission: name='android.permission.VIBRATE' uses-permission: name='android.permission.POST_NOTIFICATIONS' uses-permission: name='android.permission.WAKE_LOCK' uses-permission: name='com.google.android.c2dm.permission.RECEIVE' @@ -123,7 +124,7 @@ application-icon-480:'res/mipmap/ic_launcher.png' application-icon-640:'res/mipmap/ic_launcher.png' application-icon-65534:'res/mipmap/ic_launcher.png' application: label='Mifos Pay' icon='res/mipmap/ic_launcher.png' -launchable-activity: name='org.mifospay.SplashScreenActivity' label='' icon='' +launchable-activity: name='org.mifospay.MainActivity' label='' icon='' property: name='android.adservices.AD_SERVICES_CONFIG' resource='res/xml/ga_ad_services_config.xml' uses-library-not-required:'androidx.window.extensions' uses-library-not-required:'androidx.window.sidecar' @@ -142,4 +143,4 @@ supports-screens: 'small' 'normal' 'large' 'xlarge' supports-any-density: 'true' locales: '--_--' 'af' 'am' 'ar' 'as' 'az' 'be' 'bg' 'bn' 'bs' 'ca' 'cs' 'da' 'de' 'de-DE' 'el' 'en-AU' 'en-CA' 'en-GB' 'en-IN' 'en-XC' 'eo' 'es' 'es-419' 'es-US' 'et' 'eu' 'fa' 'fi' 'fr' 'fr-CA' 'ga' 'gd' 'gl' 'gu' 'hi' 'hr' 'hu' 'hy' 'in' 'in-ID' 'is' 'it' 'it-IT' 'iw' 'ja' 'jv' 'ka' 'kk' 'km' 'kn' 'ko' 'ku' 'ky' 'lb' 'lo' 'lt' 'lv' 'mk' 'ml' 'mn' 'mr' 'ms' 'my' 'nb' 'ne' 'nl' 'no' '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' densities: '120' '160' '240' '320' '480' '640' '65534' -native-code: 'arm64-v8a' 'armeabi' 'armeabi-v7a' 'mips' 'mips64' 'x86' 'x86_64' +native-code: 'arm64-v8a' 'armeabi-v7a' 'x86' 'x86_64' diff --git a/mifospay/src/main/AndroidManifest.xml b/mifospay/src/main/AndroidManifest.xml index 8384b76be..e566beb8a 100644 --- a/mifospay/src/main/AndroidManifest.xml +++ b/mifospay/src/main/AndroidManifest.xml @@ -37,34 +37,32 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/AppTheme"> - - + android:theme="@style/Theme.MifosSplash"> + android:theme="@style/Theme.MifosSplash" + android:windowSoftInputMode="adjustPan"> - - + + + + + - - @@ -99,13 +93,6 @@ - - \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/MainActivity.kt b/mifospay/src/main/java/org/mifospay/MainActivity.kt index e22024333..8416a5d33 100644 --- a/mifospay/src/main/java/org/mifospay/MainActivity.kt +++ b/mifospay/src/main/java/org/mifospay/MainActivity.kt @@ -14,7 +14,6 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels -import androidx.compose.material.navigation.rememberBottomSheetNavigator import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass import androidx.compose.runtime.CompositionLocalProvider @@ -40,13 +39,14 @@ import org.mifospay.core.data.util.NetworkMonitor import org.mifospay.core.data.util.TimeZoneMonitor import org.mifospay.core.designsystem.theme.MifosTheme import org.mifospay.core.ui.LocalTimeZone -import org.mifospay.ui.MifosApp +import org.mifospay.navigation.MifosNavGraph.LOGIN_GRAPH +import org.mifospay.navigation.MifosNavGraph.PASSCODE_GRAPH +import org.mifospay.navigation.RootNavGraph import org.mifospay.ui.rememberMifosAppState import javax.inject.Inject @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @AndroidEntryPoint -@Suppress("UnusedPrivateProperty") class MainActivity : ComponentActivity() { /** @@ -64,7 +64,7 @@ class MainActivity : ComponentActivity() { @Inject lateinit var analyticsHelper: AnalyticsHelper - val viewModel: MainActivityViewModel by viewModels() + private val viewModel: MainActivityViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { val splashScreen = installSplashScreen() @@ -81,9 +81,6 @@ class MainActivity : ComponentActivity() { } } - // Keep the splash screen on-screen until the UI state is loaded. This condition is - // evaluated each time the app needs to be redrawn so it should be fast to avoid blocking - // the UI. splashScreen.setKeepOnScreenCondition { when (uiState) { Loading -> true @@ -91,29 +88,47 @@ class MainActivity : ComponentActivity() { } } - // Turn off the decor fitting system windows, which allows us to handle insets, - // including IME animations, and go edge-to-edge - // This also sets up the initial system bar style based on the platform theme enableEdgeToEdge() setContent { - val bottomSheetNavigator = rememberBottomSheetNavigator() - val navController = rememberNavController(bottomSheetNavigator) + val navController = rememberNavController() + val appState = rememberMifosAppState( windowSizeClass = calculateWindowSizeClass(this), networkMonitor = networkMonitor, timeZoneMonitor = timeZoneMonitor, - navController = navController, ) val currentTimeZone by appState.currentTimeZone.collectAsStateWithLifecycle() + val navDestination = when (uiState) { + is Success -> if ((uiState as Success).userData.isAuthenticated) { + PASSCODE_GRAPH + } else { + LOGIN_GRAPH + } + + else -> LOGIN_GRAPH + } + CompositionLocalProvider( LocalAnalyticsHelper provides analyticsHelper, LocalTimeZone provides currentTimeZone, ) { MifosTheme { - MifosApp(appState, bottomSheetNavigator) + RootNavGraph( + appState = appState, + navHostController = navController, + startDestination = navDestination, + onClickLogout = { + viewModel.logOut() + navController.navigate(LOGIN_GRAPH) { + popUpTo(navController.graph.id) { + inclusive = true + } + } + }, + ) } } } @@ -128,16 +143,4 @@ class MainActivity : ComponentActivity() { super.onPause() lazyStats.get().isTrackingEnabled = false } - - /** - * The default light scrim, as defined by androidx and the platform: - * https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/kotlin/androidx/activity/EdgeToEdge.kt;l=35-38;drc=27e7d52e8604a080133e8b842db10c89b4482598 - */ - private val lightScrim = android.graphics.Color.argb(0xe6, 0xFF, 0xFF, 0xFF) - - /** - * The default dark scrim, as defined by androidx and the platform: - * https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/kotlin/androidx/activity/EdgeToEdge.kt;l=40-44;drc=27e7d52e8604a080133e8b842db10c89b4482598 - */ - private val darkScrim = android.graphics.Color.argb(0x80, 0x1b, 0x1b, 0x1b) } diff --git a/mifospay/src/main/java/org/mifospay/MainActivityViewModel.kt b/mifospay/src/main/java/org/mifospay/MainActivityViewModel.kt index 615109974..763374697 100644 --- a/mifospay/src/main/java/org/mifospay/MainActivityViewModel.kt +++ b/mifospay/src/main/java/org/mifospay/MainActivityViewModel.kt @@ -17,12 +17,15 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch import org.mifospay.core.data.repository.auth.UserDataRepository +import org.mifospay.feature.passcode.data.PasscodeManager import javax.inject.Inject @HiltViewModel class MainActivityViewModel @Inject constructor( - userDataRepository: UserDataRepository, + private val userDataRepository: UserDataRepository, + private val passcodeManager: PasscodeManager, ) : ViewModel() { val uiState: StateFlow = userDataRepository.userData.map { @@ -32,6 +35,13 @@ class MainActivityViewModel @Inject constructor( initialValue = MainActivityUiState.Loading, started = SharingStarted.WhileSubscribed(5_000), ) + + fun logOut() { + viewModelScope.launch { + userDataRepository.logOut() + passcodeManager.clearPasscode() + } + } } sealed interface MainActivityUiState { diff --git a/mifospay/src/main/java/org/mifospay/MifosPayApp.kt b/mifospay/src/main/java/org/mifospay/MifosPayApp.kt index 6a0d29fc7..795035371 100644 --- a/mifospay/src/main/java/org/mifospay/MifosPayApp.kt +++ b/mifospay/src/main/java/org/mifospay/MifosPayApp.kt @@ -10,39 +10,11 @@ package org.mifospay import android.app.Application -import android.content.Context -import androidx.appcompat.app.AppCompatDelegate -import com.mifos.mobile.passcode.utils.ForegroundChecker import dagger.hilt.android.HiltAndroidApp -/** - * Created by naman on 17/8/17. - */ @HiltAndroidApp class MifosPayApp : Application() { override fun onCreate() { super.onCreate() - if (instance == null) { - instance = this - } - - // Initialize ForegroundChecker - ForegroundChecker.init(this) - } - - companion object { - private var instance: MifosPayApp? = null - - init { - AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) - } - - operator fun get(context: Context): MifosPayApp { - return context.applicationContext as MifosPayApp - } - - @JvmStatic - val context: Context? - get() = instance } } diff --git a/mifospay/src/main/java/org/mifospay/SplashScreenActivity.kt b/mifospay/src/main/java/org/mifospay/SplashScreenActivity.kt deleted file mode 100644 index 60aae0d34..000000000 --- a/mifospay/src/main/java/org/mifospay/SplashScreenActivity.kt +++ /dev/null @@ -1,40 +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 - -import android.annotation.SuppressLint -import android.content.Intent -import android.content.pm.ActivityInfo -import android.os.Build -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen -import androidx.lifecycle.lifecycleScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import org.mifospay.feature.auth.login.LoginActivity - -@SuppressLint("CustomSplashScreen") -class SplashScreenActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - val splashScreen = installSplashScreen() - splashScreen.setKeepOnScreenCondition { true } - } - super.onCreate(savedInstanceState) - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - lifecycleScope.launch { - delay(2000) - startActivity(Intent(this@SplashScreenActivity, LoginActivity::class.java)) - finish() - } - } -} diff --git a/mifospay/src/main/java/org/mifospay/base/BaseActivity.kt b/mifospay/src/main/java/org/mifospay/base/BaseActivity.kt deleted file mode 100644 index 7043ab6b1..000000000 --- a/mifospay/src/main/java/org/mifospay/base/BaseActivity.kt +++ /dev/null @@ -1,170 +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.base - -import android.app.ProgressDialog -import android.content.pm.ActivityInfo -import android.view.MenuItem -import androidx.appcompat.widget.Toolbar -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout -import com.mifos.mobile.passcode.BasePassCodeActivity -import org.mifospay.R -import org.mifospay.feature.passcode.PassCodeActivity - -/** - * Created by naman on 16/6/17. - */ -open class BaseActivity : BasePassCodeActivity(), BaseActivityCallback { - var toolbar: Toolbar? = null - override var swipeRefreshLayout: SwipeRefreshLayout? = null - var progressDialog: ProgressDialog? = null - override fun setContentView(layoutResID: Int) { - super.setContentView(layoutResID) - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - toolbar = findViewById(R.id.toolbar) - swipeRefreshLayout = findViewById(R.id.swipe_layout) - if (toolbar != null) { - setSupportActionBar(toolbar) - } - } - - override fun showSwipeProgress() { - if (swipeRefreshLayout != null) { - swipeRefreshLayout!!.isEnabled = true - swipeRefreshLayout!!.isRefreshing = true - } - } - - override fun hideSwipeProgress() { - if (swipeRefreshLayout != null) { - swipeRefreshLayout!!.isRefreshing = false - } - } - - override fun setSwipeRefreshEnabled(enabled: Boolean) { - if (swipeRefreshLayout != null) { - swipeRefreshLayout!!.isEnabled = enabled - } - } - - override fun showProgressDialog(message: String?) { - if (progressDialog != null) { - progressDialog!!.setMessage(message) - progressDialog!!.show() - } else { - progressDialog = ProgressDialog(this) - progressDialog!!.setCanceledOnTouchOutside(false) - progressDialog!!.setMessage(message) - progressDialog!!.show() - } - } - - override fun hideProgressDialog() { - if (progressDialog != null) { - progressDialog!!.dismiss() - } - } - - override fun cancelProgressDialog() { - if (progressDialog != null && progressDialog!!.isShowing) { - progressDialog!!.cancel() - } - } - - override fun dismissProgressDialog() { - if (progressDialog != null && progressDialog!!.isShowing) { - progressDialog!!.dismiss() - } - } - - override fun setToolbarTitle(title: String?) { - if (supportActionBar != null && getTitle() != null) { - setTitle(title) - } - } - - override fun showColoredBackButton(drawable: Int) { - showHomeButton() - setToolbarIcon(drawable) - } - - override fun showCloseButton() { - showHomeButton() - setToolbarIcon(R.drawable.feature_make_transfer_ic_close) - } - - private fun showHomeButton() { - if (supportActionBar != null) { - supportActionBar!!.setHomeButtonEnabled(true) - supportActionBar!!.setDisplayHomeAsUpEnabled(true) - } - } - - private fun setToolbarIcon(res: Int) { - if (supportActionBar != null) { - supportActionBar!!.setHomeAsUpIndicator(res) - } - } - - override fun hideBackButton() { - if (supportActionBar != null) { - supportActionBar!!.setHomeButtonEnabled(false) - supportActionBar!!.setDisplayHomeAsUpEnabled(false) - } - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - android.R.id.home -> onBackPressed() - } - return super.onOptionsItemSelected(item) - } - - fun addFragment(fragment: Fragment?, containerId: Int) { - val transaction = supportFragmentManager.beginTransaction() - transaction.add(containerId, fragment!!) - transaction.commit() - } - - fun replaceFragment(fragment: Fragment, addToBackStack: Boolean, containerId: Int) { - invalidateOptionsMenu() - val backStateName = fragment.javaClass.name - val fragmentPopped = supportFragmentManager.popBackStackImmediate( - backStateName, - 0, - ) - if (!fragmentPopped && supportFragmentManager.findFragmentByTag(backStateName) == - null - ) { - val transaction = supportFragmentManager.beginTransaction() - transaction.setCustomAnimations(R.anim.custom_fade_in, R.anim.custom_fade_out) - transaction.replace(containerId, fragment, backStateName) - if (addToBackStack) { - transaction.addToBackStack(backStateName) - } - transaction.commit() - } - } - - fun clearFragmentBackStack() { - val fm = supportFragmentManager - val backStackCount = supportFragmentManager.backStackEntryCount - for (i in 0 until backStackCount) { - val backStackId = supportFragmentManager.getBackStackEntryAt(i).id - fm.popBackStack(backStackId, FragmentManager.POP_BACK_STACK_INCLUSIVE) - } - } - - override fun getPassCodeClass(): Class<*> { - return PassCodeActivity::class.java - } -} diff --git a/mifospay/src/main/java/org/mifospay/common/ui/SearchActivity.kt b/mifospay/src/main/java/org/mifospay/common/ui/SearchActivity.kt index 10e908f4f..6179f443d 100644 --- a/mifospay/src/main/java/org/mifospay/common/ui/SearchActivity.kt +++ b/mifospay/src/main/java/org/mifospay/common/ui/SearchActivity.kt @@ -10,16 +10,16 @@ package org.mifospay.common.ui import android.os.Bundle +import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import dagger.hilt.android.AndroidEntryPoint -import org.mifospay.base.BaseActivity import org.mifospay.core.designsystem.theme.MifosTheme /** * Created by naman on 21/8/17. */ @AndroidEntryPoint -class SearchActivity : BaseActivity() { +class SearchActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { diff --git a/mifospay/src/main/java/org/mifospay/di/ApplicationModule.kt b/mifospay/src/main/java/org/mifospay/di/ApplicationModule.kt index ba2dba403..1dc03bb0c 100644 --- a/mifospay/src/main/java/org/mifospay/di/ApplicationModule.kt +++ b/mifospay/src/main/java/org/mifospay/di/ApplicationModule.kt @@ -9,16 +9,12 @@ */ package org.mifospay.di -import android.content.Context -import com.mifos.mobile.passcode.utils.PasscodePreferencesHelper import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import org.mifospay.core.datastore.PreferencesHelper import org.mifospay.data.local.LocalRepository -import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) @@ -28,12 +24,4 @@ class ApplicationModule { fun providesLocalRepository(preferencesHelper: PreferencesHelper): LocalRepository { return LocalRepository(preferencesHelper) } - - @Provides - @Singleton - fun providesPasscodePreferencesHelper( - @ApplicationContext context: Context, - ): PasscodePreferencesHelper { - return PasscodePreferencesHelper(context) - } } diff --git a/mifospay/src/main/java/org/mifospay/navigation/LoginNavGraph.kt b/mifospay/src/main/java/org/mifospay/navigation/LoginNavGraph.kt new file mode 100644 index 000000000..92e652ae3 --- /dev/null +++ b/mifospay/src/main/java/org/mifospay/navigation/LoginNavGraph.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.navigation +import org.mifospay.common.Constants +import org.mifospay.feature.auth.navigation.LOGIN_ROUTE +import org.mifospay.feature.auth.navigation.loginScreen +import org.mifospay.feature.auth.navigation.mobileVerificationScreen +import org.mifospay.feature.auth.navigation.navigateToSignup +import org.mifospay.feature.auth.navigation.signupScreen +import org.mifospay.feature.passcode.navigateToPasscodeScreen + +internal fun NavGraphBuilder.loginNavGraph(navController: NavController) { + navigation( + route = MifosNavGraph.LOGIN_GRAPH, + startDestination = LOGIN_ROUTE, + ) { + loginScreen( + onNavigateToPasscodeScreen = navController::navigateToPasscodeScreen, + ) + + signupScreen( + onLoginSuccess = navController::navigateToPasscodeScreen, + onRegisterSuccess = navController::navigateToPasscodeScreen, + ) + + mobileVerificationScreen( + onOtpVerificationSuccess = { fullNumber, extraData -> + navController.navigateToSignup( + savingProductId = extraData[Constants.MIFOS_SAVINGS_PRODUCT_ID] as Int, + mobileNumber = fullNumber, + country = "Canada", + email = extraData[Constants.GOOGLE_EMAIL] as? String ?: "", + firstName = extraData[Constants.GOOGLE_GIVEN_NAME] as? String ?: "", + lastName = extraData[Constants.GOOGLE_FAMILY_NAME] as? String ?: "", + businessName = extraData[Constants.GOOGLE_DISPLAY_NAME] as? String ?: "", + ) + }, + ) + } +} diff --git a/mifospay/src/main/java/org/mifospay/navigation/MifosNavGraph.kt b/mifospay/src/main/java/org/mifospay/navigation/MifosNavGraph.kt new file mode 100644 index 000000000..ffb539627 --- /dev/null +++ b/mifospay/src/main/java/org/mifospay/navigation/MifosNavGraph.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md + */ +package org.mifospay.navigation + +internal object MifosNavGraph { + const val ROOT_GRAPH = "root_graph" + const val LOGIN_GRAPH = "login_graph" + const val PASSCODE_GRAPH = "passcode_graph" + const val MAIN_GRAPH = "main_graph" +} diff --git a/mifospay/src/main/java/org/mifospay/navigation/MifosNavHost.kt b/mifospay/src/main/java/org/mifospay/navigation/MifosNavHost.kt index 138935bfd..3f5b4a583 100644 --- a/mifospay/src/main/java/org/mifospay/navigation/MifosNavHost.kt +++ b/mifospay/src/main/java/org/mifospay/navigation/MifosNavHost.kt @@ -10,25 +10,14 @@ package org.mifospay.navigation import android.content.Context -import android.content.Intent import android.net.Uri +import androidx.compose.material.navigation.ModalBottomSheetLayout import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.core.content.FileProvider -import androidx.core.os.bundleOf -import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost -import com.mifos.mobile.passcode.utils.PassCodeConstants -import com.mifos.mobile.passcode.utils.PasscodePreferencesHelper import org.mifospay.common.Constants import org.mifospay.core.ui.utility.TabContent -import org.mifospay.feature.auth.login.LoginActivity -import org.mifospay.feature.auth.navigation.loginScreen -import org.mifospay.feature.auth.navigation.mobileVerificationScreen -import org.mifospay.feature.auth.navigation.navigateToMobileVerification -import org.mifospay.feature.auth.navigation.navigateToSignup -import org.mifospay.feature.auth.navigation.signupScreen import org.mifospay.feature.bank.accounts.AccountsScreen import org.mifospay.feature.bank.accounts.navigation.bankAccountDetailScreen import org.mifospay.feature.bank.accounts.navigation.linkBankAccountScreen @@ -57,7 +46,6 @@ import org.mifospay.feature.make.transfer.navigation.makeTransferScreen import org.mifospay.feature.make.transfer.navigation.navigateToMakeTransferScreen import org.mifospay.feature.merchants.navigation.merchantTransferScreen import org.mifospay.feature.merchants.ui.MerchantScreen -import org.mifospay.feature.passcode.PassCodeActivity import org.mifospay.feature.payments.PaymentsScreenContents import org.mifospay.feature.payments.RequestScreen import org.mifospay.feature.payments.paymentsScreen @@ -84,6 +72,7 @@ import org.mifospay.feature.standing.instruction.newSiScreen import org.mifospay.feature.standing.instruction.siDetailsScreen import org.mifospay.feature.upiSetup.navigation.navigateToSetupUpiPin import org.mifospay.feature.upiSetup.navigation.setupUpiPinScreen +import org.mifospay.ui.MifosAppState import java.io.File import java.util.Objects @@ -94,15 +83,14 @@ import java.util.Objects * The navigation graph defined in this file defines the different top level routes. Navigation * within each route is handled using state and Back Handlers. */ +@Suppress("MaxLineLength", "LongMethod") @Composable -@Suppress("MaxLineLength", "LongMethod", "UnusedParameter") -fun MifosNavHost( - navController: NavHostController, - onShowSnackbar: suspend (String, String?) -> Boolean, +internal fun MifosNavHost( + appState: MifosAppState, + onClickLogout: () -> Unit, modifier: Modifier = Modifier, - startDestination: String = HOME_ROUTE, ) { - val context = LocalContext.current + val navController = appState.navController val tabContents = listOf( TabContent(FinanceScreenContents.ACCOUNTS.name) { @@ -161,207 +149,147 @@ fun MifosNavHost( }, ) - NavHost( - navController = navController, - startDestination = startDestination, + ModalBottomSheetLayout( + bottomSheetNavigator = appState.bottomSheetNavigator, modifier = modifier, ) { - homeScreen( - onRequest = navController::navigateToShowQrScreen, - onPay = navController::navigateToSendMoneyScreen, - ) - paymentsScreen( - tabContents = paymentsTabContents, - ) - financeScreen( - tabContents = tabContents, - ) - addCardScreen( - onDismiss = navController::popBackStack, - onAddCard = { - // Handle adding the cards - navController.popBackStack() - }, - ) - profileScreen( - onEditProfile = navController::navigateToEditProfile, - onSettings = navController::navigateToSettings, - ) - sendMoneyScreen( - onBackClick = navController::popBackStack, - proceedWithMakeTransferFlow = navController::navigateToMakeTransferScreen, - ) - makeTransferScreen( - onDismiss = navController::popBackStack, - ) - showQrScreen( - onBackClick = navController::popBackStack, - ) - merchantTransferScreen( - proceedWithMakeTransferFlow = navController::navigateToMakeTransferScreen, - onBackPressed = navController::popBackStack, - ) - settingsScreen( - onBackPress = navController::popBackStack, - navigateToEditPasswordScreen = navController::navigateToEditPassword, - onLogout = context::logOut, - onChangePasscode = context::onChangePasscodeClicked, - ) + NavHost( + route = MifosNavGraph.MAIN_GRAPH, + startDestination = HOME_ROUTE, + navController = navController, + ) { + homeScreen( + onRequest = navController::navigateToShowQrScreen, + onPay = navController::navigateToSendMoneyScreen, + ) + paymentsScreen( + tabContents = paymentsTabContents, + ) + financeScreen( + tabContents = tabContents, + ) + addCardScreen( + onDismiss = navController::popBackStack, + onAddCard = { + // Handle adding the cards + navController.popBackStack() + }, + ) + profileScreen( + onEditProfile = navController::navigateToEditProfile, + onSettings = navController::navigateToSettings, + ) + sendMoneyScreen( + onBackClick = navController::popBackStack, + proceedWithMakeTransferFlow = navController::navigateToMakeTransferScreen, + ) + makeTransferScreen( + onDismiss = navController::popBackStack, + ) + showQrScreen( + onBackClick = navController::popBackStack, + ) + merchantTransferScreen( + proceedWithMakeTransferFlow = navController::navigateToMakeTransferScreen, + onBackPressed = navController::popBackStack, + ) + settingsScreen( + onBackPress = navController::popBackStack, + navigateToEditPasswordScreen = navController::navigateToEditPassword, + onLogout = onClickLogout, + onChangePasscode = { + // TODO:: Implement change passcode screen + }, + ) - kycScreen( - onLevel1Clicked = navController::navigateToKYCLevel1, - onLevel2Clicked = navController::navigateToKYCLevel2, - onLevel3Clicked = navController::navigateToKYCLevel3, - ) - kycLevel1Screen( - navigateToKycLevel2 = navController::navigateToKYCLevel2, - ) - kycLevel2Screen( - onSuccessKyc2 = navController::navigateToKYCLevel3, - ) + kycScreen( + onLevel1Clicked = navController::navigateToKYCLevel1, + onLevel2Clicked = navController::navigateToKYCLevel2, + onLevel3Clicked = navController::navigateToKYCLevel3, + ) + kycLevel1Screen( + navigateToKycLevel2 = navController::navigateToKYCLevel2, + ) + kycLevel2Screen( + onSuccessKyc2 = navController::navigateToKYCLevel3, + ) - kycLevel3Screen() + kycLevel3Screen() - newSiScreen(onBackClick = navController::popBackStack) + newSiScreen(onBackClick = navController::popBackStack) - siDetailsScreen( - onClickCreateNew = navController::navigateToNewSiScreen, - onBackPress = navController::popBackStack, - ) + siDetailsScreen( + onClickCreateNew = navController::navigateToNewSiScreen, + onBackPress = navController::popBackStack, + ) - editProfileScreen( - onBackPress = navController::popBackStack, - getUri = ::getUri, - ) + editProfileScreen( + onBackPress = navController::popBackStack, + getUri = ::getUri, + ) - faqScreen( - navigateBack = navController::popBackStack, - ) - readQrScreen( - onBackClick = navController::popBackStack, - ) + faqScreen( + navigateBack = navController::popBackStack, + ) + readQrScreen( + onBackClick = navController::popBackStack, + ) - specificTransactionsScreen( - onBackClick = navController::popBackStack, - onTransactionItemClicked = { transactionId -> - navController.navigateToReceipt(Uri.parse(Constants.RECEIPT_DOMAIN + transactionId)) - }, - ) - invoiceDetailScreen( - onBackPress = navController::popBackStack, - navigateToReceiptScreen = { uri -> - navController.navigateToReceipt(Uri.parse(Constants.RECEIPT_DOMAIN + uri)) - }, - ) - receiptScreen( - openPassCodeActivity = context::openPassCodeActivity, - onBackClick = navController::popBackStack, - ) - setupUpiPinScreen( - onBackPress = navController::popBackStack, - ) - bankAccountDetailScreen( - onSetupUpiPin = { bankAccountDetails, index -> - navController.navigateToSetupUpiPin(bankAccountDetails, index, Constants.SETUP) - }, - onChangeUpiPin = { bankAccountDetails, index -> - navController.navigateToSetupUpiPin(bankAccountDetails, index, Constants.CHANGE) - }, - onForgotUpiPin = { bankAccountDetails, index -> - navController.navigateToSetupUpiPin(bankAccountDetails, index, Constants.FORGOT) - }, - onBackClick = { bankAccountDetails, index -> - navController.previousBackStackEntry?.savedStateHandle?.set( - Constants.UPDATED_BANK_ACCOUNT, - bankAccountDetails, - ) - navController.previousBackStackEntry?.savedStateHandle?.set(Constants.INDEX, index) - navController.popBackStack() - }, - ) - linkBankAccountScreen( - onBackClick = navController::popBackStack, - ) - editPasswordScreen( - onBackPress = navController::popBackStack, - onCancelChanges = navController::popBackStack, - ) - signupScreen( - onLoginSuccess = { - val intent = Intent(context, PassCodeActivity::class.java).apply { - putExtra(PassCodeConstants.PASSCODE_INITIAL_LOGIN, true) - } - context.startActivity(intent) - }, - onRegisterSuccess = { - // Todo: Implement onRegisterSuccess - }, - ) - mobileVerificationScreen( - onOtpVerificationSuccess = { fullNumber, extraData -> - navController.navigateToSignup( - savingProductId = extraData[Constants.MIFOS_SAVINGS_PRODUCT_ID] as Int, - mobileNumber = fullNumber, - country = "Canada", - email = extraData[Constants.GOOGLE_EMAIL] as? String ?: "", - firstName = extraData[Constants.GOOGLE_GIVEN_NAME] as? String ?: "", - lastName = extraData[Constants.GOOGLE_FAMILY_NAME] as? String ?: "", - businessName = extraData[Constants.GOOGLE_DISPLAY_NAME] as? String ?: "", - ) - }, - ) + specificTransactionsScreen( + onBackClick = navController::popBackStack, + onTransactionItemClicked = { transactionId -> + navController.navigateToReceipt(Uri.parse(Constants.RECEIPT_DOMAIN + transactionId)) + }, + ) + invoiceDetailScreen( + onBackPress = navController::popBackStack, + navigateToReceiptScreen = { uri -> + navController.navigateToReceipt(Uri.parse(Constants.RECEIPT_DOMAIN + uri)) + }, + ) + receiptScreen( + openPassCodeActivity = { + // TODO: Implement Passcode Screen for Receipt + }, + onBackClick = navController::popBackStack, + ) + setupUpiPinScreen( + onBackPress = navController::popBackStack, + ) - loginScreen( - onDismissSignUp = { - // Todo: Navigate to the main screen after successful login - }, - onNavigateToMobileVerificationScreen = { mifosSignedUp, googleDisplayName, googleEmail, googleFamilyName, googleGivenName -> - navController.navigateToMobileVerification( - mifosSignedUp = mifosSignedUp, - googleDisplayName = googleDisplayName, - googleEmail = googleEmail, - googleFamilyName = googleFamilyName, - googleGivenName = googleGivenName, - ) - }, - ) + bankAccountDetailScreen( + onSetupUpiPin = { bankAccountDetails, index -> + navController.navigateToSetupUpiPin(bankAccountDetails, index, Constants.SETUP) + }, + onChangeUpiPin = { bankAccountDetails, index -> + navController.navigateToSetupUpiPin(bankAccountDetails, index, Constants.CHANGE) + }, + onForgotUpiPin = { bankAccountDetails, index -> + navController.navigateToSetupUpiPin(bankAccountDetails, index, Constants.FORGOT) + }, + onBackClick = { bankAccountDetails, index -> + navController.previousBackStackEntry?.savedStateHandle?.set( + Constants.UPDATED_BANK_ACCOUNT, + bankAccountDetails, + ) + navController.previousBackStackEntry?.savedStateHandle?.set( + Constants.INDEX, + index, + ) + navController.popBackStack() + }, + ) + linkBankAccountScreen( + onBackClick = navController::popBackStack, + ) + editPasswordScreen( + onBackPress = navController::popBackStack, + onCancelChanges = navController::popBackStack, + ) + } } } -private fun Context.logOut() { - val intent = Intent(this, LoginActivity::class.java) - intent.addFlags( - Intent.FLAG_ACTIVITY_CLEAR_TOP or - Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK, - ) - this.startActivity(intent) -} - -private fun Context.onChangePasscodeClicked() { - val passcodePreferencesHelper = PasscodePreferencesHelper(this) - - val currentPasscode = passcodePreferencesHelper.passCode - passcodePreferencesHelper.savePassCode("") - - PassCodeActivity.startPassCodeActivity( - context = this, - bundle = bundleOf( - Pair(Constants.CURRENT_PASSCODE, currentPasscode), - Pair(Constants.UPDATE_PASSCODE, true), - ), - ) -} - -fun Context.openPassCodeActivity(deepLinkURI: Uri) { - PassCodeActivity.startPassCodeActivity( - context = this, - bundle = bundleOf( - Pair("uri", deepLinkURI.toString()), - Pair(PassCodeConstants.PASSCODE_INITIAL_LOGIN, true), - ), - ) -} - fun getUri(context: Context, file: File): Uri { val uri = FileProvider.getUriForFile( Objects.requireNonNull(context), diff --git a/mifospay/src/main/java/org/mifospay/navigation/PasscodeNavGraph.kt b/mifospay/src/main/java/org/mifospay/navigation/PasscodeNavGraph.kt new file mode 100644 index 000000000..3b0f4202a --- /dev/null +++ b/mifospay/src/main/java/org/mifospay/navigation/PasscodeNavGraph.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the 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.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.navigation +import org.mifospay.feature.passcode.PASSCODE_SCREEN +import org.mifospay.feature.passcode.passcodeRoute + +internal fun NavGraphBuilder.passcodeNavGraph(navController: NavController) { + navigation( + route = MifosNavGraph.PASSCODE_GRAPH, + startDestination = PASSCODE_SCREEN, + ) { + passcodeRoute( + onForgotButton = { + navController.popBackStack() + navController.navigate(MifosNavGraph.MAIN_GRAPH) + }, + onSkipButton = { + navController.popBackStack() + navController.navigate(MifosNavGraph.MAIN_GRAPH) + }, + onPasscodeConfirm = { + navController.popBackStack() + navController.navigate(MifosNavGraph.MAIN_GRAPH) + }, + onPasscodeRejected = { + navController.popBackStack() + navController.navigate(MifosNavGraph.MAIN_GRAPH) + }, + ) + } +} diff --git a/mifospay/src/main/java/org/mifospay/navigation/RootNavGraph.kt b/mifospay/src/main/java/org/mifospay/navigation/RootNavGraph.kt new file mode 100644 index 000000000..1a0735b28 --- /dev/null +++ b/mifospay/src/main/java/org/mifospay/navigation/RootNavGraph.kt @@ -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.navigation + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import org.mifospay.ui.MifosApp +import org.mifospay.ui.MifosAppState + +@Composable +internal fun RootNavGraph( + appState: MifosAppState, + navHostController: NavHostController, + startDestination: String, + onClickLogout: () -> Unit, + modifier: Modifier = Modifier, +) { + NavHost( + navController = navHostController, + startDestination = startDestination, + route = MifosNavGraph.ROOT_GRAPH, + modifier = modifier, + ) { + loginNavGraph(navHostController) + + passcodeNavGraph(navHostController) + + composable(MifosNavGraph.MAIN_GRAPH) { + MifosApp( + appState = appState, + onClickLogout = onClickLogout, + ) + } + } +} diff --git a/mifospay/src/main/java/org/mifospay/ui/MifosApp.kt b/mifospay/src/main/java/org/mifospay/ui/MifosApp.kt index 870036332..49dcccfc9 100644 --- a/mifospay/src/main/java/org/mifospay/ui/MifosApp.kt +++ b/mifospay/src/main/java/org/mifospay/ui/MifosApp.kt @@ -25,8 +25,6 @@ import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.material.navigation.BottomSheetNavigator -import androidx.compose.material.navigation.ModalBottomSheetLayout import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api @@ -34,10 +32,8 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarDuration.Indefinite -import androidx.compose.material3.SnackbarDuration.Short import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.SnackbarResult.ActionPerformed import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable @@ -85,7 +81,7 @@ import org.mifospay.navigation.TopLevelDestination @Composable fun MifosApp( appState: MifosAppState, - bottomSheetNavigator: BottomSheetNavigator, + onClickLogout: () -> Unit, modifier: Modifier = Modifier, ) { val shouldShowGradientBackground = @@ -95,11 +91,11 @@ fun MifosApp( MifosBackground(modifier) { MifosGradientBackground( gradientColors = - if (shouldShowGradientBackground) { - LocalGradientColors.current - } else { - GradientColors() - }, + if (shouldShowGradientBackground) { + LocalGradientColors.current + } else { + GradientColors() + }, ) { val snackbarHostState = remember { SnackbarHostState() } @@ -120,11 +116,11 @@ fun MifosApp( AnimatedVisibility(true) { Box( modifier = - Modifier - .fillMaxWidth() - .wrapContentSize(Alignment.TopEnd) - .padding(end = 24.dp) - .background(color = MaterialTheme.colorScheme.surface), + Modifier + .fillMaxWidth() + .wrapContentSize(Alignment.TopEnd) + .padding(end = 24.dp) + .background(color = MaterialTheme.colorScheme.surface), ) { DropdownMenu( modifier = Modifier.background(color = MaterialTheme.colorScheme.surface), @@ -160,17 +156,12 @@ fun MifosApp( } } - // TODO unread destinations to show dot indicator - // val unreadDestinations by appState.topLevelDestinationsWithUnreadResources.collectAsStateWithLifecycle() - Scaffold( - modifier = - Modifier.semantics { - testTagsAsResourceId = true - }, + modifier = Modifier.semantics { + testTagsAsResourceId = true + }, containerColor = Color.Transparent, contentColor = MaterialTheme.colorScheme.onBackground, - contentWindowInsets = WindowInsets(0, 0, 0, 0), snackbarHost = { SnackbarHost(snackbarHostState) }, bottomBar = { if (appState.shouldShowBottomBar) { @@ -202,9 +193,9 @@ fun MifosApp( onNavigateToDestination = appState::navigateToTopLevelDestination, currentDestination = appState.currentDestination, modifier = - Modifier - .testTag("NiaNavRail") - .safeDrawingPadding(), + Modifier + .testTag("NiaNavRail") + .safeDrawingPadding(), ) } @@ -216,33 +207,22 @@ fun MifosApp( titleRes = destination.titleTextId, actionIcon = MifosIcons.MoreVert, actionIconContentDescription = - stringResource( - id = R.string.feature_profile_settings, - ), + stringResource( + id = R.string.feature_profile_settings, + ), colors = - TopAppBarDefaults.centerAlignedTopAppBarColors( - containerColor = Color.Transparent, - ), + TopAppBarDefaults.centerAlignedTopAppBarColors( + containerColor = Color.Transparent, + ), onActionClick = { showHomeMenuOption = true }, ) } - ModalBottomSheetLayout(bottomSheetNavigator = bottomSheetNavigator) { - MifosNavHost( - navController = appState.navController, - onShowSnackbar = { message, action -> - snackbarHostState.showSnackbar( - message = message, - actionLabel = action, - duration = Short, - ) == ActionPerformed - }, - ) - } + MifosNavHost( + appState = appState, + onClickLogout = onClickLogout, + ) } - - // TODO: We may want to add padding or spacer when the snackbar is shown so that - // content doesn't display behind it. } } } @@ -331,11 +311,11 @@ private fun Modifier.notificationDot(): Modifier = // however, its parameters are private, so we must depend on them implicitly // (NavigationBarTokens.ActiveIndicatorWidth = 64.dp) center = - center + - Offset( - 64.dp.toPx() * .45f, - 32.dp.toPx() * -.45f - 6.dp.toPx(), - ), + center + + Offset( + 64.dp.toPx() * .45f, + 32.dp.toPx() * -.45f - 6.dp.toPx(), + ), ) } } diff --git a/mifospay/src/main/java/org/mifospay/ui/MifosAppState.kt b/mifospay/src/main/java/org/mifospay/ui/MifosAppState.kt index 451dfb900..638ff13a7 100644 --- a/mifospay/src/main/java/org/mifospay/ui/MifosAppState.kt +++ b/mifospay/src/main/java/org/mifospay/ui/MifosAppState.kt @@ -9,6 +9,8 @@ */ package org.mifospay.ui +import androidx.compose.material.navigation.BottomSheetNavigator +import androidx.compose.material.navigation.rememberBottomSheetNavigator import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.Composable @@ -47,11 +49,13 @@ fun rememberMifosAppState( networkMonitor: NetworkMonitor, timeZoneMonitor: TimeZoneMonitor, coroutineScope: CoroutineScope = rememberCoroutineScope(), - navController: NavHostController = rememberNavController(), + bottomSheetNavigator: BottomSheetNavigator = rememberBottomSheetNavigator(), + navController: NavHostController = rememberNavController(bottomSheetNavigator), ): MifosAppState { NavigationTrackingSideEffect(navController) return remember( navController, + bottomSheetNavigator, coroutineScope, windowSizeClass, networkMonitor, @@ -59,6 +63,7 @@ fun rememberMifosAppState( ) { MifosAppState( navController = navController, + bottomSheetNavigator = bottomSheetNavigator, coroutineScope = coroutineScope, windowSizeClass = windowSizeClass, networkMonitor = networkMonitor, @@ -70,6 +75,7 @@ fun rememberMifosAppState( @Stable class MifosAppState( val navController: NavHostController, + val bottomSheetNavigator: BottomSheetNavigator, coroutineScope: CoroutineScope, val windowSizeClass: WindowSizeClass, networkMonitor: NetworkMonitor, diff --git a/mifospay/src/main/res/color/background_chip_state.xml b/mifospay/src/main/res/color/background_chip_state.xml deleted file mode 100644 index 2c1244261..000000000 --- a/mifospay/src/main/res/color/background_chip_state.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/bg_et_round_border.xml b/mifospay/src/main/res/drawable/bg_et_round_border.xml deleted file mode 100644 index 3183ca5b4..000000000 --- a/mifospay/src/main/res/drawable/bg_et_round_border.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - diff --git a/mifospay/src/main/res/drawable/bg_splash.xml b/mifospay/src/main/res/drawable/bg_splash.xml index a0baf6d93..da3e7cb77 100644 --- a/mifospay/src/main/res/drawable/bg_splash.xml +++ b/mifospay/src/main/res/drawable/bg_splash.xml @@ -12,9 +12,14 @@ - + \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/button_round_black.xml b/mifospay/src/main/res/drawable/button_round_black.xml deleted file mode 100644 index 835132df5..000000000 --- a/mifospay/src/main/res/drawable/button_round_black.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/button_round_gray.xml b/mifospay/src/main/res/drawable/button_round_gray.xml deleted file mode 100644 index 89b9cb025..000000000 --- a/mifospay/src/main/res/drawable/button_round_gray.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/button_round_primary.xml b/mifospay/src/main/res/drawable/button_round_primary.xml deleted file mode 100644 index 835132df5..000000000 --- a/mifospay/src/main/res/drawable/button_round_primary.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/button_round_stroke.xml b/mifospay/src/main/res/drawable/button_round_stroke.xml deleted file mode 100644 index b7ceb0ef6..000000000 --- a/mifospay/src/main/res/drawable/button_round_stroke.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/button_round_stroke_gray.xml b/mifospay/src/main/res/drawable/button_round_stroke_gray.xml deleted file mode 100644 index 549db6843..000000000 --- a/mifospay/src/main/res/drawable/button_round_stroke_gray.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/button_round_stroke_primary.xml b/mifospay/src/main/res/drawable/button_round_stroke_primary.xml deleted file mode 100644 index fd1c97a74..000000000 --- a/mifospay/src/main/res/drawable/button_round_stroke_primary.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/cardview_round_blue.xml b/mifospay/src/main/res/drawable/cardview_round_blue.xml deleted file mode 100644 index e9c8d2072..000000000 --- a/mifospay/src/main/res/drawable/cardview_round_blue.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/cardview_round_green.xml b/mifospay/src/main/res/drawable/cardview_round_green.xml deleted file mode 100644 index 1be22ce0f..000000000 --- a/mifospay/src/main/res/drawable/cardview_round_green.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/drawable_bottom_sheet_view.xml b/mifospay/src/main/res/drawable/drawable_bottom_sheet_view.xml deleted file mode 100644 index df68df456..000000000 --- a/mifospay/src/main/res/drawable/drawable_bottom_sheet_view.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/drawable_editable_image_hint.xml b/mifospay/src/main/res/drawable/drawable_editable_image_hint.xml deleted file mode 100644 index 1b66a55c6..000000000 --- a/mifospay/src/main/res/drawable/drawable_editable_image_hint.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/et_search.xml b/mifospay/src/main/res/drawable/et_search.xml deleted file mode 100644 index 6a0efb4c1..000000000 --- a/mifospay/src/main/res/drawable/et_search.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_account_balance_wallet.xml b/mifospay/src/main/res/drawable/ic_account_balance_wallet.xml deleted file mode 100644 index 0f123f2c2..000000000 --- a/mifospay/src/main/res/drawable/ic_account_balance_wallet.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_accounts.xml b/mifospay/src/main/res/drawable/ic_accounts.xml deleted file mode 100644 index 3ea27ba5e..000000000 --- a/mifospay/src/main/res/drawable/ic_accounts.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_add.xml b/mifospay/src/main/res/drawable/ic_add.xml deleted file mode 100644 index b52ca0588..000000000 --- a/mifospay/src/main/res/drawable/ic_add.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_add_white.xml b/mifospay/src/main/res/drawable/ic_add_white.xml deleted file mode 100644 index a74762170..000000000 --- a/mifospay/src/main/res/drawable/ic_add_white.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_arrow_back_black_24dp.xml b/mifospay/src/main/res/drawable/ic_arrow_back_black_24dp.xml deleted file mode 100644 index dbbf1e74d..000000000 --- a/mifospay/src/main/res/drawable/ic_arrow_back_black_24dp.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_arrow_back_white_24dp.xml b/mifospay/src/main/res/drawable/ic_arrow_back_white_24dp.xml deleted file mode 100644 index b0c052c88..000000000 --- a/mifospay/src/main/res/drawable/ic_arrow_back_white_24dp.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_bank.xml b/mifospay/src/main/res/drawable/ic_bank.xml deleted file mode 100644 index a7856762d..000000000 --- a/mifospay/src/main/res/drawable/ic_bank.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_baseline_content_copy_24.xml b/mifospay/src/main/res/drawable/ic_baseline_content_copy_24.xml deleted file mode 100644 index 9b5e86d30..000000000 --- a/mifospay/src/main/res/drawable/ic_baseline_content_copy_24.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_baseline_insert_photo_24.xml b/mifospay/src/main/res/drawable/ic_baseline_insert_photo_24.xml deleted file mode 100644 index 9a6558e47..000000000 --- a/mifospay/src/main/res/drawable/ic_baseline_insert_photo_24.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_baseline_share_24.xml b/mifospay/src/main/res/drawable/ic_baseline_share_24.xml deleted file mode 100644 index 7eea3e481..000000000 --- a/mifospay/src/main/res/drawable/ic_baseline_share_24.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_camera.xml b/mifospay/src/main/res/drawable/ic_camera.xml deleted file mode 100644 index dffa5d6df..000000000 --- a/mifospay/src/main/res/drawable/ic_camera.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - diff --git a/mifospay/src/main/res/drawable/ic_cards.xml b/mifospay/src/main/res/drawable/ic_cards.xml deleted file mode 100644 index a43e8e0e7..000000000 --- a/mifospay/src/main/res/drawable/ic_cards.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_check_round_black_24dp.xml b/mifospay/src/main/res/drawable/ic_check_round_black_24dp.xml deleted file mode 100644 index fb907bfa1..000000000 --- a/mifospay/src/main/res/drawable/ic_check_round_black_24dp.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_close.xml b/mifospay/src/main/res/drawable/ic_close.xml deleted file mode 100644 index e024ce4a4..000000000 --- a/mifospay/src/main/res/drawable/ic_close.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_contact.xml b/mifospay/src/main/res/drawable/ic_contact.xml deleted file mode 100644 index a2bb581a3..000000000 --- a/mifospay/src/main/res/drawable/ic_contact.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_done.xml b/mifospay/src/main/res/drawable/ic_done.xml deleted file mode 100644 index 213fa116a..000000000 --- a/mifospay/src/main/res/drawable/ic_done.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_edit.xml b/mifospay/src/main/res/drawable/ic_edit.xml deleted file mode 100644 index 1aaddb39c..000000000 --- a/mifospay/src/main/res/drawable/ic_edit.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_email.xml b/mifospay/src/main/res/drawable/ic_email.xml deleted file mode 100644 index c0bc3b329..000000000 --- a/mifospay/src/main/res/drawable/ic_email.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/mifospay/src/main/res/drawable/ic_empty_state.xml b/mifospay/src/main/res/drawable/ic_empty_state.xml deleted file mode 100644 index 490b6be50..000000000 --- a/mifospay/src/main/res/drawable/ic_empty_state.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_error_state.xml b/mifospay/src/main/res/drawable/ic_error_state.xml deleted file mode 100644 index 5ff3eb681..000000000 --- a/mifospay/src/main/res/drawable/ic_error_state.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_flash_off.xml b/mifospay/src/main/res/drawable/ic_flash_off.xml deleted file mode 100644 index da6195745..000000000 --- a/mifospay/src/main/res/drawable/ic_flash_off.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_flash_on.xml b/mifospay/src/main/res/drawable/ic_flash_on.xml deleted file mode 100644 index 40d5c8118..000000000 --- a/mifospay/src/main/res/drawable/ic_flash_on.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_history.xml b/mifospay/src/main/res/drawable/ic_history.xml deleted file mode 100644 index bec66e5f9..000000000 --- a/mifospay/src/main/res/drawable/ic_history.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_invoice.xml b/mifospay/src/main/res/drawable/ic_invoice.xml deleted file mode 100644 index 4014b0003..000000000 --- a/mifospay/src/main/res/drawable/ic_invoice.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_invoices.xml b/mifospay/src/main/res/drawable/ic_invoices.xml deleted file mode 100644 index d05eb17b7..000000000 --- a/mifospay/src/main/res/drawable/ic_invoices.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_logo_outline.xml b/mifospay/src/main/res/drawable/ic_logo_outline.xml deleted file mode 100644 index 842e0a73c..000000000 --- a/mifospay/src/main/res/drawable/ic_logo_outline.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - diff --git a/mifospay/src/main/res/drawable/ic_merchant.xml b/mifospay/src/main/res/drawable/ic_merchant.xml deleted file mode 100644 index d0565b244..000000000 --- a/mifospay/src/main/res/drawable/ic_merchant.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_merchants.xml b/mifospay/src/main/res/drawable/ic_merchants.xml deleted file mode 100644 index 2b8395da7..000000000 --- a/mifospay/src/main/res/drawable/ic_merchants.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_mobile.xml b/mifospay/src/main/res/drawable/ic_mobile.xml deleted file mode 100644 index fc0915a7b..000000000 --- a/mifospay/src/main/res/drawable/ic_mobile.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/mifospay/src/main/res/drawable/ic_next.xml b/mifospay/src/main/res/drawable/ic_next.xml deleted file mode 100644 index ac2958c7e..000000000 --- a/mifospay/src/main/res/drawable/ic_next.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_next_black.xml b/mifospay/src/main/res/drawable/ic_next_black.xml deleted file mode 100644 index 4d2ec831c..000000000 --- a/mifospay/src/main/res/drawable/ic_next_black.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_notification.xml b/mifospay/src/main/res/drawable/ic_notification.xml deleted file mode 100644 index 8431212e9..000000000 --- a/mifospay/src/main/res/drawable/ic_notification.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_photo_library.xml b/mifospay/src/main/res/drawable/ic_photo_library.xml deleted file mode 100644 index 3b5fcab42..000000000 --- a/mifospay/src/main/res/drawable/ic_photo_library.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_remove.xml b/mifospay/src/main/res/drawable/ic_remove.xml deleted file mode 100644 index c861a572b..000000000 --- a/mifospay/src/main/res/drawable/ic_remove.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_remove_circle_outline_black_24dp.xml b/mifospay/src/main/res/drawable/ic_remove_circle_outline_black_24dp.xml deleted file mode 100644 index a9e118ffc..000000000 --- a/mifospay/src/main/res/drawable/ic_remove_circle_outline_black_24dp.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_repeat.xml b/mifospay/src/main/res/drawable/ic_repeat.xml deleted file mode 100644 index f413b236e..000000000 --- a/mifospay/src/main/res/drawable/ic_repeat.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_repeat_selector.xml b/mifospay/src/main/res/drawable/ic_repeat_selector.xml deleted file mode 100644 index 6fac0b5ce..000000000 --- a/mifospay/src/main/res/drawable/ic_repeat_selector.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_request.xml b/mifospay/src/main/res/drawable/ic_request.xml deleted file mode 100644 index fdc053093..000000000 --- a/mifospay/src/main/res/drawable/ic_request.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_request_selector.xml b/mifospay/src/main/res/drawable/ic_request_selector.xml deleted file mode 100644 index 616adda63..000000000 --- a/mifospay/src/main/res/drawable/ic_request_selector.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_right_arrow.xml b/mifospay/src/main/res/drawable/ic_right_arrow.xml deleted file mode 100644 index f68f3f5af..000000000 --- a/mifospay/src/main/res/drawable/ic_right_arrow.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_save.xml b/mifospay/src/main/res/drawable/ic_save.xml deleted file mode 100644 index 72297264a..000000000 --- a/mifospay/src/main/res/drawable/ic_save.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_saved_cards.xml b/mifospay/src/main/res/drawable/ic_saved_cards.xml deleted file mode 100644 index 58461dd25..000000000 --- a/mifospay/src/main/res/drawable/ic_saved_cards.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_search.xml b/mifospay/src/main/res/drawable/ic_search.xml deleted file mode 100644 index a9de3da63..000000000 --- a/mifospay/src/main/res/drawable/ic_search.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_send.xml b/mifospay/src/main/res/drawable/ic_send.xml deleted file mode 100644 index 5842a8d27..000000000 --- a/mifospay/src/main/res/drawable/ic_send.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_send_selector.xml b/mifospay/src/main/res/drawable/ic_send_selector.xml deleted file mode 100644 index e7c9f0678..000000000 --- a/mifospay/src/main/res/drawable/ic_send_selector.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_setting.xml b/mifospay/src/main/res/drawable/ic_setting.xml deleted file mode 100644 index adaf75e5d..000000000 --- a/mifospay/src/main/res/drawable/ic_setting.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/ic_share.xml b/mifospay/src/main/res/drawable/ic_share.xml deleted file mode 100644 index 5a08b5b29..000000000 --- a/mifospay/src/main/res/drawable/ic_share.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_tick.xml b/mifospay/src/main/res/drawable/ic_tick.xml deleted file mode 100644 index 9896786da..000000000 --- a/mifospay/src/main/res/drawable/ic_tick.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/ic_transaction.xml b/mifospay/src/main/res/drawable/ic_transaction.xml deleted file mode 100644 index 67034ba01..000000000 --- a/mifospay/src/main/res/drawable/ic_transaction.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - diff --git a/mifospay/src/main/res/drawable/ic_verify.xml b/mifospay/src/main/res/drawable/ic_verify.xml deleted file mode 100644 index 72a380b1a..000000000 --- a/mifospay/src/main/res/drawable/ic_verify.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/layout_rounded_edge.xml b/mifospay/src/main/res/drawable/layout_rounded_edge.xml deleted file mode 100644 index 033749202..000000000 --- a/mifospay/src/main/res/drawable/layout_rounded_edge.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/qrcode_black.xml b/mifospay/src/main/res/drawable/qrcode_black.xml deleted file mode 100644 index 274f795d4..000000000 --- a/mifospay/src/main/res/drawable/qrcode_black.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/qrcode_black_selector.xml b/mifospay/src/main/res/drawable/qrcode_black_selector.xml deleted file mode 100644 index d0b33aeec..000000000 --- a/mifospay/src/main/res/drawable/qrcode_black_selector.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/qrcode_blue.xml b/mifospay/src/main/res/drawable/qrcode_blue.xml deleted file mode 100644 index a84a08aef..000000000 --- a/mifospay/src/main/res/drawable/qrcode_blue.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/qrcode_blue_selector.xml b/mifospay/src/main/res/drawable/qrcode_blue_selector.xml deleted file mode 100644 index bc8be6c54..000000000 --- a/mifospay/src/main/res/drawable/qrcode_blue_selector.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/shape_bottom_sheet_dialog_grip.xml b/mifospay/src/main/res/drawable/shape_bottom_sheet_dialog_grip.xml deleted file mode 100644 index a182bf8d3..000000000 --- a/mifospay/src/main/res/drawable/shape_bottom_sheet_dialog_grip.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/mifospay/src/main/res/drawable/sim_card_selected.xml b/mifospay/src/main/res/drawable/sim_card_selected.xml deleted file mode 100644 index 369a18515..000000000 --- a/mifospay/src/main/res/drawable/sim_card_selected.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/sim_card_unselected.xml b/mifospay/src/main/res/drawable/sim_card_unselected.xml deleted file mode 100644 index 90c592e68..000000000 --- a/mifospay/src/main/res/drawable/sim_card_unselected.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/transfer_failure.xml b/mifospay/src/main/res/drawable/transfer_failure.xml deleted file mode 100644 index cf8068363..000000000 --- a/mifospay/src/main/res/drawable/transfer_failure.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/drawable/transfer_success.xml b/mifospay/src/main/res/drawable/transfer_success.xml deleted file mode 100644 index 736913a81..000000000 --- a/mifospay/src/main/res/drawable/transfer_success.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mifospay/src/main/res/values/splash.xml b/mifospay/src/main/res/values/splash.xml index 14a51f31a..cf5c6b597 100644 --- a/mifospay/src/main/res/values/splash.xml +++ b/mifospay/src/main/res/values/splash.xml @@ -10,9 +10,10 @@ --> - diff --git a/mifospay/src/main/res/values/themes.xml b/mifospay/src/main/res/values/themes.xml index 6821d923c..d16d98d50 100644 --- a/mifospay/src/main/res/values/themes.xml +++ b/mifospay/src/main/res/values/themes.xml @@ -8,7 +8,7 @@ See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md --> - + diff --git a/settings.gradle.kts b/settings.gradle.kts index 94141b7a7..22ffdf4ae 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,21 +4,13 @@ pluginManagement { gradlePluginPortal() google() mavenCentral() - maven("https://www.jitpack.io") - maven("https://plugins.gradle.org/m2/") } } dependencyResolutionManagement { - - // repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) was removed as it centralized repository configuration in this - // file to ensure that all subprojects use the same repositories. As a result Gradle has deprecated the use of project-level repositories in favor of settings-level repositories, - // leading to warnings or errors if project repositories are still used when RepositoriesMode.FAIL_ON_PROJECT_REPOS is enabled. - // Find the discussion at https://stackoverflow.com/questions/69163511/build-was-configured-to-prefer-settings-repositories-over-project-repositories-b - + repositoriesMode.set(RepositoriesMode.PREFER_PROJECT) repositories { google() mavenCentral() - jcenter() maven("https://www.jitpack.io") maven("https://plugins.gradle.org/m2/") } @@ -39,6 +31,7 @@ include(":core:model") include(":core:datastore-proto") include(":core:analytics") +include(":feature:home") include(":feature:history") include(":feature:receipt") include(":feature:faq") @@ -62,6 +55,6 @@ include(":feature:payments") include(":feature:request-money") include(":feature:upi-setup") include(":feature:qr") -include(":feature:home") + include(":shared") include(":desktop") diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 3f1a7de1e..8ca79392c 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -23,7 +23,7 @@ kotlin { } jvm("desktop"){ - jvmToolchain(17) + jvmToolchain(21) } listOf(