├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── dev-request.yml │ └── feature-request.yml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── apk.yml │ ├── automatic_release.yml │ ├── ci_actions_test.yml │ ├── compose_stability.yml │ ├── detekt.yml │ ├── integration_test.yml │ ├── internal_release.yml │ ├── issue_assign.yml │ ├── issue_created.yml │ ├── lint.yml │ ├── paparazzi_screenshot_test.yml │ ├── pr_description.yml │ ├── stale.yml │ ├── test.yml │ └── upgrade-gradle-wrapper.yml ├── .gitignore ├── .idea ├── .gitignore ├── .name ├── compiler.xml └── migrations.xml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── all_modules.gv ├── app ├── build.gradle.kts ├── google-services.json ├── lint-baseline.xml ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ ├── IvyNavGraph.kt │ │ │ └── wallet │ │ │ ├── IvyAndroidApp.kt │ │ │ ├── IvyAppStarter.kt │ │ │ ├── PaymentTileService.kt │ │ │ ├── RootActivity.kt │ │ │ ├── RootViewModel.kt │ │ │ ├── di │ │ │ └── AppBindingsModule.kt │ │ │ ├── migrations │ │ │ ├── Migration.kt │ │ │ ├── MigrationsManager.kt │ │ │ └── impl │ │ │ │ └── DisableGitHubAutoBackupMigration.kt │ │ │ └── ui │ │ │ └── applocked │ │ │ └── AppLockedScreen.kt │ └── res │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_monochrome.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_monochrome.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_monochrome.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_monochrome.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_foreground.webp │ │ ├── ic_launcher_monochrome.webp │ │ └── ic_launcher_round.webp │ │ ├── resources.properties │ │ ├── values │ │ ├── ic_launcher_background.xml │ │ └── styles.xml │ │ └── xml │ │ └── shortcuts.xml │ └── release │ └── res │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ ├── ic_launcher_monochrome.webp │ └── ic_launcher_round.webp │ ├── mipmap-mdpi │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ ├── ic_launcher_monochrome.webp │ └── ic_launcher_round.webp │ ├── mipmap-xhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ ├── ic_launcher_monochrome.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ ├── ic_launcher_monochrome.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxxhdpi │ ├── ic_launcher.webp │ ├── ic_launcher_foreground.webp │ ├── ic_launcher_monochrome.webp │ └── ic_launcher_round.webp │ └── values │ └── ic_launcher_background.xml ├── build.gradle.kts ├── buildSrc ├── build.gradle.kts ├── settings.gradle.kts └── src │ └── main │ └── kotlin │ ├── ivy.compose.gradle.kts │ ├── ivy.detekt.gradle.kts │ ├── ivy.feature.gradle.kts │ ├── ivy.hilt.gradle.kts │ ├── ivy.integration.testing.gradle.kts │ ├── ivy.kotlin-android.gradle.kts │ ├── ivy.kotlinx-serialization.gradle.kts │ ├── ivy.module.gradle.kts │ ├── ivy.paparazzi.gradle.kts │ ├── ivy.room.gradle.kts │ ├── ivy.script.gradle.kts │ ├── ivy.widget.gradle.kts │ └── versionCatalog.kt ├── ci-actions ├── base │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── ivy │ │ │ └── automate │ │ │ └── base │ │ │ ├── ArgsParseExt.kt │ │ │ ├── ArrowExt.kt │ │ │ ├── Common.kt │ │ │ ├── Constants.kt │ │ │ ├── ExactDsl.kt │ │ │ ├── IvyError.kt │ │ │ ├── github │ │ │ ├── GitHubIssueArgs.kt │ │ │ ├── GitHubService.kt │ │ │ ├── GitHubServiceImpl.kt │ │ │ └── model │ │ │ │ ├── GitHubComment.kt │ │ │ │ ├── GitHubIssue.kt │ │ │ │ ├── GitHubIssueNumber.kt │ │ │ │ ├── GitHubLabel.kt │ │ │ │ ├── GitHubLabelName.kt │ │ │ │ ├── GitHubPAT.kt │ │ │ │ ├── GitHubUser.kt │ │ │ │ ├── GitHubUsername.kt │ │ │ │ └── NotBlankTrimmedString.kt │ │ │ └── ktor │ │ │ └── KtorClientScope.kt │ │ └── test │ │ └── kotlin │ │ └── ivy │ │ └── automate │ │ └── base │ │ ├── github │ │ └── GitHubIssueArgsTest.kt │ │ └── model │ │ ├── GitHubIssueNumberTest.kt │ │ ├── GitHubLabelNameTest.kt │ │ ├── GitHubPATTest.kt │ │ ├── GitHubUsernameTest.kt │ │ └── NotBlankTrimmedStringTest.kt ├── compose-stability │ ├── build.gradle.kts │ ├── ivy-compose-stability-baseline.txt │ └── src │ │ └── main │ │ └── kotlin │ │ └── ivy │ │ └── automate │ │ └── compose │ │ └── stability │ │ ├── Main.kt │ │ └── model │ │ └── UnstableComposable.kt ├── issue-assign │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── ivy │ │ │ └── automate │ │ │ └── issue │ │ │ ├── ActionExecutor.kt │ │ │ ├── CommentAnalyzer.kt │ │ │ ├── DetermineAction.kt │ │ │ └── Main.kt │ │ └── test │ │ └── kotlin │ │ └── ivy │ │ └── automate │ │ └── issue │ │ ├── ActionExecutorTest.kt │ │ ├── CommentAnalyzerTest.kt │ │ └── DetermineActionTest.kt ├── issue-create-comment │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── ivy │ │ │ └── automate │ │ │ └── issue │ │ │ └── create │ │ │ └── Main.kt │ │ └── test │ │ └── kotlin │ │ └── ivy │ │ └── automate │ │ └── issue │ │ └── create │ │ └── CommentTextTest.kt └── pr-description-check │ ├── build.gradle.kts │ └── src │ ├── main │ └── kotlin │ │ └── ivy │ │ └── automate │ │ └── pr │ │ ├── ClosesIssueAnalyzer.kt │ │ ├── Main.kt │ │ └── PRDescriptionAnalyzer.kt │ └── test │ └── kotlin │ └── ivy │ └── automate │ └── pr │ └── ClosesIssueAnalyzerTest.kt ├── config └── detekt │ ├── baseline.yml │ └── config.yml ├── debug.jks ├── docs ├── CI-Troubleshooting.md ├── Guidelines.md ├── archive │ └── Yoda-Style-Architecture.md ├── assets │ ├── app-layers.d2 │ ├── app-layers.svg │ ├── architecture.d2 │ ├── architecture.svg │ ├── data-mapping.d2 │ ├── data-mapping.svg │ ├── modularization.d2 │ ├── modularization.svg │ ├── modules-graph.svg │ ├── screen-vm.d2 │ └── screen-vm.svg ├── guidelines │ ├── Architecture.md │ ├── Data-Modeling.md │ ├── Error-Handling.md │ ├── README.md │ ├── Screen-Architecture.md │ ├── Screenshot-Testing.md │ └── Unit-Testing.md └── resources │ ├── Blog-Articles.md │ ├── Books.md │ ├── Docs.md │ ├── README.md │ └── Videos.md ├── fastlane ├── Appfile ├── Fastfile └── metadata │ └── android │ └── en-GB │ └── changelogs │ └── default.txt ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screen ├── accounts │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── accounts │ │ │ ├── AccountsEvent.kt │ │ │ ├── AccountsState.kt │ │ │ ├── AccountsTab.kt │ │ │ ├── AccountsViewModel.kt │ │ │ └── IncomeExpensesRow.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── accounts │ │ │ └── AccountsTabPaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab compact composable[Dark].png │ │ ├── com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab compact composable[Light].png │ │ ├── com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab composable[Dark].png │ │ ├── com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab composable[Light].png │ │ ├── com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab nonCompact composable[Dark].png │ │ └── com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab nonCompact composable[Light].png ├── attributions │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── attributions │ │ │ ├── AttributionItem.kt │ │ │ ├── AttributionsEvent.kt │ │ │ ├── AttributionsProvider.kt │ │ │ ├── AttributionsScreen.kt │ │ │ ├── AttributionsState.kt │ │ │ └── AttributionsViewModel.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── attributions │ │ │ └── AttributionsScreenPaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.attributions_AttributionsScreenPaparazziTest_snapshot Attribution Screen[Dark].png │ │ └── com.ivy.attributions_AttributionsScreenPaparazziTest_snapshot Attribution Screen[Light].png ├── balance │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── balance │ │ │ ├── BalanceEvent.kt │ │ │ ├── BalanceScreen.kt │ │ │ ├── BalanceState.kt │ │ │ └── BalanceViewModel.kt │ │ └── test │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.balance_BalanceScreenPaparazziTest_snapshot Balance Screen[Dark].png │ │ └── com.ivy.balance_BalanceScreenPaparazziTest_snapshot Balance Screen[Light].png ├── budgets │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── budgets │ │ ├── BudgetBottomBar.kt │ │ ├── BudgetExt.kt │ │ ├── BudgetModal.kt │ │ ├── BudgetScreen.kt │ │ ├── BudgetScreenEvent.kt │ │ ├── BudgetScreenState.kt │ │ ├── BudgetViewModel.kt │ │ └── model │ │ └── DisplayBudget.kt ├── categories │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── categories │ │ │ ├── CategoriesBottomBar.kt │ │ │ ├── CategoriesScreen.kt │ │ │ ├── CategoriesScreenEvent.kt │ │ │ ├── CategoriesScreenState.kt │ │ │ ├── CategoriesViewModel.kt │ │ │ └── CategoryData.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── categories │ │ │ └── CategoriesScreenPaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories Screen[Dark].png │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories Screen[Light].png │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen with search bar[Dark].png │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen with search bar[Light].png │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen[Dark].png │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen[Light].png │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen with search bar[Dark].png │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen with search bar[Light].png │ │ ├── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen[Dark].png │ │ └── com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen[Light].png ├── contributors │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── contributors │ │ │ ├── Contributor.kt │ │ │ ├── ContributorsEvent.kt │ │ │ ├── ContributorsScreen.kt │ │ │ ├── ContributorsState.kt │ │ │ ├── ContributorsViewModel.kt │ │ │ ├── IvyWalletRepositoryDataSource.kt │ │ │ └── ProjectRepositoryInfo.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── contributors │ │ │ ├── ContributorsScreenPaparazziTest.kt │ │ │ └── ContributorsViewModelTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.contributors_ContributorsScreenPaparazziTest_snapshot Contributor Screen[Dark].png │ │ └── com.ivy.contributors_ContributorsScreenPaparazziTest_snapshot Contributor Screen[Light].png ├── disclaimer │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── disclaimer │ │ │ ├── DisclaimerScreen.kt │ │ │ ├── DisclaimerViewModel.kt │ │ │ ├── DisclaimerViewState.kt │ │ │ └── composables │ │ │ ├── AcceptTermsText.kt │ │ │ ├── AgreeButton.kt │ │ │ ├── AgreementCheckBox.kt │ │ │ └── DisclaimerTopAppBar.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── disclaimer │ │ │ └── DisclaimerScreenPaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.disclaimer_DisclaimerScreenPaparazziTest_all checked[Dark].png │ │ ├── com.ivy.disclaimer_DisclaimerScreenPaparazziTest_all checked[Light].png │ │ ├── com.ivy.disclaimer_DisclaimerScreenPaparazziTest_none checked[Dark].png │ │ └── com.ivy.disclaimer_DisclaimerScreenPaparazziTest_none checked[Light].png ├── edit-transaction │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── transaction │ │ ├── EditTransactionScreen.kt │ │ ├── EditTransactionViewEvent.kt │ │ └── EditTransactionViewModel.kt ├── exchange-rates │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── exchangerates │ │ │ ├── ExchangeRateBottomBar.kt │ │ │ ├── ExchangeRatesScreen.kt │ │ │ ├── ExchangeRatesViewModel.kt │ │ │ ├── RatesEvent.kt │ │ │ ├── RatesState.kt │ │ │ ├── component │ │ │ └── RateItem.kt │ │ │ ├── data │ │ │ └── RateUi.kt │ │ │ └── modal │ │ │ └── AddRateModal.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── exchangerates │ │ │ └── ExchangeRatesScreenPaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.exchangerates_ExchangeRatesScreenPaparazziTest_snapshot Exchange Rates Screen[Dark].png │ │ └── com.ivy.exchangerates_ExchangeRatesScreenPaparazziTest_snapshot Exchange Rates Screen[Light].png ├── features │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── features │ │ ├── FeaturesScreen.kt │ │ ├── FeaturesUiEvent.kt │ │ ├── FeaturesUiState.kt │ │ └── FeaturesViewModel.kt ├── home │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── home │ │ │ ├── Constants.kt │ │ │ ├── HomeEvent.kt │ │ │ ├── HomeHeader.kt │ │ │ ├── HomeMoreMenu.kt │ │ │ ├── HomeState.kt │ │ │ ├── HomeTab.kt │ │ │ ├── HomeViewModel.kt │ │ │ └── customerjourney │ │ │ ├── CustomerJourney.kt │ │ │ ├── CustomerJourneyCardModel.kt │ │ │ └── CustomerJourneyCardsProvider.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── home │ │ │ └── HomePaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.home_HomePaparazziTest_snapshot Home Screen[Dark].png │ │ └── com.ivy.home_HomePaparazziTest_snapshot Home Screen[Light].png ├── import-data │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── importdata │ │ ├── csv │ │ ├── CSVEvent.kt │ │ ├── CSVScreen.kt │ │ ├── CSVState.kt │ │ ├── CSVViewModel.kt │ │ └── domain │ │ │ ├── CSVImporterV2.kt │ │ │ ├── ParseFields.kt │ │ │ └── ParseStatus.kt │ │ └── csvimport │ │ ├── ImportScreen.kt │ │ ├── ImportStep.kt │ │ ├── ImportViewModel.kt │ │ └── flow │ │ ├── ImportFrom.kt │ │ ├── ImportProcessing.kt │ │ ├── ImportResultUI.kt │ │ ├── ImportSteps.kt │ │ └── instructions │ │ ├── DefaultImportSteps.kt │ │ ├── FinancistoSteps.kt │ │ ├── FortuneCitySteps.kt │ │ ├── ImportInstructions.kt │ │ ├── IvyWalletSteps.kt │ │ ├── KTWMoneyMangerSteps.kt │ │ ├── MonefySteps.kt │ │ ├── MoneyManagerPraseSteps.kt │ │ ├── OneMoneySteps.kt │ │ ├── SpendeeSteps.kt │ │ └── WalletByBudgetBakersSteps.kt ├── loans │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── loans │ │ │ ├── loan │ │ │ ├── Constants.kt │ │ │ ├── LoanBottomBar.kt │ │ │ ├── LoanScreenEvent.kt │ │ │ ├── LoanScreenState.kt │ │ │ ├── LoanTab.kt │ │ │ ├── LoanViewModel.kt │ │ │ ├── LoansScreen.kt │ │ │ └── data │ │ │ │ ├── DisplayLoan.kt │ │ │ │ └── DisplayLoanRecord.kt │ │ │ └── loandetails │ │ │ ├── LoanDetailsScreen.kt │ │ │ ├── LoanDetailsScreenState.kt │ │ │ ├── LoanDetailsViewModel.kt │ │ │ └── events │ │ │ ├── DeleteLoanModalEvent.kt │ │ │ ├── LoanDetailsScreenEvent.kt │ │ │ ├── LoanModalEvent.kt │ │ │ └── LoanRecordModalEvent.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── loans │ │ │ └── LoanScreenPaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen composable[Dark].png │ │ ├── com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen composable[Light].png │ │ ├── com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen non tabular composable[Dark].png │ │ ├── com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen non tabular composable[Light].png │ │ ├── com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen tabular composable[Dark].png │ │ └── com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen tabular composable[Light].png ├── main │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── main │ │ ├── MainBottomBar.kt │ │ ├── MainScreen.kt │ │ └── MainViewModel.kt ├── onboarding │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── onboarding │ │ ├── OnboardingDetailState.kt │ │ ├── OnboardingEvent.kt │ │ ├── OnboardingScreen.kt │ │ ├── OnboardingState.kt │ │ ├── components │ │ ├── OnboardingProgressSlider.kt │ │ ├── OnboardingToolbar.kt │ │ └── Suggestions.kt │ │ ├── steps │ │ ├── OnboardingAccounts.kt │ │ ├── OnboardingCategories.kt │ │ ├── OnboardingSetCurrency.kt │ │ ├── OnboardingSplashLogin.kt │ │ ├── OnboardingType.kt │ │ └── archived │ │ │ ├── OnboardingPrivacyTC.kt │ │ │ └── OnboardingSetName.kt │ │ └── viewmodel │ │ ├── OnboardingRouter.kt │ │ └── OnboardingViewModel.kt ├── piechart │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── piechart │ │ ├── CategoryAmount.kt │ │ ├── PieChart.kt │ │ ├── PieChartStatisticBottomBar.kt │ │ ├── PieChartStatisticEvent.kt │ │ ├── PieChartStatisticScreen.kt │ │ ├── PieChartStatisticState.kt │ │ ├── PieChartStatisticViewModel.kt │ │ ├── SelectedCategory.kt │ │ └── action │ │ └── PieChartAct.kt ├── planned-payments │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── planned │ │ ├── edit │ │ ├── EditPlannedScreen.kt │ │ ├── EditPlannedScreenEvent.kt │ │ ├── EditPlannedScreenState.kt │ │ ├── EditPlannedViewModel.kt │ │ └── RecurringRule.kt │ │ └── list │ │ ├── PlannedPaymentCard.kt │ │ ├── PlannedPaymentsBottomBar.kt │ │ ├── PlannedPaymentsLazyColumn.kt │ │ ├── PlannedPaymentsScreen.kt │ │ ├── PlannedPaymentsScreenEvent.kt │ │ ├── PlannedPaymentsScreenState.kt │ │ └── PlannedPaymentsViewModel.kt ├── releases │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── releases │ │ │ ├── ReleaseInfo.kt │ │ │ ├── ReleasesContentParser.kt │ │ │ ├── ReleasesDataSource.kt │ │ │ ├── ReleasesEvent.kt │ │ │ ├── ReleasesScreen.kt │ │ │ ├── ReleasesState.kt │ │ │ └── ReleasesViewModel.kt │ │ └── test │ │ └── java │ │ └── com │ │ └── ivy │ │ └── releases │ │ └── ReleasesContentParserTest.kt ├── reports │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── reports │ │ │ ├── FilterOverlay.kt │ │ │ ├── ReportFilter.kt │ │ │ ├── ReportScreen.kt │ │ │ ├── ReportScreenEvent.kt │ │ │ ├── ReportScreenState.kt │ │ │ └── ReportViewModel.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── report │ │ │ └── ReportPaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.report_ReportPaparazziTest_snapshot Report Screen no filter[Dark].png │ │ ├── com.ivy.report_ReportPaparazziTest_snapshot Report Screen no filter[Light].png │ │ ├── com.ivy.report_ReportPaparazziTest_snapshot Report Screen[Dark].png │ │ └── com.ivy.report_ReportPaparazziTest_snapshot Report Screen[Light].png ├── search │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── search │ │ │ ├── SearchEvent.kt │ │ │ ├── SearchScreen.kt │ │ │ ├── SearchState.kt │ │ │ └── SearchViewModel.kt │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── search │ │ │ └── SearchPaparazziTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.search_SearchPaparazziTest_snapshot Search Screen[Dark].png │ │ └── com.ivy.search_SearchPaparazziTest_snapshot Search Screen[Light].png ├── settings │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── settings │ │ ├── SettingsEvent.kt │ │ ├── SettingsScreen.kt │ │ ├── SettingsState.kt │ │ └── SettingsViewModel.kt └── transactions │ ├── build.gradle.kts │ └── src │ ├── main │ └── java │ │ └── com │ │ └── ivy │ │ └── transactions │ │ ├── TransactionsEvent.kt │ │ ├── TransactionsScreen.kt │ │ ├── TransactionsState.kt │ │ └── TransactionsViewModel.kt │ └── test │ ├── java │ └── com │ │ └── ivy │ │ └── transactions │ │ └── TransactionsPaparazziTest.kt │ └── snapshots │ └── images │ ├── com.ivy.transactions_TransactionsPaparazziTest_snapshot Transactions Screen[Dark].png │ └── com.ivy.transactions_TransactionsPaparazziTest_snapshot Transactions Screen[Light].png ├── scripts ├── composeStability.sh ├── composeStabilityBaseline.sh ├── detekt.sh ├── detektBaseline.sh ├── detektFormat.sh ├── generateModulesGraph.sh ├── integrationTests.sh ├── lint.sh ├── lintBaseline.sh ├── paparazziScreenshotTests.sh └── unitTests.sh ├── settings.gradle.kts ├── shared ├── base │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── base │ │ │ ├── TestDispatchersProvider.kt │ │ │ ├── Toaster.kt │ │ │ ├── di │ │ │ ├── BaseHiltBindings.kt │ │ │ ├── BaseModule.kt │ │ │ └── KotlinxSerializationModule.kt │ │ │ ├── kotlinxserilzation │ │ │ ├── KSerializerInstant.kt │ │ │ ├── KSerializerLocalDateTime.kt │ │ │ └── KSerializerUUID.kt │ │ │ ├── legacy │ │ │ ├── DateTimeUtil.kt │ │ │ ├── FileUtil.kt │ │ │ ├── GlobalUtils.kt │ │ │ ├── LegacyTag.kt │ │ │ ├── SharedPrefs.kt │ │ │ ├── Theme.kt │ │ │ ├── Transaction.kt │ │ │ ├── TransactionHistoryItem.kt │ │ │ └── ZipUtils.kt │ │ │ ├── model │ │ │ ├── IntervalType.kt │ │ │ ├── LoanRecordType.kt │ │ │ ├── LoanType.kt │ │ │ └── TransactionType.kt │ │ │ ├── resource │ │ │ ├── AndroidResourceProvider.kt │ │ │ ├── ResourceProvider.kt │ │ │ └── TestResourceProvider.kt │ │ │ ├── threading │ │ │ ├── DispatchersProvider.kt │ │ │ └── IvyDispatchersProvider.kt │ │ │ └── time │ │ │ ├── TimeConversionExt.kt │ │ │ ├── TimeConverter.kt │ │ │ ├── TimeProvider.kt │ │ │ ├── TimeRange.kt │ │ │ └── impl │ │ │ ├── DeviceTimeProvider.kt │ │ │ ├── StandardTimeConverter.kt │ │ │ └── TestTimeConverter.kt │ │ └── test │ │ └── java │ │ └── com │ │ └── ivy │ │ └── base │ │ └── time │ │ └── impl │ │ ├── DeviceTimeProviderTest.kt │ │ ├── StandardTimeConverterPropertyTest.kt │ │ └── StandardTimeConverterTest.kt ├── data │ ├── core-testing │ │ └── build.gradle.kts │ ├── core │ │ ├── build.gradle.kts │ │ ├── schemas │ │ │ └── com.ivy.data.db.IvyRoomDatabase │ │ │ │ ├── 101.json │ │ │ │ ├── 102.json │ │ │ │ ├── 103.json │ │ │ │ ├── 104.json │ │ │ │ ├── 105.json │ │ │ │ ├── 106.json │ │ │ │ ├── 107.json │ │ │ │ ├── 108.json │ │ │ │ ├── 109.json │ │ │ │ ├── 110.json │ │ │ │ ├── 111.json │ │ │ │ ├── 112.json │ │ │ │ ├── 113.json │ │ │ │ ├── 114.json │ │ │ │ ├── 115.json │ │ │ │ ├── 116.json │ │ │ │ ├── 117.json │ │ │ │ ├── 118.json │ │ │ │ ├── 119.json │ │ │ │ ├── 120.json │ │ │ │ ├── 121.json │ │ │ │ ├── 122.json │ │ │ │ ├── 123.json │ │ │ │ ├── 124.json │ │ │ │ ├── 125.json │ │ │ │ ├── 126.json │ │ │ │ ├── 127.json │ │ │ │ ├── 128.json │ │ │ │ ├── 129.json │ │ │ │ └── 130.json │ │ └── src │ │ │ ├── androidTest │ │ │ ├── assets │ │ │ │ └── backups │ │ │ │ │ ├── 450-150.json │ │ │ │ │ └── 450-150.zip │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── ivy │ │ │ │ └── data │ │ │ │ ├── backup │ │ │ │ └── BackupDataUseCaseAndroidTest.kt │ │ │ │ └── db │ │ │ │ ├── IvyRoomDatabaseMigrationTest.kt │ │ │ │ └── Migration128to129Test.kt │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── ivy │ │ │ │ └── data │ │ │ │ ├── DataObserver.kt │ │ │ │ ├── backup │ │ │ │ ├── BackupDataUseCase.kt │ │ │ │ ├── CSVRow.kt │ │ │ │ ├── ImportResult.kt │ │ │ │ └── IvyWalletCompleteData.kt │ │ │ │ ├── datasource │ │ │ │ └── LocalLegalDataSource.kt │ │ │ │ ├── datastore │ │ │ │ ├── Datastore.kt │ │ │ │ └── DatastoreKeys.kt │ │ │ │ ├── db │ │ │ │ ├── IvyRoomDatabase.kt │ │ │ │ ├── RoomTypeConverters.kt │ │ │ │ ├── dao │ │ │ │ │ ├── fake │ │ │ │ │ │ ├── FakeAccountDao.kt │ │ │ │ │ │ ├── FakeBudgetDao.kt │ │ │ │ │ │ ├── FakeCategoryDao.kt │ │ │ │ │ │ ├── FakeLoanDao.kt │ │ │ │ │ │ ├── FakeLoanRecordDao.kt │ │ │ │ │ │ ├── FakePlannedPaymentDao.kt │ │ │ │ │ │ ├── FakeSettingsDao.kt │ │ │ │ │ │ ├── FakeTagAssociationDao.kt │ │ │ │ │ │ ├── FakeTagDao.kt │ │ │ │ │ │ └── FakeTransactionDao.kt │ │ │ │ │ ├── read │ │ │ │ │ │ ├── AccountDao.kt │ │ │ │ │ │ ├── BudgetDao.kt │ │ │ │ │ │ ├── CategoryDao.kt │ │ │ │ │ │ ├── ExchangeRatesDao.kt │ │ │ │ │ │ ├── LoanDao.kt │ │ │ │ │ │ ├── LoanRecordDao.kt │ │ │ │ │ │ ├── PlannedPaymentRuleDao.kt │ │ │ │ │ │ ├── SettingsDao.kt │ │ │ │ │ │ ├── TagAssociationDao.kt │ │ │ │ │ │ ├── TagDao.kt │ │ │ │ │ │ ├── TransactionDao.kt │ │ │ │ │ │ └── UserDao.kt │ │ │ │ │ └── write │ │ │ │ │ │ ├── WriteAccountDao.kt │ │ │ │ │ │ ├── WriteBudgetDao.kt │ │ │ │ │ │ ├── WriteCategoryDao.kt │ │ │ │ │ │ ├── WriteExchangeRatesDao.kt │ │ │ │ │ │ ├── WriteLoanDao.kt │ │ │ │ │ │ ├── WriteLoanRecordDao.kt │ │ │ │ │ │ ├── WritePlannedPaymentRuleDao.kt │ │ │ │ │ │ ├── WriteSettingsDao.kt │ │ │ │ │ │ ├── WriteTagAssociationDao.kt │ │ │ │ │ │ ├── WriteTagDao.kt │ │ │ │ │ │ └── WriteTransactionDao.kt │ │ │ │ ├── entity │ │ │ │ │ ├── AccountEntity.kt │ │ │ │ │ ├── BudgetEntity.kt │ │ │ │ │ ├── CategoryEntity.kt │ │ │ │ │ ├── ExchangeRateEntity.kt │ │ │ │ │ ├── LoanEntity.kt │ │ │ │ │ ├── LoanRecordEntity.kt │ │ │ │ │ ├── PlannedPaymentRuleEntity.kt │ │ │ │ │ ├── SettingsEntity.kt │ │ │ │ │ ├── TagAssociationEntity.kt │ │ │ │ │ ├── TagEntity.kt │ │ │ │ │ ├── TransactionEntity.kt │ │ │ │ │ └── UserEntity.kt │ │ │ │ └── migration │ │ │ │ │ ├── Migration105to106_TrnRecurringRules.kt │ │ │ │ │ ├── Migration106to107_Wishlist.kt │ │ │ │ │ ├── Migration107to108_Sync.kt │ │ │ │ │ ├── Migration108to109_Users.kt │ │ │ │ │ ├── Migration109to110_PlannedPayments.kt │ │ │ │ │ ├── Migration110to111_PlannedPaymentRule.kt │ │ │ │ │ ├── Migration111to112_User_testUser.kt │ │ │ │ │ ├── Migration112to113_ExchangeRates.kt │ │ │ │ │ ├── Migration113to114_Multi_Currency.kt │ │ │ │ │ ├── Migration114to115_Category_Account_Icons.kt │ │ │ │ │ ├── Migration115to116_Account_Include_In_Balance.kt │ │ │ │ │ ├── Migration116to117_SalteEdgeIntgration.kt │ │ │ │ │ ├── Migration117to118_Budgets.kt │ │ │ │ │ ├── Migration118to119_Loans.kt │ │ │ │ │ ├── Migration119to120_LoanTransactions.kt │ │ │ │ │ ├── Migration120to121_DropWishlistItem.kt │ │ │ │ │ ├── Migration122to123_ExchangeRates.kt │ │ │ │ │ ├── Migration123to124_LoanIncludeDateTime.kt │ │ │ │ │ ├── Migration124to125_LoanEditDateTime.kt │ │ │ │ │ ├── Migration125to126_Tags.kt │ │ │ │ │ ├── Migration126to127_LoanRecordType.kt │ │ │ │ │ ├── Migration127to128_PaidForDateRecord.kt │ │ │ │ │ ├── Migration128to129_DeleteIsDeleted.kt │ │ │ │ │ └── Migration129to130_LoanIncludeNote.kt │ │ │ │ ├── di │ │ │ │ ├── DatastoreModule.kt │ │ │ │ ├── KtorClientModule.kt │ │ │ │ ├── RemoteDataSourceModule.kt │ │ │ │ └── RoomDbModule.kt │ │ │ │ ├── file │ │ │ │ └── FileSystem.kt │ │ │ │ ├── remote │ │ │ │ ├── RemoteExchangeRatesDataSource.kt │ │ │ │ ├── impl │ │ │ │ │ └── RemoteExchangeRatesDataSourceImpl.kt │ │ │ │ └── responses │ │ │ │ │ └── ExchangeRatesResponse.kt │ │ │ │ ├── repository │ │ │ │ ├── AccountRepository.kt │ │ │ │ ├── CategoryRepository.kt │ │ │ │ ├── CurrencyRepository.kt │ │ │ │ ├── ExchangeRatesRepository.kt │ │ │ │ ├── LegalRepository.kt │ │ │ │ ├── RepositoryMemo.kt │ │ │ │ ├── TagRepository.kt │ │ │ │ ├── TransactionRepository.kt │ │ │ │ ├── fake │ │ │ │ │ └── FakeRepositoryMemo.kt │ │ │ │ └── mapper │ │ │ │ │ ├── AccountMapper.kt │ │ │ │ │ ├── CategoryMapper.kt │ │ │ │ │ ├── ExchangeRateMapper.kt │ │ │ │ │ ├── TagMapper.kt │ │ │ │ │ └── TransactionMapper.kt │ │ │ │ └── temp │ │ │ │ └── migration │ │ │ │ └── TempMigrationUtils.kt │ │ │ └── test │ │ │ ├── java │ │ │ └── com │ │ │ │ └── ivy │ │ │ │ └── data │ │ │ │ ├── ArbAccountEntity.kt │ │ │ │ ├── ArbTransactionEntity.kt │ │ │ │ ├── TestResourceUtil.kt │ │ │ │ ├── backup │ │ │ │ └── BackupDataUseCaseTest.kt │ │ │ │ ├── dao │ │ │ │ ├── FakeAccountDaoTest.kt │ │ │ │ └── FakeCategoryDaoTest.kt │ │ │ │ └── repository │ │ │ │ ├── AccountRepositoryTest.kt │ │ │ │ ├── CategoryRepositoryTest.kt │ │ │ │ ├── ExchangeRatesRepositoryTest.kt │ │ │ │ ├── TransactionRepositoryTest.kt │ │ │ │ └── mapper │ │ │ │ ├── AccountMapperPropertyTest.kt │ │ │ │ ├── AccountMapperTest.kt │ │ │ │ ├── CategoryMapperTest.kt │ │ │ │ ├── ExchangeRateMapperTest.kt │ │ │ │ ├── TransactionMapperPropertyTest.kt │ │ │ │ └── TransactionMapperTest.kt │ │ │ └── resources │ │ │ └── backups │ │ │ └── 450-150.json │ ├── model-testing │ │ ├── build.gradle.kts │ │ └── src │ │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── ivy │ │ │ │ └── data │ │ │ │ └── model │ │ │ │ └── testing │ │ │ │ ├── ArbAccount.kt │ │ │ │ ├── ArbCategory.kt │ │ │ │ ├── ArbTransaction.kt │ │ │ │ ├── ArbUtils.kt │ │ │ │ ├── ArbValue.kt │ │ │ │ ├── DoubleApproxAssertion.kt │ │ │ │ └── ModelFixtures.kt │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── data │ │ │ └── model │ │ │ └── testing │ │ │ ├── ArbCategoryTest.kt │ │ │ ├── ArbTransactionTest.kt │ │ │ ├── ArbUtilTest.kt │ │ │ ├── ArbValueTest.kt │ │ │ └── DoubleApproxAssertionTest.kt │ └── model │ │ ├── build.gradle.kts │ │ └── src │ │ ├── main │ │ └── kotlin │ │ │ └── com │ │ │ └── ivy │ │ │ └── data │ │ │ └── model │ │ │ ├── Account.kt │ │ │ ├── Category.kt │ │ │ ├── ExchangeRate.kt │ │ │ ├── Reorderable.kt │ │ │ ├── Tag.kt │ │ │ ├── Transaction.kt │ │ │ ├── Value.kt │ │ │ ├── exact │ │ │ └── ExactDsl.kt │ │ │ ├── primitive │ │ │ ├── AssetCode.kt │ │ │ ├── AssociationId.kt │ │ │ ├── ColorInt.kt │ │ │ ├── IconAsset.kt │ │ │ ├── NonNegativeDouble.kt │ │ │ ├── NonNegativeInt.kt │ │ │ ├── NonNegativeLong.kt │ │ │ ├── NonZeroDouble.kt │ │ │ ├── NotBlankTrimmedString.kt │ │ │ ├── PositiveDouble.kt │ │ │ └── PositiveInt.kt │ │ │ ├── sync │ │ │ ├── Identifiable.kt │ │ │ └── UniqueId.kt │ │ │ └── util │ │ │ └── ValueRounding.kt │ │ └── test │ │ └── java │ │ └── com │ │ └── ivy │ │ └── data │ │ └── model │ │ ├── primitive │ │ ├── AssetCodeTest.kt │ │ ├── IconIdTest.kt │ │ ├── NonNegativeDoubleTest.kt │ │ ├── NonNegativeIntTest.kt │ │ ├── NonZeroDoubleTest.kt │ │ ├── NotBlankTrimmedStringTest.kt │ │ ├── PositiveDoubleTest.kt │ │ ├── PositiveIntTest.kt │ │ └── TransactionTest.kt │ │ └── util │ │ └── ValueRoundingTest.kt ├── domain │ ├── build.gradle.kts │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── domain │ │ │ └── usecase │ │ │ └── SyncExchangeRatesUseCaseTest.kt │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ivy │ │ │ └── domain │ │ │ ├── AppStarter.kt │ │ │ ├── RootScreen.kt │ │ │ ├── di │ │ │ └── IvyCoreBindingsModule.kt │ │ │ ├── features │ │ │ ├── BoolFeature.kt │ │ │ ├── FeatureGroup.kt │ │ │ ├── Features.kt │ │ │ └── IvyFeatures.kt │ │ │ ├── model │ │ │ ├── StatSummary.kt │ │ │ └── TimeRange.kt │ │ │ └── usecase │ │ │ ├── BalanceBuilder.kt │ │ │ ├── StatSummaryBuilder.kt │ │ │ ├── account │ │ │ ├── AccountBalanceUseCase.kt │ │ │ └── AccountStatsUseCase.kt │ │ │ ├── category │ │ │ └── CategoryStatsUseCase.kt │ │ │ ├── csv │ │ │ ├── ExportCsvUseCase.kt │ │ │ ├── IvyCsvRow.kt │ │ │ └── ReadCsvUseCase.kt │ │ │ ├── exchange │ │ │ ├── ExchangeUseCase.kt │ │ │ └── SyncExchangeRatesUseCase.kt │ │ │ └── wallet │ │ │ ├── WalletBalanceUseCase.kt │ │ │ └── WalletStatsUseCase.kt │ │ └── test │ │ └── java │ │ └── com │ │ └── ivy │ │ └── domain │ │ ├── ArbTransactionsUtil.kt │ │ ├── ValueUtil.kt │ │ ├── model │ │ └── StatSummaryAssertion.kt │ │ └── usecase │ │ ├── balance │ │ └── BalanceBuilderTest.kt │ │ ├── csv │ │ └── ExportCsvUseCasePropertyTest.kt │ │ └── stat │ │ ├── AccountStatsUseCasePropertyTest.kt │ │ └── StatSummaryBuilderTest.kt └── ui │ ├── core │ ├── build.gradle.kts │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── ivy │ │ │ │ ├── design │ │ │ │ └── system │ │ │ │ │ ├── IvyMaterial3Theme.kt │ │ │ │ │ └── colors │ │ │ │ │ ├── ColorShades.kt │ │ │ │ │ └── IvyColors.kt │ │ │ │ └── ui │ │ │ │ ├── ComposeViewModel.kt │ │ │ │ ├── FormatMoneyUseCase.kt │ │ │ │ ├── RememberScrollPosition.kt │ │ │ │ ├── component │ │ │ │ └── OpenSourceCard.kt │ │ │ │ ├── di │ │ │ │ └── IvyUiBindings.kt │ │ │ │ └── time │ │ │ │ ├── DevicePreferences.kt │ │ │ │ ├── TimeFormatter.kt │ │ │ │ └── impl │ │ │ │ ├── AndroidDateTimePicker.kt │ │ │ │ ├── AndroidDevicePreferences.kt │ │ │ │ ├── DateTimePicker.kt │ │ │ │ └── IvyTimeFormatter.kt │ │ └── res │ │ │ ├── drawable-nodpi │ │ │ ├── donate_illustration.png │ │ │ ├── ivywallet_logo.png │ │ │ ├── monefy_logo.png │ │ │ ├── moneymanager_logo.png │ │ │ ├── spendee_logo.png │ │ │ └── wallet_by_budgetbakers_logo.png │ │ │ ├── drawable │ │ │ ├── bluecoins.png │ │ │ ├── didyouknow.xml │ │ │ ├── expense_shape_widget_background.xml │ │ │ ├── financisto_logo.png │ │ │ ├── fortune_city_app_logo.png │ │ │ ├── github_logo.xml │ │ │ ├── home_more_menu_amoled_dark_mode.xml │ │ │ ├── home_more_menu_auto_mode.xml │ │ │ ├── home_more_menu_budgets.xml │ │ │ ├── home_more_menu_categories.xml │ │ │ ├── home_more_menu_dark_mode.xml │ │ │ ├── home_more_menu_light_mode.xml │ │ │ ├── home_more_menu_loans.xml │ │ │ ├── home_more_menu_planned_payments.xml │ │ │ ├── home_more_menu_reports.xml │ │ │ ├── home_more_menu_settings.xml │ │ │ ├── home_more_menu_share.xml │ │ │ ├── ic_account_onboarding.xml │ │ │ ├── ic_accounts.xml │ │ │ ├── ic_accounts_no_padding.xml │ │ │ ├── ic_add.xml │ │ │ ├── ic_add_attachment.xml │ │ │ ├── ic_add_custom_field.xml │ │ │ ├── ic_add_due_date.xml │ │ │ ├── ic_add_recurring.xml │ │ │ ├── ic_add_reminder.xml │ │ │ ├── ic_add_timetracking.xml │ │ │ ├── ic_agreed.xml │ │ │ ├── ic_alarm.xml │ │ │ ├── ic_archive.xml │ │ │ ├── ic_arrow_right.xml │ │ │ ├── ic_attachment.xml │ │ │ ├── ic_back.xml │ │ │ ├── ic_back_android.xml │ │ │ ├── ic_backspace.xml │ │ │ ├── ic_budget_s.xml │ │ │ ├── ic_budget_xl.xml │ │ │ ├── ic_budget_xs.xml │ │ │ ├── ic_buffer_exceeded.xml │ │ │ ├── ic_buffer_ok.xml │ │ │ ├── ic_bulb.xml │ │ │ ├── ic_calendar.xml │ │ │ ├── ic_categories.xml │ │ │ ├── ic_categories_no_padding.xml │ │ │ ├── ic_category_edit.xml │ │ │ ├── ic_check.xml │ │ │ ├── ic_checkbox_checked.xml │ │ │ ├── ic_checkbox_unchecked.xml │ │ │ ├── ic_checklist.xml │ │ │ ├── ic_checklist_add.xml │ │ │ ├── ic_clock.xml │ │ │ ├── ic_currency.xml │ │ │ ├── ic_custom_account_l.xml │ │ │ ├── ic_custom_account_m.xml │ │ │ ├── ic_custom_account_s.xml │ │ │ ├── ic_custom_ada_l.xml │ │ │ ├── ic_custom_ada_m.xml │ │ │ ├── ic_custom_ada_s.xml │ │ │ ├── ic_custom_atom_l.xml │ │ │ ├── ic_custom_atom_m.xml │ │ │ ├── ic_custom_atom_s.xml │ │ │ ├── ic_custom_bank_l.xml │ │ │ ├── ic_custom_bank_m.xml │ │ │ ├── ic_custom_bank_s.xml │ │ │ ├── ic_custom_bills_l.xml │ │ │ ├── ic_custom_bills_m.xml │ │ │ ├── ic_custom_bills_s.xml │ │ │ ├── ic_custom_birthday_l.xml │ │ │ ├── ic_custom_birthday_m.xml │ │ │ ├── ic_custom_birthday_s.xml │ │ │ ├── ic_custom_btc_l.xml │ │ │ ├── ic_custom_btc_m.xml │ │ │ ├── ic_custom_btc_s.xml │ │ │ ├── ic_custom_calculator_l.xml │ │ │ ├── ic_custom_calculator_m.xml │ │ │ ├── ic_custom_calculator_s.xml │ │ │ ├── ic_custom_calendar_l.xml │ │ │ ├── ic_custom_calendar_m.xml │ │ │ ├── ic_custom_calendar_s.xml │ │ │ ├── ic_custom_camera_l.xml │ │ │ ├── ic_custom_camera_m.xml │ │ │ ├── ic_custom_camera_s.xml │ │ │ ├── ic_custom_cash_l.xml │ │ │ ├── ic_custom_cash_m.xml │ │ │ ├── ic_custom_cash_s.xml │ │ │ ├── ic_custom_category_l.xml │ │ │ ├── ic_custom_category_m.xml │ │ │ ├── ic_custom_category_s.xml │ │ │ ├── ic_custom_chemistry_l.xml │ │ │ ├── ic_custom_chemistry_m.xml │ │ │ ├── ic_custom_chemistry_s.xml │ │ │ ├── ic_custom_clothes2_l.xml │ │ │ ├── ic_custom_clothes2_m.xml │ │ │ ├── ic_custom_clothes2_s.xml │ │ │ ├── ic_custom_clothes_l.xml │ │ │ ├── ic_custom_clothes_m.xml │ │ │ ├── ic_custom_clothes_s.xml │ │ │ ├── ic_custom_coffee_l.xml │ │ │ ├── ic_custom_coffee_m.xml │ │ │ ├── ic_custom_coffee_s.xml │ │ │ ├── ic_custom_connect_l.xml │ │ │ ├── ic_custom_connect_m.xml │ │ │ ├── ic_custom_connect_s.xml │ │ │ ├── ic_custom_crown_l.xml │ │ │ ├── ic_custom_crown_m.xml │ │ │ ├── ic_custom_crown_s.xml │ │ │ ├── ic_custom_diamond_l.xml │ │ │ ├── ic_custom_diamond_m.xml │ │ │ ├── ic_custom_diamond_s.xml │ │ │ ├── ic_custom_dna_l.xml │ │ │ ├── ic_custom_dna_m.xml │ │ │ ├── ic_custom_dna_s.xml │ │ │ ├── ic_custom_doctor_l.xml │ │ │ ├── ic_custom_doctor_m.xml │ │ │ ├── ic_custom_doctor_s.xml │ │ │ ├── ic_custom_document_l.xml │ │ │ ├── ic_custom_document_m.xml │ │ │ ├── ic_custom_document_s.xml │ │ │ ├── ic_custom_doge_l.xml │ │ │ ├── ic_custom_doge_m.xml │ │ │ ├── ic_custom_doge_s.xml │ │ │ ├── ic_custom_drink_l.xml │ │ │ ├── ic_custom_drink_m.xml │ │ │ ├── ic_custom_drink_s.xml │ │ │ ├── ic_custom_education_l.xml │ │ │ ├── ic_custom_education_m.xml │ │ │ ├── ic_custom_education_s.xml │ │ │ ├── ic_custom_eth_l.xml │ │ │ ├── ic_custom_eth_m.xml │ │ │ ├── ic_custom_eth_s.xml │ │ │ ├── ic_custom_family_l.xml │ │ │ ├── ic_custom_family_m.xml │ │ │ ├── ic_custom_family_s.xml │ │ │ ├── ic_custom_farmacy_l.xml │ │ │ ├── ic_custom_farmacy_m.xml │ │ │ ├── ic_custom_farmacy_s.xml │ │ │ ├── ic_custom_fingerprint_l.xml │ │ │ ├── ic_custom_fingerprint_m.xml │ │ │ ├── ic_custom_fingerprint_s.xml │ │ │ ├── ic_custom_fishfood_l.xml │ │ │ ├── ic_custom_fishfood_m.xml │ │ │ ├── ic_custom_fishfood_s.xml │ │ │ ├── ic_custom_fitness_l.xml │ │ │ ├── ic_custom_fitness_m.xml │ │ │ ├── ic_custom_fitness_s.xml │ │ │ ├── ic_custom_food2_l.xml │ │ │ ├── ic_custom_food2_m.xml │ │ │ ├── ic_custom_food2_s.xml │ │ │ ├── ic_custom_fooddrink_l.xml │ │ │ ├── ic_custom_fooddrink_m.xml │ │ │ ├── ic_custom_fooddrink_s.xml │ │ │ ├── ic_custom_furniture_l.xml │ │ │ ├── ic_custom_furniture_m.xml │ │ │ ├── ic_custom_furniture_s.xml │ │ │ ├── ic_custom_gambling_l.xml │ │ │ ├── ic_custom_gambling_m.xml │ │ │ ├── ic_custom_gambling_s.xml │ │ │ ├── ic_custom_game_l.xml │ │ │ ├── ic_custom_game_m.xml │ │ │ ├── ic_custom_game_s.xml │ │ │ ├── ic_custom_gears_l.xml │ │ │ ├── ic_custom_gears_m.xml │ │ │ ├── ic_custom_gears_s.xml │ │ │ ├── ic_custom_gift_l.xml │ │ │ ├── ic_custom_gift_m.xml │ │ │ ├── ic_custom_gift_s.xml │ │ │ ├── ic_custom_groceries_l.xml │ │ │ ├── ic_custom_groceries_m.xml │ │ │ ├── ic_custom_groceries_s.xml │ │ │ ├── ic_custom_hairdresser_l.xml │ │ │ ├── ic_custom_hairdresser_m.xml │ │ │ ├── ic_custom_hairdresser_s.xml │ │ │ ├── ic_custom_health_l.xml │ │ │ ├── ic_custom_health_m.xml │ │ │ ├── ic_custom_health_s.xml │ │ │ ├── ic_custom_hike_l.xml │ │ │ ├── ic_custom_hike_m.xml │ │ │ ├── ic_custom_hike_s.xml │ │ │ ├── ic_custom_house_l.xml │ │ │ ├── ic_custom_house_m.xml │ │ │ ├── ic_custom_house_s.xml │ │ │ ├── ic_custom_insurance_l.xml │ │ │ ├── ic_custom_insurance_m.xml │ │ │ ├── ic_custom_insurance_s.xml │ │ │ ├── ic_custom_label_l.xml │ │ │ ├── ic_custom_label_m.xml │ │ │ ├── ic_custom_label_s.xml │ │ │ ├── ic_custom_leaf_l.xml │ │ │ ├── ic_custom_leaf_m.xml │ │ │ ├── ic_custom_leaf_s.xml │ │ │ ├── ic_custom_loan_l.xml │ │ │ ├── ic_custom_loan_m.xml │ │ │ ├── ic_custom_loan_s.xml │ │ │ ├── ic_custom_location_l.xml │ │ │ ├── ic_custom_location_m.xml │ │ │ ├── ic_custom_location_s.xml │ │ │ ├── ic_custom_makeup_l.xml │ │ │ ├── ic_custom_makeup_m.xml │ │ │ ├── ic_custom_makeup_s.xml │ │ │ ├── ic_custom_music_l.xml │ │ │ ├── ic_custom_music_m.xml │ │ │ ├── ic_custom_music_s.xml │ │ │ ├── ic_custom_notice_l.xml │ │ │ ├── ic_custom_notice_m.xml │ │ │ ├── ic_custom_notice_s.xml │ │ │ ├── ic_custom_orderfood2_l.xml │ │ │ ├── ic_custom_orderfood2_m.xml │ │ │ ├── ic_custom_orderfood2_s.xml │ │ │ ├── ic_custom_orderfood_l.xml │ │ │ ├── ic_custom_orderfood_m.xml │ │ │ ├── ic_custom_orderfood_s.xml │ │ │ ├── ic_custom_palette_l.xml │ │ │ ├── ic_custom_palette_m.xml │ │ │ ├── ic_custom_palette_s.xml │ │ │ ├── ic_custom_people_l.xml │ │ │ ├── ic_custom_people_m.xml │ │ │ ├── ic_custom_people_s.xml │ │ │ ├── ic_custom_pet_l.xml │ │ │ ├── ic_custom_pet_m.xml │ │ │ ├── ic_custom_pet_s.xml │ │ │ ├── ic_custom_plant_l.xml │ │ │ ├── ic_custom_plant_m.xml │ │ │ ├── ic_custom_plant_s.xml │ │ │ ├── ic_custom_programming_l.xml │ │ │ ├── ic_custom_programming_m.xml │ │ │ ├── ic_custom_programming_s.xml │ │ │ ├── ic_custom_relationship_l.xml │ │ │ ├── ic_custom_relationship_m.xml │ │ │ ├── ic_custom_relationship_s.xml │ │ │ ├── ic_custom_restaurant_l.xml │ │ │ ├── ic_custom_restaurant_m.xml │ │ │ ├── ic_custom_restaurant_s.xml │ │ │ ├── ic_custom_revolut_l.xml │ │ │ ├── ic_custom_revolut_m.xml │ │ │ ├── ic_custom_revolut_s.xml │ │ │ ├── ic_custom_rocket_l.xml │ │ │ ├── ic_custom_rocket_m.xml │ │ │ ├── ic_custom_rocket_s.xml │ │ │ ├── ic_custom_safe_l.xml │ │ │ ├── ic_custom_safe_m.xml │ │ │ ├── ic_custom_safe_s.xml │ │ │ ├── ic_custom_sail_l.xml │ │ │ ├── ic_custom_sail_m.xml │ │ │ ├── ic_custom_sail_s.xml │ │ │ ├── ic_custom_selfdevelopment_l.xml │ │ │ ├── ic_custom_selfdevelopment_m.xml │ │ │ ├── ic_custom_selfdevelopment_s.xml │ │ │ ├── ic_custom_server_l.xml │ │ │ ├── ic_custom_server_m.xml │ │ │ ├── ic_custom_server_s.xml │ │ │ ├── ic_custom_shopping2_l.xml │ │ │ ├── ic_custom_shopping2_m.xml │ │ │ ├── ic_custom_shopping2_s.xml │ │ │ ├── ic_custom_shopping_l.xml │ │ │ ├── ic_custom_shopping_m.xml │ │ │ ├── ic_custom_shopping_s.xml │ │ │ ├── ic_custom_sports_l.xml │ │ │ ├── ic_custom_sports_m.xml │ │ │ ├── ic_custom_sports_s.xml │ │ │ ├── ic_custom_star_l.xml │ │ │ ├── ic_custom_star_m.xml │ │ │ ├── ic_custom_star_s.xml │ │ │ ├── ic_custom_stats_l.xml │ │ │ ├── ic_custom_stats_m.xml │ │ │ ├── ic_custom_stats_s.xml │ │ │ ├── ic_custom_tools_l.xml │ │ │ ├── ic_custom_tools_m.xml │ │ │ ├── ic_custom_tools_s.xml │ │ │ ├── ic_custom_transfer_m.xml │ │ │ ├── ic_custom_transport_l.xml │ │ │ ├── ic_custom_transport_m.xml │ │ │ ├── ic_custom_transport_s.xml │ │ │ ├── ic_custom_travel_l.xml │ │ │ ├── ic_custom_travel_m.xml │ │ │ ├── ic_custom_travel_s.xml │ │ │ ├── ic_custom_trees_l.xml │ │ │ ├── ic_custom_trees_m.xml │ │ │ ├── ic_custom_trees_s.xml │ │ │ ├── ic_custom_vehicle_l.xml │ │ │ ├── ic_custom_vehicle_m.xml │ │ │ ├── ic_custom_vehicle_s.xml │ │ │ ├── ic_custom_work_l.xml │ │ │ ├── ic_custom_work_m.xml │ │ │ ├── ic_custom_work_s.xml │ │ │ ├── ic_custom_xrp_l.xml │ │ │ ├── ic_custom_xrp_m.xml │ │ │ ├── ic_custom_xrp_s.xml │ │ │ ├── ic_custom_zeus_l.xml │ │ │ ├── ic_custom_zeus_m.xml │ │ │ ├── ic_custom_zeus_s.xml │ │ │ ├── ic_darkmode.xml │ │ │ ├── ic_data_synced.xml │ │ │ ├── ic_date.xml │ │ │ ├── ic_delete.xml │ │ │ ├── ic_description.xml │ │ │ ├── ic_dismiss.xml │ │ │ ├── ic_dismiss_close.xml │ │ │ ├── ic_divider.xml │ │ │ ├── ic_donate_crown.xml │ │ │ ├── ic_donate_minus.xml │ │ │ ├── ic_donate_plus.xml │ │ │ ├── ic_done.xml │ │ │ ├── ic_drag_handle.xml │ │ │ ├── ic_due_date.xml │ │ │ ├── ic_duedate.xml │ │ │ ├── ic_edit.xml │ │ │ ├── ic_email.xml │ │ │ ├── ic_expand_less.xml │ │ │ ├── ic_expand_more.xml │ │ │ ├── ic_expandarrow.xml │ │ │ ├── ic_expense.xml │ │ │ ├── ic_export_csv.xml │ │ │ ├── ic_export_csv_no_padding.xml │ │ │ ├── ic_file.xml │ │ │ ├── ic_filter_l.xml │ │ │ ├── ic_filter_xs.xml │ │ │ ├── ic_fingerprint.xml │ │ │ ├── ic_format_text.xml │ │ │ ├── ic_google.xml │ │ │ ├── ic_hamburger.xml │ │ │ ├── ic_hashtag.xml │ │ │ ├── ic_hidden.xml │ │ │ ├── ic_hide_m.xml │ │ │ ├── ic_home.xml │ │ │ ├── ic_import_video.xml │ │ │ ├── ic_import_web.xml │ │ │ ├── ic_income.xml │ │ │ ├── ic_income_white.xml │ │ │ ├── ic_ivy_logo.xml │ │ │ ├── ic_label_hashtag.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── ic_launcher_foreground.xml │ │ │ ├── ic_launcher_monochrome.xml │ │ │ ├── ic_lightmode.xml │ │ │ ├── ic_local_account.xml │ │ │ ├── ic_login.xml │ │ │ ├── ic_logo.xml │ │ │ ├── ic_logout.xml │ │ │ ├── ic_modal_attachment_file.xml │ │ │ ├── ic_modal_attachment_link.xml │ │ │ ├── ic_modal_reminder.xml │ │ │ ├── ic_monefy.xml │ │ │ ├── ic_money_lover.xml │ │ │ ├── ic_notes.xml │ │ │ ├── ic_notification.xml │ │ │ ├── ic_notification_m.xml │ │ │ ├── ic_notransactions.xml │ │ │ ├── ic_onboarding_next_arrow.xml │ │ │ ├── ic_options.xml │ │ │ ├── ic_outline_clear_24.xml │ │ │ ├── ic_overdue.xml │ │ │ ├── ic_planned_payments.xml │ │ │ ├── ic_plus.xml │ │ │ ├── ic_popup_add.xml │ │ │ ├── ic_popup_close.xml │ │ │ ├── ic_popup_collapse.xml │ │ │ ├── ic_popup_expand.xml │ │ │ ├── ic_premium_big.xml │ │ │ ├── ic_premium_small.xml │ │ │ ├── ic_priority_dropdown.xml │ │ │ ├── ic_profile.xml │ │ │ ├── ic_recurring.xml │ │ │ ├── ic_recurring_next.xml │ │ │ ├── ic_recurring_upcoming.xml │ │ │ ├── ic_refresh.xml │ │ │ ├── ic_remove.xml │ │ │ ├── ic_remove_checklist_item.xml │ │ │ ├── ic_reorder.xml │ │ │ ├── ic_reset_password.xml │ │ │ ├── ic_save.xml │ │ │ ├── ic_search.xml │ │ │ ├── ic_secure.xml │ │ │ ├── ic_settings.xml │ │ │ ├── ic_share.xml │ │ │ ├── ic_side_menu_collapsed.xml │ │ │ ├── ic_side_menu_expanded.xml │ │ │ ├── ic_sort_by_alpha_24.xml │ │ │ ├── ic_speendee.xml │ │ │ ├── ic_statistics_s.xml │ │ │ ├── ic_statistics_xs.xml │ │ │ ├── ic_support.xml │ │ │ ├── ic_swipe_horizontal.xml │ │ │ ├── ic_swipe_up.xml │ │ │ ├── ic_swipe_up_dark.xml │ │ │ ├── ic_sync.xml │ │ │ ├── ic_tasks.xml │ │ │ ├── ic_telegram_24dp.xml │ │ │ ├── ic_template.xml │ │ │ ├── ic_time.xml │ │ │ ├── ic_time_tracking_log_entry.xml │ │ │ ├── ic_time_tracking_pause.xml │ │ │ ├── ic_time_tracking_play.xml │ │ │ ├── ic_timetracking.xml │ │ │ ├── ic_toshl_finance.xml │ │ │ ├── ic_transfer.xml │ │ │ ├── ic_upload.xml │ │ │ ├── ic_visible.xml │ │ │ ├── ic_vue_brands_android.xml │ │ │ ├── ic_vue_brands_apple.xml │ │ │ ├── ic_vue_brands_be.xml │ │ │ ├── ic_vue_brands_blogger.xml │ │ │ ├── ic_vue_brands_bootsrap.xml │ │ │ ├── ic_vue_brands_dribbble.xml │ │ │ ├── ic_vue_brands_drive.xml │ │ │ ├── ic_vue_brands_dropbox.xml │ │ │ ├── ic_vue_brands_facebook.xml │ │ │ ├── ic_vue_brands_figma.xml │ │ │ ├── ic_vue_brands_framer.xml │ │ │ ├── ic_vue_brands_google.xml │ │ │ ├── ic_vue_brands_google_play.xml │ │ │ ├── ic_vue_brands_html3.xml │ │ │ ├── ic_vue_brands_html5.xml │ │ │ ├── ic_vue_brands_illustrator.xml │ │ │ ├── ic_vue_brands_js.xml │ │ │ ├── ic_vue_brands_messenger.xml │ │ │ ├── ic_vue_brands_ok.xml │ │ │ ├── ic_vue_brands_paypal.xml │ │ │ ├── ic_vue_brands_photoshop.xml │ │ │ ├── ic_vue_brands_python.xml │ │ │ ├── ic_vue_brands_slack.xml │ │ │ ├── ic_vue_brands_snapchat.xml │ │ │ ├── ic_vue_brands_spotify.xml │ │ │ ├── ic_vue_brands_trello.xml │ │ │ ├── ic_vue_brands_triangle.xml │ │ │ ├── ic_vue_brands_twitch.xml │ │ │ ├── ic_vue_brands_ui8.xml │ │ │ ├── ic_vue_brands_vuesax.xml │ │ │ ├── ic_vue_brands_whatsapp.xml │ │ │ ├── ic_vue_brands_windows.xml │ │ │ ├── ic_vue_brands_xd.xml │ │ │ ├── ic_vue_brands_xiaomi.xml │ │ │ ├── ic_vue_brands_youtube.xml │ │ │ ├── ic_vue_brands_zoom.xml │ │ │ ├── ic_vue_building_bank.xml │ │ │ ├── ic_vue_building_building.xml │ │ │ ├── ic_vue_building_building1.xml │ │ │ ├── ic_vue_building_buildings.xml │ │ │ ├── ic_vue_building_courthouse.xml │ │ │ ├── ic_vue_building_hospital.xml │ │ │ ├── ic_vue_building_house.xml │ │ │ ├── ic_vue_chart_chart.xml │ │ │ ├── ic_vue_chart_diagram.xml │ │ │ ├── ic_vue_chart_graph.xml │ │ │ ├── ic_vue_chart_status_up.xml │ │ │ ├── ic_vue_chart_trend_up.xml │ │ │ ├── ic_vue_crypto_aave.xml │ │ │ ├── ic_vue_crypto_ankr.xml │ │ │ ├── ic_vue_crypto_augur.xml │ │ │ ├── ic_vue_crypto_autonio.xml │ │ │ ├── ic_vue_crypto_avalanche.xml │ │ │ ├── ic_vue_crypto_binance_coin.xml │ │ │ ├── ic_vue_crypto_binance_usd.xml │ │ │ ├── ic_vue_crypto_bitcoin.xml │ │ │ ├── ic_vue_crypto_cardano.xml │ │ │ ├── ic_vue_crypto_celo.xml │ │ │ ├── ic_vue_crypto_celsius_.xml │ │ │ ├── ic_vue_crypto_chainlink.xml │ │ │ ├── ic_vue_crypto_civic.xml │ │ │ ├── ic_vue_crypto_dai.xml │ │ │ ├── ic_vue_crypto_dash.xml │ │ │ ├── ic_vue_crypto_decred.xml │ │ │ ├── ic_vue_crypto_dent.xml │ │ │ ├── ic_vue_crypto_educare.xml │ │ │ ├── ic_vue_crypto_emercoin.xml │ │ │ ├── ic_vue_crypto_enjin_coin.xml │ │ │ ├── ic_vue_crypto_eos.xml │ │ │ ├── ic_vue_crypto_ethereum.xml │ │ │ ├── ic_vue_crypto_ethereum_classic.xml │ │ │ ├── ic_vue_crypto_ftx_token.xml │ │ │ ├── ic_vue_crypto_graph.xml │ │ │ ├── ic_vue_crypto_harmony.xml │ │ │ ├── ic_vue_crypto_hedera_hashgraph.xml │ │ │ ├── ic_vue_crypto_hex.xml │ │ │ ├── ic_vue_crypto_huobi_token.xml │ │ │ ├── ic_vue_crypto_icon.xml │ │ │ ├── ic_vue_crypto_iost.xml │ │ │ ├── ic_vue_crypto_kyber_network.xml │ │ │ ├── ic_vue_crypto_litecoin.xml │ │ │ ├── ic_vue_crypto_maker.xml │ │ │ ├── ic_vue_crypto_monero.xml │ │ │ ├── ic_vue_crypto_nebulas.xml │ │ │ ├── ic_vue_crypto_nem.xml │ │ │ ├── ic_vue_crypto_nexo.xml │ │ │ ├── ic_vue_crypto_ocean_protocol.xml │ │ │ ├── ic_vue_crypto_okb.xml │ │ │ ├── ic_vue_crypto_ontology.xml │ │ │ ├── ic_vue_crypto_polkadot.xml │ │ │ ├── ic_vue_crypto_polygon.xml │ │ │ ├── ic_vue_crypto_polyswarm.xml │ │ │ ├── ic_vue_crypto_quant.xml │ │ │ ├── ic_vue_crypto_siacoin.xml │ │ │ ├── ic_vue_crypto_solana.xml │ │ │ ├── ic_vue_crypto_stacks.xml │ │ │ ├── ic_vue_crypto_stellar.xml │ │ │ ├── ic_vue_crypto_tenx.xml │ │ │ ├── ic_vue_crypto_tether.xml │ │ │ ├── ic_vue_crypto_theta.xml │ │ │ ├── ic_vue_crypto_thorchain.xml │ │ │ ├── ic_vue_crypto_trontron.xml │ │ │ ├── ic_vue_crypto_usd_coin.xml │ │ │ ├── ic_vue_crypto_velas.xml │ │ │ ├── ic_vue_crypto_vibe.xml │ │ │ ├── ic_vue_crypto_wanchain.xml │ │ │ ├── ic_vue_crypto_wing.xml │ │ │ ├── ic_vue_crypto_xrp.xml │ │ │ ├── ic_vue_crypto_zel.xml │ │ │ ├── ic_vue_delivery_box.xml │ │ │ ├── ic_vue_delivery_box1.xml │ │ │ ├── ic_vue_delivery_package.xml │ │ │ ├── ic_vue_delivery_receive.xml │ │ │ ├── ic_vue_delivery_truck.xml │ │ │ ├── ic_vue_design_bezier.xml │ │ │ ├── ic_vue_design_brush.xml │ │ │ ├── ic_vue_design_color_swatch.xml │ │ │ ├── ic_vue_design_magicpen.xml │ │ │ ├── ic_vue_design_roller.xml │ │ │ ├── ic_vue_design_scissors.xml │ │ │ ├── ic_vue_design_tool_pen.xml │ │ │ ├── ic_vue_dev_arrow.xml │ │ │ ├── ic_vue_dev_code.xml │ │ │ ├── ic_vue_dev_data.xml │ │ │ ├── ic_vue_dev_hashtag.xml │ │ │ ├── ic_vue_dev_hierarchy.xml │ │ │ ├── ic_vue_dev_relation.xml │ │ │ ├── ic_vue_edu_award.xml │ │ │ ├── ic_vue_edu_book.xml │ │ │ ├── ic_vue_edu_bookmark.xml │ │ │ ├── ic_vue_edu_briefcase.xml │ │ │ ├── ic_vue_edu_calculator.xml │ │ │ ├── ic_vue_edu_glass.xml │ │ │ ├── ic_vue_edu_graduate_cap.xml │ │ │ ├── ic_vue_edu_magazine.xml │ │ │ ├── ic_vue_edu_note.xml │ │ │ ├── ic_vue_edu_omega.xml │ │ │ ├── ic_vue_edu_pen.xml │ │ │ ├── ic_vue_edu_planer.xml │ │ │ ├── ic_vue_edu_ruler_pen.xml │ │ │ ├── ic_vue_edu_telescope.xml │ │ │ ├── ic_vue_edu_todo.xml │ │ │ ├── ic_vue_files_folder.xml │ │ │ ├── ic_vue_files_folder_cloud.xml │ │ │ ├── ic_vue_files_folder_favorite.xml │ │ │ ├── ic_vue_location_discover.xml │ │ │ ├── ic_vue_location_global.xml │ │ │ ├── ic_vue_location_global_edit.xml │ │ │ ├── ic_vue_location_global_search.xml │ │ │ ├── ic_vue_location_location.xml │ │ │ ├── ic_vue_location_map.xml │ │ │ ├── ic_vue_location_map1.xml │ │ │ ├── ic_vue_location_radar.xml │ │ │ ├── ic_vue_location_routing.xml │ │ │ ├── ic_vue_main_archive.xml │ │ │ ├── ic_vue_main_battery_charging.xml │ │ │ ├── ic_vue_main_battery_half.xml │ │ │ ├── ic_vue_main_broom.xml │ │ │ ├── ic_vue_main_cake.xml │ │ │ ├── ic_vue_main_calendar.xml │ │ │ ├── ic_vue_main_clock.xml │ │ │ ├── ic_vue_main_coffee.xml │ │ │ ├── ic_vue_main_crown.xml │ │ │ ├── ic_vue_main_cup.xml │ │ │ ├── ic_vue_main_emoji_happy.xml │ │ │ ├── ic_vue_main_emoji_normal.xml │ │ │ ├── ic_vue_main_emoji_sad.xml │ │ │ ├── ic_vue_main_flash.xml │ │ │ ├── ic_vue_main_gift.xml │ │ │ ├── ic_vue_main_glass.xml │ │ │ ├── ic_vue_main_home.xml │ │ │ ├── ic_vue_main_home_safe.xml │ │ │ ├── ic_vue_main_home_wifi.xml │ │ │ ├── ic_vue_main_judge.xml │ │ │ ├── ic_vue_main_lamp.xml │ │ │ ├── ic_vue_main_lamp_charge.xml │ │ │ ├── ic_vue_main_lifebuoy.xml │ │ │ ├── ic_vue_main_milk.xml │ │ │ ├── ic_vue_main_notification.xml │ │ │ ├── ic_vue_main_pet.xml │ │ │ ├── ic_vue_main_reserve.xml │ │ │ ├── ic_vue_main_send.xml │ │ │ ├── ic_vue_main_share.xml │ │ │ ├── ic_vue_main_signpost.xml │ │ │ ├── ic_vue_main_sport.xml │ │ │ ├── ic_vue_main_timer.xml │ │ │ ├── ic_vue_main_trash.xml │ │ │ ├── ic_vue_main_tree.xml │ │ │ ├── ic_vue_media_camera.xml │ │ │ ├── ic_vue_media_film.xml │ │ │ ├── ic_vue_media_film_play.xml │ │ │ ├── ic_vue_media_image.xml │ │ │ ├── ic_vue_media_microphone.xml │ │ │ ├── ic_vue_media_mountains.xml │ │ │ ├── ic_vue_media_music.xml │ │ │ ├── ic_vue_media_photocamera.xml │ │ │ ├── ic_vue_media_play.xml │ │ │ ├── ic_vue_media_scissors.xml │ │ │ ├── ic_vue_media_screenmirroring.xml │ │ │ ├── ic_vue_media_setting.xml │ │ │ ├── ic_vue_media_speaker.xml │ │ │ ├── ic_vue_media_subtitle.xml │ │ │ ├── ic_vue_media_voice.xml │ │ │ ├── ic_vue_messages_device_msg.xml │ │ │ ├── ic_vue_messages_direct.xml │ │ │ ├── ic_vue_messages_edit.xml │ │ │ ├── ic_vue_messages_letter.xml │ │ │ ├── ic_vue_messages_msg.xml │ │ │ ├── ic_vue_messages_msg_favorite.xml │ │ │ ├── ic_vue_messages_msg_notification.xml │ │ │ ├── ic_vue_messages_msg_search.xml │ │ │ ├── ic_vue_messages_msg_text.xml │ │ │ ├── ic_vue_messages_msgs.xml │ │ │ ├── ic_vue_money_archive.xml │ │ │ ├── ic_vue_money_bitcoin_refresh.xml │ │ │ ├── ic_vue_money_buy_bitcoin.xml │ │ │ ├── ic_vue_money_buy_crypto.xml │ │ │ ├── ic_vue_money_card.xml │ │ │ ├── ic_vue_money_card_bitcoin.xml │ │ │ ├── ic_vue_money_card_coin.xml │ │ │ ├── ic_vue_money_card_receive.xml │ │ │ ├── ic_vue_money_card_send.xml │ │ │ ├── ic_vue_money_coins.xml │ │ │ ├── ic_vue_money_discount.xml │ │ │ ├── ic_vue_money_dollar.xml │ │ │ ├── ic_vue_money_math.xml │ │ │ ├── ic_vue_money_percentage.xml │ │ │ ├── ic_vue_money_receipt_discount.xml │ │ │ ├── ic_vue_money_receipt_empty.xml │ │ │ ├── ic_vue_money_receipt_items.xml │ │ │ ├── ic_vue_money_recive.xml │ │ │ ├── ic_vue_money_security_card.xml │ │ │ ├── ic_vue_money_send.xml │ │ │ ├── ic_vue_money_tag.xml │ │ │ ├── ic_vue_money_ticket.xml │ │ │ ├── ic_vue_money_ticket_discount.xml │ │ │ ├── ic_vue_money_ticket_star.xml │ │ │ ├── ic_vue_money_transfer.xml │ │ │ ├── ic_vue_money_wallet.xml │ │ │ ├── ic_vue_money_wallet_cards.xml │ │ │ ├── ic_vue_money_wallet_empty.xml │ │ │ ├── ic_vue_money_wallet_money.xml │ │ │ ├── ic_vue_pc_bluetooth.xml │ │ │ ├── ic_vue_pc_charging.xml │ │ │ ├── ic_vue_pc_cpu.xml │ │ │ ├── ic_vue_pc_game.xml │ │ │ ├── ic_vue_pc_gameboy.xml │ │ │ ├── ic_vue_pc_headphone.xml │ │ │ ├── ic_vue_pc_monitor.xml │ │ │ ├── ic_vue_pc_phone.xml │ │ │ ├── ic_vue_pc_phone_call.xml │ │ │ ├── ic_vue_pc_printer.xml │ │ │ ├── ic_vue_pc_setting.xml │ │ │ ├── ic_vue_pc_speaker.xml │ │ │ ├── ic_vue_pc_watch.xml │ │ │ ├── ic_vue_pc_wifi.xml │ │ │ ├── ic_vue_people_2persons.xml │ │ │ ├── ic_vue_people_people.xml │ │ │ ├── ic_vue_people_person.xml │ │ │ ├── ic_vue_people_person_search.xml │ │ │ ├── ic_vue_people_person_tag.xml │ │ │ ├── ic_vue_security_alarm.xml │ │ │ ├── ic_vue_security_eye.xml │ │ │ ├── ic_vue_security_key.xml │ │ │ ├── ic_vue_security_lock.xml │ │ │ ├── ic_vue_security_password.xml │ │ │ ├── ic_vue_security_radar.xml │ │ │ ├── ic_vue_security_shield.xml │ │ │ ├── ic_vue_security_shield_person.xml │ │ │ ├── ic_vue_security_shield_security.xml │ │ │ ├── ic_vue_shop_bag.xml │ │ │ ├── ic_vue_shop_bag1.xml │ │ │ ├── ic_vue_shop_barcode.xml │ │ │ ├── ic_vue_shop_cart.xml │ │ │ ├── ic_vue_shop_shop.xml │ │ │ ├── ic_vue_support_dislike.xml │ │ │ ├── ic_vue_support_heart.xml │ │ │ ├── ic_vue_support_like.xml │ │ │ ├── ic_vue_support_like_dislike.xml │ │ │ ├── ic_vue_support_medal.xml │ │ │ ├── ic_vue_support_smileys.xml │ │ │ ├── ic_vue_support_star.xml │ │ │ ├── ic_vue_transport_airplane.xml │ │ │ ├── ic_vue_transport_bus.xml │ │ │ ├── ic_vue_transport_car.xml │ │ │ ├── ic_vue_transport_car_wash.xml │ │ │ ├── ic_vue_transport_gas.xml │ │ │ ├── ic_vue_transport_ship.xml │ │ │ ├── ic_vue_transport_train.xml │ │ │ ├── ic_vue_type_link.xml │ │ │ ├── ic_vue_type_link2.xml │ │ │ ├── ic_vue_type_paperclip.xml │ │ │ ├── ic_vue_type_text.xml │ │ │ ├── ic_vue_type_textalign_center.xml │ │ │ ├── ic_vue_type_textalign_justifycenter.xml │ │ │ ├── ic_vue_type_textalign_left.xml │ │ │ ├── ic_vue_type_textalign_right.xml │ │ │ ├── ic_vue_type_translate.xml │ │ │ ├── ic_vue_weather_cloud.xml │ │ │ ├── ic_vue_weather_cold.xml │ │ │ ├── ic_vue_weather_drop.xml │ │ │ ├── ic_vue_weather_flash.xml │ │ │ ├── ic_vue_weather_moon.xml │ │ │ ├── ic_vue_weather_sun.xml │ │ │ ├── ic_vue_weather_wind.xml │ │ │ ├── ic_wallet.xml │ │ │ ├── ic_widget_expense.xml │ │ │ ├── ic_widget_income.xml │ │ │ ├── ic_widget_transfer.xml │ │ │ ├── ic_wishlist.xml │ │ │ ├── income_shape_widget_background.xml │ │ │ ├── ivy_wallet_logo.xml │ │ │ ├── ktw_money_manager_logo.png │ │ │ ├── no_account_illustration.xml │ │ │ ├── no_account_illustration_dark.xml │ │ │ ├── onboarding_illustration_accounts.png │ │ │ ├── onboarding_illustration_categories.png │ │ │ ├── onboarding_illustration_import.png │ │ │ ├── one_money_logo.png │ │ │ ├── preview_widget_add_trn.png │ │ │ ├── preview_widget_add_trn_compact.png │ │ │ ├── preview_widget_wallet_balance.png │ │ │ ├── questions.png │ │ │ └── shape_widget_background.xml │ │ │ ├── font │ │ │ ├── opensans_bold.ttf │ │ │ ├── opensans_bolditalic.ttf │ │ │ ├── opensans_extrabold.ttf │ │ │ ├── opensans_extrabolditalic.ttf │ │ │ ├── opensans_italic.ttf │ │ │ ├── opensans_light.ttf │ │ │ ├── opensans_lightitalic.ttf │ │ │ ├── opensans_regular.ttf │ │ │ ├── opensans_semibold.ttf │ │ │ ├── opensans_semibolditalic.ttf │ │ │ ├── raleway_black.ttf │ │ │ ├── raleway_blackitalic.ttf │ │ │ ├── raleway_bold.ttf │ │ │ ├── raleway_bolditalic.ttf │ │ │ ├── raleway_extrabold.ttf │ │ │ ├── raleway_extrabolditalic.ttf │ │ │ ├── raleway_extralight.ttf │ │ │ ├── raleway_extralightitalic.ttf │ │ │ ├── raleway_italic.ttf │ │ │ ├── raleway_light.ttf │ │ │ ├── raleway_lightitalic.ttf │ │ │ ├── raleway_medium.ttf │ │ │ ├── raleway_mediumitalic.ttf │ │ │ ├── raleway_regular.ttf │ │ │ ├── raleway_semibold.ttf │ │ │ ├── raleway_semibolditalic.ttf │ │ │ ├── raleway_thin.ttf │ │ │ └── raleway_thinitalic.ttf │ │ │ ├── values-ar │ │ │ └── strings.xml │ │ │ ├── values-bg │ │ │ └── strings.xml │ │ │ ├── values-de │ │ │ └── strings.xml │ │ │ ├── values-es │ │ │ └── strings.xml │ │ │ ├── values-gl │ │ │ └── strings.xml │ │ │ ├── values-hi │ │ │ └── strings.xml │ │ │ ├── values-id │ │ │ └── strings.xml │ │ │ ├── values-in │ │ │ └── strings.xml │ │ │ ├── values-it │ │ │ └── strings.xml │ │ │ ├── values-kn │ │ │ └── strings.xml │ │ │ ├── values-mn │ │ │ └── strings.xml │ │ │ ├── values-pl │ │ │ └── strings.xml │ │ │ ├── values-pt-rBR │ │ │ └── strings.xml │ │ │ ├── values-ru │ │ │ └── strings.xml │ │ │ ├── values-vi │ │ │ └── strings.xml │ │ │ ├── values-zh-rCN │ │ │ └── strings.xml │ │ │ ├── values-zh-rTW │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ └── strings.xml │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── ivy │ │ │ └── ui │ │ │ ├── FormatMoneyUseCaseTest.kt │ │ │ ├── PaparazziScreenshotTest.kt │ │ │ ├── component │ │ │ └── OpenSourceCardPaparazziTest.kt │ │ │ └── time │ │ │ └── impl │ │ │ └── IvyTimeFormatterTest.kt │ │ └── snapshots │ │ └── images │ │ ├── com.ivy.ui.component_OpenSourceCardPaparazziTest_default state[Dark].png │ │ └── com.ivy.ui.component_OpenSourceCardPaparazziTest_default state[Light].png │ ├── navigation │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── navigation │ │ ├── IvyPreview.kt │ │ ├── Navigation.kt │ │ ├── NavigationRoot.kt │ │ ├── Screen.kt │ │ └── Screens.kt │ └── testing │ ├── build.gradle.kts │ └── src │ ├── main │ └── java │ │ └── com │ │ └── ivy │ │ └── ui │ │ └── testing │ │ ├── ComposeViewModelTest.kt │ │ └── PaparazziScreenshotTest.kt │ └── test │ ├── java │ └── com │ │ └── ivy │ │ └── ui │ │ └── testing │ │ ├── ComposeViewModelTestExtTest.kt │ │ ├── DemoPaparazziTest.kt │ │ └── FakeViewModel.kt │ └── snapshots │ └── images │ ├── com.ivy.ui.testing_DemoPaparazziTest_snapshot demo composable[Dark].png │ └── com.ivy.ui.testing_DemoPaparazziTest_snapshot demo composable[Light].png ├── temp ├── legacy-code │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ivy │ │ └── legacy │ │ ├── Constants.kt │ │ ├── IntervalTypeExt.kt │ │ ├── IvyComposeApp.kt │ │ ├── IvyWalletCtx.kt │ │ ├── LoanExt.kt │ │ ├── LogoutLogic.kt │ │ ├── android │ │ └── notification │ │ │ ├── IvyNotification.kt │ │ │ ├── IvyNotificationChannel.kt │ │ │ └── NotificationService.kt │ │ ├── data │ │ ├── AppBaseData.kt │ │ ├── BufferInfo.kt │ │ ├── DueSection.kt │ │ ├── EditTransactionDisplayLoan.kt │ │ ├── datastore │ │ │ └── IvyDataStore.kt │ │ └── model │ │ │ ├── AccountBalance.kt │ │ │ ├── AccountData.kt │ │ │ ├── FromToTimeRange.kt │ │ │ ├── LastNTimeRange.kt │ │ │ ├── MainTab.kt │ │ │ ├── Month.kt │ │ │ └── TimePeriod.kt │ │ ├── datamodel │ │ ├── Account.kt │ │ ├── Budget.kt │ │ ├── Category.kt │ │ ├── ExchangeRate.kt │ │ ├── Loan.kt │ │ ├── LoanRecord.kt │ │ ├── PlannedPaymentRule.kt │ │ ├── Settings.kt │ │ ├── TransactionExt.kt │ │ └── temp │ │ │ ├── AccountExt.kt │ │ │ ├── BudgetExt.kt │ │ │ ├── CategoryExt.kt │ │ │ ├── ExchangeRateExt.kt │ │ │ ├── LoanExt.kt │ │ │ ├── LoanRecordExt.kt │ │ │ ├── PlannedPaymentRuleExt.kt │ │ │ ├── SettingsExt.kt │ │ │ └── TransactionExt.kt │ │ ├── domain │ │ ├── action │ │ │ ├── account │ │ │ │ ├── AccTrnsAct.kt │ │ │ │ ├── AccountByIdAct.kt │ │ │ │ ├── AccountsAct.kt │ │ │ │ ├── CalcAccBalanceAct.kt │ │ │ │ └── CalcAccIncomeExpenseAct.kt │ │ │ ├── budget │ │ │ │ └── BudgetsAct.kt │ │ │ ├── category │ │ │ │ ├── CategoryIncomeWithAccountFiltersAct.kt │ │ │ │ └── CategoryTrnsBetweenAct.kt │ │ │ ├── exchange │ │ │ │ └── ExchangeAct.kt │ │ │ ├── global │ │ │ │ ├── StartDayOfMonthAct.kt │ │ │ │ └── UpdateStartDayOfMonthAct.kt │ │ │ ├── loan │ │ │ │ ├── LoanByIdAct.kt │ │ │ │ └── LoansAct.kt │ │ │ ├── settings │ │ │ │ ├── BaseCurrencyAct.kt │ │ │ │ ├── CalcBufferDiffAct.kt │ │ │ │ ├── SettingsAct.kt │ │ │ │ └── UpdateSettingsAct.kt │ │ │ ├── transaction │ │ │ │ ├── AllTrnsAct.kt │ │ │ │ ├── CalcTrnsIncomeExpenseAct.kt │ │ │ │ ├── DueTrnsAct.kt │ │ │ │ ├── HistoryTrnsAct.kt │ │ │ │ ├── HistoryWithDateDivsAct.kt │ │ │ │ ├── TrnByIdAct.kt │ │ │ │ ├── TrnsWithDateDivsAct.kt │ │ │ │ └── TrnsWithRangeAndAccFiltersAct.kt │ │ │ ├── viewmodel │ │ │ │ ├── account │ │ │ │ │ └── AccountDataAct.kt │ │ │ │ ├── home │ │ │ │ │ ├── DueTrnsInfoAct.kt │ │ │ │ │ ├── HasTrnsAct.kt │ │ │ │ │ ├── OverdueAct.kt │ │ │ │ │ ├── ShouldHideBalanceAct.kt │ │ │ │ │ ├── ShouldHideIncomeAct.kt │ │ │ │ │ ├── UpcomingAct.kt │ │ │ │ │ ├── UpdateAccCacheAct.kt │ │ │ │ │ └── UpdateCategoriesCacheAct.kt │ │ │ │ └── transaction │ │ │ │ │ └── SaveTrnLocallyAct.kt │ │ │ └── wallet │ │ │ │ ├── CalcIncomeExpenseAct.kt │ │ │ │ └── CalcWalletBalanceAct.kt │ │ ├── data │ │ │ ├── CustomExchangeRateState.kt │ │ │ ├── IvyCurrency.kt │ │ │ ├── Reorderable.kt │ │ │ ├── SortOrder.kt │ │ │ └── TransactionHistoryDateDivider.kt │ │ ├── deprecated │ │ │ └── logic │ │ │ │ ├── AccountCreator.kt │ │ │ │ ├── BudgetCreator.kt │ │ │ │ ├── CategoryCreator.kt │ │ │ │ ├── LoanCreator.kt │ │ │ │ ├── LoanRecordCreator.kt │ │ │ │ ├── PlannedPaymentsGenerator.kt │ │ │ │ ├── PlannedPaymentsLogic.kt │ │ │ │ ├── PreloadDataLogic.kt │ │ │ │ ├── SmartTitleSuggestionsLogic.kt │ │ │ │ ├── WalletAccountLogic.kt │ │ │ │ ├── WalletCategoryLogic.kt │ │ │ │ ├── csv │ │ │ │ ├── CSVImporter.kt │ │ │ │ ├── CSVMapper.kt │ │ │ │ ├── CSVNormalizer.kt │ │ │ │ └── model │ │ │ │ │ ├── ImportType.kt │ │ │ │ │ └── RowMapping.kt │ │ │ │ ├── currency │ │ │ │ └── ExchangeRatesLogic.kt │ │ │ │ ├── loantrasactions │ │ │ │ ├── LTLoanMapper.kt │ │ │ │ ├── LTLoanRecordMapper.kt │ │ │ │ ├── LoanTransactionsCore.kt │ │ │ │ └── LoanTransactionsLogic.kt │ │ │ │ └── model │ │ │ │ ├── CreateAccountData.kt │ │ │ │ ├── CreateBudgetData.kt │ │ │ │ ├── CreateCategoryData.kt │ │ │ │ ├── CreateLoanData.kt │ │ │ │ ├── CreateLoanRecordData.kt │ │ │ │ └── EditLoanRecordData.kt │ │ └── pure │ │ │ ├── account │ │ │ └── AccountFunctions.kt │ │ │ ├── data │ │ │ ├── ClosedTimeRange.kt │ │ │ ├── IncomeExpensePair.kt │ │ │ ├── IncomeExpenseTransferPair.kt │ │ │ └── WalletDAOs.kt │ │ │ ├── exchange │ │ │ ├── Exchange.kt │ │ │ └── ExchangeTrns.kt │ │ │ ├── transaction │ │ │ ├── AccountValueFunctions.kt │ │ │ ├── CatValueFunctions.kt │ │ │ ├── FoldTransactions.kt │ │ │ ├── TrnDateDividers.kt │ │ │ ├── TrnFunctions.kt │ │ │ └── WalletValueFunctions.kt │ │ │ └── util │ │ │ ├── IvyDomainUtils.kt │ │ │ └── Utils.kt │ │ ├── frp │ │ ├── Annotations.kt │ │ ├── Composition.kt │ │ ├── Composition2.kt │ │ ├── CompositionN.kt │ │ ├── OnScreenStart.kt │ │ ├── Utils.kt │ │ ├── action │ │ │ ├── Action.kt │ │ │ ├── CompositionFilter.kt │ │ │ ├── CompositionMap.kt │ │ │ ├── CompositionSum.kt │ │ │ └── FPAction.kt │ │ ├── monad │ │ │ ├── Res.kt │ │ │ └── ResComposition.kt │ │ ├── test │ │ │ ├── TestIdlingResource.kt │ │ │ └── TestingContext.kt │ │ ├── view │ │ │ └── FRPComposable.kt │ │ └── viewmodel │ │ │ ├── FRPViewModel.kt │ │ │ └── ViewmodelUtils.kt │ │ ├── legacy │ │ └── ui │ │ │ ├── IvyColorPicker.kt │ │ │ └── theme │ │ │ ├── IvyColors.kt │ │ │ ├── components │ │ │ ├── AddPrimaryAttributeButton.kt │ │ │ ├── BackBottomBar.kt │ │ │ ├── BalanceRow.kt │ │ │ ├── BudgetBattery.kt │ │ │ ├── BufferBattery.kt │ │ │ ├── ChangeTransactionTypeModal.kt │ │ │ ├── CircleButtons.kt │ │ │ ├── CurrencyPicker.kt │ │ │ ├── CustomExchangeRateCard.kt │ │ │ ├── DateTimeRow.kt │ │ │ ├── DeleteButton.kt │ │ │ ├── GradientCut.kt │ │ │ ├── IntervalPickerRow.kt │ │ │ ├── ItemIcon.kt │ │ │ ├── IvyBasicTextField.kt │ │ │ ├── IvyBorderButton.kt │ │ │ ├── IvyButton.kt │ │ │ ├── IvyCheckbox.kt │ │ │ ├── IvyChecklistTextField.kt │ │ │ ├── IvyCircleButton.kt │ │ │ ├── IvyComponents.kt │ │ │ ├── IvyDescriptionTextField.kt │ │ │ ├── IvyDivider.kt │ │ │ ├── IvyDividerDot.kt │ │ │ ├── IvyIcon.kt │ │ │ ├── IvyNameTextFieldValue.kt │ │ │ ├── IvyNumberTextField.kt │ │ │ ├── IvyOutlinedButton.kt │ │ │ ├── IvyOutlinedTextField.kt │ │ │ ├── IvySwitch.kt │ │ │ ├── IvyTitleTextField.kt │ │ │ ├── IvyToolbar.kt │ │ │ ├── ListItem.kt │ │ │ ├── OnboardingComponents.kt │ │ │ ├── ProgressBar.kt │ │ │ ├── ReorderModal.kt │ │ │ ├── WrapContentRow.kt │ │ │ └── charts │ │ │ │ └── linechart │ │ │ │ └── IvyLineChart.kt │ │ │ ├── modal │ │ │ ├── AddKeywordModal.kt │ │ │ ├── BufferModal.kt │ │ │ ├── ChooseIconModal.kt │ │ │ ├── ChoosePeriodModal.kt │ │ │ ├── ChooseStartDateOfMonthModal.kt │ │ │ ├── CurrencyModal.kt │ │ │ ├── DeleteModal.kt │ │ │ ├── IvyModal.kt │ │ │ ├── IvyModalComponents.kt │ │ │ ├── IvyModalDomainComponents.kt │ │ │ ├── LegacyModals.kt │ │ │ ├── LoanModal.kt │ │ │ ├── LoanRecordModal.kt │ │ │ ├── MonthPickerModal.kt │ │ │ ├── NameModal.kt │ │ │ ├── ProgressModal.kt │ │ │ ├── RecurringRuleModal.kt │ │ │ └── edit │ │ │ │ ├── AccountModal.kt │ │ │ │ ├── AmountModal.kt │ │ │ │ ├── CalculatorModal.kt │ │ │ │ ├── CategoryModal.kt │ │ │ │ ├── ChooseCategoryModal.kt │ │ │ │ └── DescriptionModal.kt │ │ │ └── wallet │ │ │ ├── AmountCurrency.kt │ │ │ └── PeriodSelector.kt │ │ ├── notification │ │ ├── TransactionReminderLogic.kt │ │ └── TransactionReminderWorker.kt │ │ ├── ui │ │ ├── SearchInput.kt │ │ └── component │ │ │ ├── IncomeExpenseCards.kt │ │ │ ├── ItemStatisticToolbar.kt │ │ │ ├── edit │ │ │ ├── PrimaryAttributeColumn.kt │ │ │ ├── TransactionDateTime.kt │ │ │ └── core │ │ │ │ ├── Category.kt │ │ │ │ ├── Description.kt │ │ │ │ ├── DueDate.kt │ │ │ │ ├── EditBottomSheet.kt │ │ │ │ ├── Title.kt │ │ │ │ └── Toolbar.kt │ │ │ ├── tags │ │ │ ├── AddOrEditTagModal.kt │ │ │ ├── AddTagButton.kt │ │ │ └── ShowTagModal.kt │ │ │ └── transaction │ │ │ ├── HistoryDateDivider.kt │ │ │ ├── TransactionCard.kt │ │ │ ├── TransactionSectionDivider.kt │ │ │ ├── Transactions.kt │ │ │ ├── TransactionsDividerLine.kt │ │ │ └── Utils.kt │ │ └── utils │ │ ├── ActivityResultExt.kt │ │ ├── AmountFormatting.kt │ │ ├── ComposeExt.kt │ │ ├── DateExt.kt │ │ ├── FirebaseExt.kt │ │ ├── GesturesExt.kt │ │ ├── InputError.kt │ │ ├── IvyAnimation.kt │ │ ├── MVVMExt.kt │ │ ├── OpResult.kt │ │ ├── UIExt.kt │ │ ├── UiText.kt │ │ ├── UtilExt.kt │ │ ├── ValidationExt.kt │ │ └── WalletUtil.kt └── old-design │ ├── build.gradle.kts │ └── src │ └── main │ ├── java │ └── com │ │ └── ivy │ │ └── design │ │ ├── IvyColorPicker.kt │ │ ├── IvyContext.kt │ │ ├── api │ │ ├── IvyDesign.kt │ │ ├── IvyUI.kt │ │ └── systems │ │ │ └── IvyWalletDesign.kt │ │ ├── l0_system │ │ ├── Colors.kt │ │ ├── IvyColors.kt │ │ ├── IvyShapes.kt │ │ ├── IvyTheme.kt │ │ ├── IvyTypography.kt │ │ └── TypographyExt.kt │ │ ├── l1_buildingBlocks │ │ ├── ColumnRoot.kt │ │ ├── Dividers.kt │ │ ├── IvyIcon.kt │ │ ├── IvyText.kt │ │ ├── Shapes.kt │ │ ├── Spacers.kt │ │ └── data │ │ │ ├── Background.kt │ │ │ └── IvyPadding.kt │ │ ├── l2_components │ │ ├── Button.kt │ │ ├── ButtonWithIcon.kt │ │ ├── Checkbox.kt │ │ ├── IconButton.kt │ │ ├── InputField.kt │ │ └── Switch.kt │ │ ├── l3_ivyComponents │ │ └── ScreenTitle.kt │ │ └── utils │ │ ├── Android.kt │ │ ├── Animation.kt │ │ ├── Compose.kt │ │ ├── Insets.kt │ │ ├── Keyboard.kt │ │ ├── Padding.kt │ │ ├── Preview.kt │ │ └── View.kt │ └── res │ ├── drawable │ ├── ic_android_black_24dp.xml │ ├── ic_baseline_add_24.xml │ ├── ic_checkbox_checked.xml │ └── ic_checkbox_unchecked.xml │ ├── font │ ├── opensans_bold.ttf │ ├── opensans_bolditalic.ttf │ ├── opensans_extrabold.ttf │ ├── opensans_extrabolditalic.ttf │ ├── opensans_italic.ttf │ ├── opensans_light.ttf │ ├── opensans_lightitalic.ttf │ ├── opensans_regular.ttf │ ├── opensans_semibold.ttf │ ├── opensans_semibolditalic.ttf │ ├── raleway_black.ttf │ ├── raleway_blackitalic.ttf │ ├── raleway_bold.ttf │ ├── raleway_bolditalic.ttf │ ├── raleway_extrabold.ttf │ ├── raleway_extrabolditalic.ttf │ ├── raleway_extralight.ttf │ ├── raleway_extralightitalic.ttf │ ├── raleway_italic.ttf │ ├── raleway_light.ttf │ ├── raleway_lightitalic.ttf │ ├── raleway_medium.ttf │ ├── raleway_mediumitalic.ttf │ ├── raleway_regular.ttf │ ├── raleway_semibold.ttf │ ├── raleway_semibolditalic.ttf │ ├── raleway_thin.ttf │ └── raleway_thinitalic.ttf │ └── values │ └── colors.xml └── widget ├── add-transaction ├── build.gradle.kts └── src │ └── main │ ├── java │ └── com │ │ └── ivy │ │ └── widget │ │ └── transaction │ │ ├── AddTransactionWidget.kt │ │ ├── AddTransactionWidgetClick.kt │ │ └── AddTransactionWidgetCompact.kt │ └── res │ ├── drawable │ └── widget_compact_divider.xml │ ├── layout │ ├── widget_add_transaction.xml │ └── widget_add_transaction_compact.xml │ └── xml │ ├── add_transaction_widget_compact_info.xml │ ├── add_transaction_widget_info.xml │ └── wallet_balance_widget_info.xml ├── balance ├── build.gradle.kts └── src │ └── main │ └── java │ └── com │ └── ivy │ └── widget │ └── balance │ ├── WalletBalanceWidget.kt │ └── WalletBalanceWidgetContent.kt └── shared-base ├── build.gradle.kts └── src └── main └── java └── com └── ivy └── widget └── WidgetBase.kt /.gitattributes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/.gitattributes -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @ILIYANGERMANOV 2 | -------------------------------------------------------------------------------- /.github/workflows/paparazzi_screenshot_test.yml: -------------------------------------------------------------------------------- 1 | name: Paparazzi screenshots tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | sceenshot_test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout GIT 14 | uses: actions/checkout@v4 15 | 16 | - name: Setup Java SDK 17 | uses: actions/setup-java@v4 18 | with: 19 | distribution: 'adopt' 20 | java-version: '18' 21 | 22 | - name: Gradle cache 23 | uses: gradle/actions/setup-gradle@v4 24 | 25 | - name: Run Paparazzi screenshot tests 26 | run: ./gradlew verifyPaparazziDebug 27 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: 'Close Stale Issues and PRs' 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: '0 8 * * *' 7 | 8 | permissions: 9 | contents: write 10 | issues: write 11 | pull-requests: write 12 | 13 | jobs: 14 | stale: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/stale@v9 18 | with: 19 | days-before-issue-stale: 30 20 | days-before-issue-close: 7 21 | days-before-pr-stale: 2 22 | days-before-pr-close: 1 23 | exempt-issue-labels: keep,P0,bug 24 | exempt-pr-labels: keep,P0 25 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # GitHub Copilot persisted chat sessions 5 | /copilot/chatSessions 6 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | IvyWallet -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/ivy/wallet/di/AppBindingsModule.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.di 2 | 3 | import com.ivy.domain.AppStarter 4 | import com.ivy.wallet.IvyAppStarter 5 | import dagger.Binds 6 | import dagger.Module 7 | import dagger.hilt.InstallIn 8 | import dagger.hilt.components.SingletonComponent 9 | 10 | @Module 11 | @InstallIn(SingletonComponent::class) 12 | abstract class AppBindingsModule { 13 | @Binds 14 | abstract fun appStarter(appStarter: IvyAppStarter): AppStarter 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/ivy/wallet/migrations/Migration.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.migrations 2 | 3 | interface Migration { 4 | val key: String 5 | 6 | suspend fun migrate() 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/resources.properties: -------------------------------------------------------------------------------- 1 | unqualifiedResLocale=en-US -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/release/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/release/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/release/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-hdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-hdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-hdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-hdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-mdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-mdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-mdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-mdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xhdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xhdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xxhdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xxhdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xxxhdpi/ic_launcher_foreground.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xxxhdpi/ic_launcher_foreground.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xxxhdpi/ic_launcher_monochrome.webp -------------------------------------------------------------------------------- /app/src/release/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/app/src/release/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/release/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #F3FFF6 4 | -------------------------------------------------------------------------------- /buildSrc/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | gradlePluginPortal() 5 | } 6 | } 7 | 8 | dependencyResolutionManagement { 9 | repositories { 10 | google() 11 | gradlePluginPortal() 12 | } 13 | 14 | versionCatalogs { 15 | create("libs") { 16 | from(files("../gradle/libs.versions.toml")) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/ivy.feature.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | org.jetbrains.kotlin.plugin.compose 3 | id("ivy.module") 4 | id("ivy.compose") 5 | id("ivy.paparazzi") 6 | } 7 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/ivy.hilt.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.kotlin-android") 3 | id("dagger.hilt.android.plugin") 4 | id("com.google.devtools.ksp") 5 | } 6 | 7 | kotlin { 8 | sourceSets.all { 9 | kotlin.srcDir("build/generated/ksp/$name/kotlin") 10 | } 11 | } 12 | 13 | dependencies { 14 | implementation(libs.bundles.hilt) 15 | ksp(catalog.library("hilt-compiler")) 16 | } 17 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/ivy.integration.testing.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | defaultConfig { 7 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 8 | } 9 | 10 | packaging { 11 | resources.pickFirsts.apply { 12 | add("win32-x86-64/attach_hotspot_windows.dll") 13 | add("win32-x86/attach_hotspot_windows.dll") 14 | add("META-INF/**") 15 | add("xsd/catalog.xml") 16 | } 17 | } 18 | } 19 | 20 | dependencies { 21 | androidTestImplementation(libs.bundles.integration.testing) 22 | } 23 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/ivy.kotlinx-serialization.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.kotlin-android") 3 | id("org.jetbrains.kotlin.plugin.serialization") 4 | } 5 | 6 | dependencies { 7 | implementation(catalog.library("kotlinx-serialization-json")) 8 | } 9 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/ivy.module.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.kotlin-android") 3 | id("ivy.hilt") 4 | id("ivy.kotlinx-serialization") 5 | } 6 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/ivy.room.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.module") 3 | id("androidx.room") 4 | } 5 | 6 | dependencies { 7 | implementation(libs.bundles.room) 8 | ksp(libs.room.compiler) 9 | 10 | androidTestImplementation(libs.room.testing) 11 | } 12 | 13 | android { 14 | sourceSets { 15 | // Adds exported schema location as test app assets. 16 | getByName("androidTest").assets.srcDirs(files("$projectDir/schemas")) 17 | } 18 | } 19 | 20 | room { 21 | schemaDirectory("$projectDir/schemas") 22 | } 23 | -------------------------------------------------------------------------------- /buildSrc/src/main/kotlin/ivy.widget.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.module") 3 | org.jetbrains.kotlin.plugin.compose 4 | } 5 | 6 | android { 7 | // Compose 8 | buildFeatures { 9 | compose = true 10 | } 11 | } 12 | 13 | dependencies { 14 | implementation(libs.bundles.glance) 15 | implementation(libs.bundles.activity) 16 | } 17 | -------------------------------------------------------------------------------- /ci-actions/base/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.script") 3 | } 4 | 5 | dependencies { 6 | api(libs.bundles.ktor) 7 | } 8 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/ArrowExt.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base 2 | 3 | import arrow.core.Either 4 | 5 | fun Either.getOrThrow(): B { 6 | return fold( 7 | ifLeft = { throw IvyError(it.toString()) }, 8 | ifRight = { it } 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/Common.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base 2 | 3 | import arrow.core.Either 4 | import kotlinx.coroutines.Dispatchers 5 | import kotlinx.coroutines.withContext 6 | 7 | @DslMarker 8 | annotation class IvyDsl 9 | 10 | suspend fun catchIO( 11 | block: suspend () -> A 12 | ): Either = Either.catch { 13 | withContext(Dispatchers.IO) { 14 | block() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/Constants.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base 2 | 3 | object Constants { 4 | const val IVY_ADMIN = "ILIYANGERMANOV" 5 | const val ARG_GITHUB_PAT = "gitHubPAT" 6 | const val ARG_ISSUE_NUMBER = "issueNumber" 7 | const val IVY_BOT_USERNAME = "ivywallet" 8 | 9 | const val ISSUES_URL = "https://github.com/Ivy-Apps/ivy-wallet/issues" 10 | const val CONTRIBUTING_URL = "https://github.com/Ivy-Apps/ivy-wallet/blob/main/CONTRIBUTING.md" 11 | } 12 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/IvyError.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base 2 | 3 | class IvyError(msg: String) : Exception(msg) 4 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/github/model/GitHubComment.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base.github.model 2 | 3 | data class GitHubComment( 4 | val author: GitHubUser, 5 | val text: String, 6 | ) 7 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/github/model/GitHubIssue.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base.github.model 2 | 3 | data class GitHubIssue( 4 | val number: GitHubIssueNumber, 5 | val creator: GitHubUser, 6 | val assignee: GitHubUser? 7 | ) 8 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/github/model/GitHubLabel.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base.github.model 2 | 3 | data class GitHubLabel( 4 | val name: GitHubLabelName, 5 | ) 6 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/github/model/GitHubLabelName.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base.github.model 2 | 3 | import arrow.core.raise.Raise 4 | import arrow.core.raise.ensure 5 | import ivy.automate.base.Exact 6 | 7 | @JvmInline 8 | value class GitHubLabelName private constructor(val value: String) { 9 | companion object : Exact { 10 | override val exactName: String = "GitHubLabelName" 11 | 12 | override fun Raise.spec(raw: String): GitHubLabelName { 13 | ensure(raw.isNotBlank()) { "Cannot be blank" } 14 | return GitHubLabelName(raw.trim()) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/github/model/GitHubPAT.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base.github.model 2 | 3 | import arrow.core.raise.Raise 4 | import arrow.core.raise.ensure 5 | import ivy.automate.base.Exact 6 | 7 | @JvmInline 8 | value class GitHubPAT private constructor(val value: String) { 9 | companion object : Exact { 10 | override val exactName: String = "GitHubPAT" 11 | 12 | override fun Raise.spec(raw: String): GitHubPAT { 13 | ensure(raw.isNotBlank()) { "Cannot be blank" } 14 | return GitHubPAT(raw.trim()) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/github/model/GitHubUser.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base.github.model 2 | 3 | data class GitHubUser( 4 | val username: GitHubUsername 5 | ) 6 | -------------------------------------------------------------------------------- /ci-actions/base/src/main/kotlin/ivy/automate/base/github/model/GitHubUsername.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.base.github.model 2 | 3 | import arrow.core.raise.Raise 4 | import arrow.core.raise.ensure 5 | import ivy.automate.base.Exact 6 | 7 | @JvmInline 8 | value class GitHubUsername private constructor(val value: String) { 9 | companion object : Exact { 10 | override val exactName: String = "GitHubUsername" 11 | 12 | override fun Raise.spec(raw: String): GitHubUsername { 13 | ensure(raw.isNotBlank()) { "Cannot be blank" } 14 | return GitHubUsername(raw.trim()) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ci-actions/compose-stability/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.script") 3 | application 4 | } 5 | 6 | application { 7 | mainClass = "ivy.automate.compose.stability.MainKt" 8 | } 9 | 10 | dependencies { 11 | implementation(projects.ciActions.base) 12 | } 13 | -------------------------------------------------------------------------------- /ci-actions/compose-stability/src/main/kotlin/ivy/automate/compose/stability/model/UnstableComposable.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.compose.stability.model 2 | 3 | typealias FullyQualifiedName = String 4 | 5 | data class UnstableComposable( 6 | val fullyQualifiedName: FullyQualifiedName, 7 | val name: String, 8 | val skippable: Boolean, 9 | val restartable: Boolean, 10 | val unstableArguments: Set 11 | ) 12 | 13 | data class ComposableArgument( 14 | val name: String, 15 | val type: String 16 | ) -------------------------------------------------------------------------------- /ci-actions/issue-assign/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.script") 3 | application 4 | } 5 | 6 | application { 7 | mainClass = "ivy.automate.issue.MainKt" 8 | } 9 | 10 | dependencies { 11 | implementation(projects.ciActions.base) 12 | } 13 | -------------------------------------------------------------------------------- /ci-actions/issue-create-comment/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.script") 3 | application 4 | } 5 | 6 | application { 7 | mainClass = "ivy.automate.issue.create.MainKt" 8 | } 9 | 10 | dependencies { 11 | implementation(projects.ciActions.base) 12 | } 13 | -------------------------------------------------------------------------------- /ci-actions/pr-description-check/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.script") 3 | application 4 | } 5 | 6 | application { 7 | mainClass = "ivy.automate.pr.MainKt" 8 | } 9 | 10 | dependencies { 11 | implementation(projects.ciActions.base) 12 | } 13 | -------------------------------------------------------------------------------- /ci-actions/pr-description-check/src/main/kotlin/ivy/automate/pr/PRDescriptionAnalyzer.kt: -------------------------------------------------------------------------------- 1 | package ivy.automate.pr 2 | 3 | import arrow.core.Either 4 | 5 | interface PRDescriptionAnalyzer { 6 | fun analyze(prDescription: String): Either 7 | } -------------------------------------------------------------------------------- /debug.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/debug.jks -------------------------------------------------------------------------------- /docs/assets/app-layers.d2: -------------------------------------------------------------------------------- 1 | data: "Data Layer" { 2 | crud: "CRUD + Validation" { 3 | ds: "DataSource" 4 | r: "Repository" 5 | r -> ds 6 | } 7 | } 8 | domain: "Domain Layer" { 9 | "Business logic" { 10 | "Uses repositories to do smart things" 11 | } 12 | } 13 | ui: "UI Layer" { 14 | "Screens" { 15 | ui: "Compose UI" 16 | vm: "ViewModel" 17 | ui -> vm: "UiEvents" 18 | vm -> ui: "UiState" 19 | } 20 | } 21 | 22 | ui -> domain -> data 23 | ui -> data 24 | -------------------------------------------------------------------------------- /docs/assets/data-mapping.d2: -------------------------------------------------------------------------------- 1 | direction: right 2 | 3 | raw: "Raw data models" { 4 | "DTOs" 5 | "Entities" 6 | "Bytes" 7 | } 8 | domain: "Domain models" { 9 | "ADTs" 10 | "Explicit and exact" 11 | "Validated" 12 | } 13 | uiState: "ViewState models" { 14 | "*ViewState" 15 | "UI models: formatted and ready to display" 16 | "Optimized for Compose" 17 | } 18 | 19 | repo: "Repository" 20 | vm: "ViewModel" 21 | 22 | raw -> repo: "raw" 23 | repo -> domain: "domain" 24 | domain -> vm: "domain" 25 | vm -> uiState: "viewState" 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/assets/screen-vm.d2: -------------------------------------------------------------------------------- 1 | direction: right 2 | ui: "Compose UI" { 3 | "Draws UiState" 4 | "Sends UiEvents" 5 | } 6 | vm: "ViewModel" { 7 | "Provides UiState" 8 | "Handles UiEvents" 9 | } 10 | 11 | ui <- vm: "UiState" 12 | ui -> vm: "UiEvent" -------------------------------------------------------------------------------- /docs/guidelines/README.md: -------------------------------------------------------------------------------- 1 | # 🏗️ Guidelines Wiki 2 | 3 | This is Ivy Wallet's Developer Guidelines wiki. We recommend the following reading order: 4 | 5 | 1. **[Data Modeling](./Data-Modeling.md)** 6 | 2. **[Error Handling](./Error-Handling.md)** 7 | 3. **[Architecture](./Architecture.md)** 8 | 4. **[Screen Architecture](./Screen-Architecture.md)** 9 | 5. **[Unit Testing](./Unit-Testing.md)** 10 | 6. **[Screenshot Testing](./Screenshot-Testing.md)** 11 | -------------------------------------------------------------------------------- /docs/guidelines/Screenshot-Testing.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/docs/guidelines/Screenshot-Testing.md -------------------------------------------------------------------------------- /docs/resources/Docs.md: -------------------------------------------------------------------------------- 1 | # Official Docs 2 | 3 | - [Guide to app architecture by Google](https://developer.android.com/topic/architecture) 4 | - [Jetpack Compose](https://developer.android.com/jetpack/compose) 5 | - [Room DB](https://developer.android.com/training/data-storage/room) 6 | - [DataStore](https://developer.android.com/topic/libraries/architecture/datastore) -------------------------------------------------------------------------------- /docs/resources/README.md: -------------------------------------------------------------------------------- 1 | # Resources 📚 2 | 3 | Here you can find various programming resources that we found useful. 4 | Before you explore them we recommend checking our own **[Developer Guidelines 🏗️](../Guidelines.md)** for a quick start 5 | with core concepts and ideas. Then you can deep dive with: 6 | 7 | - [Videos](Videos.md) 8 | - [Books](Books.md) 9 | - [Blog articles](Blog-Articles.md) 10 | - [Official documentation](Docs.md) 11 | -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- 1 | json_key_file("google-play-console-user.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one 2 | package_name("com.ivy.wallet") # e.g. com.krausefx.app 3 | -------------------------------------------------------------------------------- /fastlane/metadata/android/en-GB/changelogs/default.txt: -------------------------------------------------------------------------------- 1 | Ivy Wallet periodic release, refer to (https://github.com/Ivy-Apps/ivy-wallet/releases) for changelog. If you find any issues, please report them in our GitHub repository. 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /screen/accounts/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.accounts" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | 18 | testImplementation(projects.shared.ui.testing) 19 | } 20 | -------------------------------------------------------------------------------- /screen/accounts/src/main/java/com/ivy/accounts/AccountsEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.accounts 2 | 3 | sealed interface AccountsEvent { 4 | data class OnReorder(val reorderedList: List) : 5 | AccountsEvent 6 | data class OnReorderModalVisible(val reorderVisible: Boolean) : AccountsEvent 7 | } 8 | -------------------------------------------------------------------------------- /screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab compact composable[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab compact composable[Dark].png -------------------------------------------------------------------------------- /screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab compact composable[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab compact composable[Light].png -------------------------------------------------------------------------------- /screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab composable[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab composable[Dark].png -------------------------------------------------------------------------------- /screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab composable[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab composable[Light].png -------------------------------------------------------------------------------- /screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab nonCompact composable[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab nonCompact composable[Dark].png -------------------------------------------------------------------------------- /screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab nonCompact composable[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/accounts/src/test/snapshots/images/com.ivy.accounts_AccountsTabPaparazziTest_snapshot accountTab nonCompact composable[Light].png -------------------------------------------------------------------------------- /screen/attributions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.attributions" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | implementation(projects.shared.ui.core) 13 | implementation(projects.shared.ui.navigation) 14 | 15 | testImplementation(projects.shared.ui.testing) 16 | } 17 | -------------------------------------------------------------------------------- /screen/attributions/src/main/java/com/ivy/attributions/AttributionItem.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.attributions 2 | 3 | sealed interface AttributionItem { 4 | data class Attribution(val name: String, val link: String) : AttributionItem 5 | data class Divider(val sectionName: String) : AttributionItem 6 | } 7 | -------------------------------------------------------------------------------- /screen/attributions/src/main/java/com/ivy/attributions/AttributionsEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.attributions 2 | 3 | sealed interface AttributionsEvent 4 | -------------------------------------------------------------------------------- /screen/attributions/src/main/java/com/ivy/attributions/AttributionsState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.attributions 2 | 3 | import kotlinx.collections.immutable.ImmutableList 4 | 5 | data class AttributionsState( 6 | val attributionItems: ImmutableList 7 | ) 8 | -------------------------------------------------------------------------------- /screen/attributions/src/test/snapshots/images/com.ivy.attributions_AttributionsScreenPaparazziTest_snapshot Attribution Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/attributions/src/test/snapshots/images/com.ivy.attributions_AttributionsScreenPaparazziTest_snapshot Attribution Screen[Dark].png -------------------------------------------------------------------------------- /screen/attributions/src/test/snapshots/images/com.ivy.attributions_AttributionsScreenPaparazziTest_snapshot Attribution Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/attributions/src/test/snapshots/images/com.ivy.attributions_AttributionsScreenPaparazziTest_snapshot Attribution Screen[Light].png -------------------------------------------------------------------------------- /screen/balance/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.balance" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | implementation(projects.shared.ui.core) 13 | implementation(projects.shared.ui.navigation) 14 | implementation(projects.temp.legacyCode) 15 | implementation(projects.temp.oldDesign) 16 | 17 | testImplementation(projects.shared.ui.testing) 18 | } -------------------------------------------------------------------------------- /screen/balance/src/main/java/com/ivy/balance/BalanceEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.balance 2 | 3 | import com.ivy.legacy.data.model.TimePeriod 4 | 5 | sealed interface BalanceEvent { 6 | data class OnSetPeriod(val timePeriod: TimePeriod) : BalanceEvent 7 | data object OnPreviousMonth : BalanceEvent 8 | data object OnNextMonth : BalanceEvent 9 | } 10 | -------------------------------------------------------------------------------- /screen/balance/src/main/java/com/ivy/balance/BalanceState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.balance 2 | 3 | import androidx.compose.runtime.Immutable 4 | import com.ivy.legacy.data.model.TimePeriod 5 | 6 | @Immutable 7 | data class BalanceState( 8 | val period: TimePeriod, 9 | val baseCurrencyCode: String, 10 | val currentBalance: Double, 11 | val plannedPaymentsAmount: Double, 12 | val balanceAfterPlannedPayments: Double 13 | ) 14 | -------------------------------------------------------------------------------- /screen/balance/src/test/snapshots/images/com.ivy.balance_BalanceScreenPaparazziTest_snapshot Balance Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/balance/src/test/snapshots/images/com.ivy.balance_BalanceScreenPaparazziTest_snapshot Balance Screen[Dark].png -------------------------------------------------------------------------------- /screen/balance/src/test/snapshots/images/com.ivy.balance_BalanceScreenPaparazziTest_snapshot Balance Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/balance/src/test/snapshots/images/com.ivy.balance_BalanceScreenPaparazziTest_snapshot Balance Screen[Light].png -------------------------------------------------------------------------------- /screen/budgets/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.budgets" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | 18 | testImplementation(projects.shared.ui.testing) 19 | } 20 | -------------------------------------------------------------------------------- /screen/budgets/src/main/java/com/ivy/budgets/BudgetExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.budgets 2 | 3 | import com.ivy.base.legacy.stringRes 4 | import com.ivy.ui.R 5 | 6 | fun determineBudgetType(categoriesCount: Int): String { 7 | return when (categoriesCount) { 8 | 0 -> stringRes(R.string.total_budget) 9 | 1 -> stringRes(R.string.category_budget) 10 | else -> stringRes(R.string.multi_category_budget, categoriesCount.toString()) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /screen/categories/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.categories" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | 18 | testImplementation(projects.shared.ui.testing) 19 | } -------------------------------------------------------------------------------- /screen/categories/src/main/java/com/ivy/categories/CategoryData.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.categories 2 | 3 | import com.ivy.data.model.Category 4 | import com.ivy.wallet.domain.data.Reorderable 5 | 6 | data class CategoryData( 7 | val category: Category, 8 | val monthlyBalance: Double, 9 | val monthlyExpenses: Double, 10 | val monthlyIncome: Double 11 | ) : Reorderable { 12 | override fun getItemOrderNum() = category.orderNum 13 | 14 | override fun withNewOrderNum(newOrderNum: Double) = this.copy( 15 | category = category.copy( 16 | orderNum = newOrderNum 17 | ) 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories Screen[Dark].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories Screen[Light].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen with search bar[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen with search bar[Dark].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen with search bar[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen with search bar[Light].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen[Dark].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories compact Screen[Light].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen with search bar[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen with search bar[Dark].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen with search bar[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen with search bar[Light].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen[Dark].png -------------------------------------------------------------------------------- /screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/categories/src/test/snapshots/images/com.ivy.categories_CategoriesScreenPaparazziTest_snapshot Categories nonCompact Screen[Light].png -------------------------------------------------------------------------------- /screen/contributors/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.contributors" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | implementation(projects.shared.ui.core) 13 | implementation(projects.shared.ui.navigation) 14 | 15 | implementation(libs.bundles.ktor) 16 | 17 | testImplementation(projects.shared.ui.testing) 18 | } 19 | -------------------------------------------------------------------------------- /screen/contributors/src/main/java/com/ivy/contributors/Contributor.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.contributors 2 | 3 | data class Contributor( 4 | val name: String, 5 | val photoUrl: String, 6 | val contributionsCount: String, 7 | val githubProfileUrl: String 8 | ) 9 | -------------------------------------------------------------------------------- /screen/contributors/src/main/java/com/ivy/contributors/ContributorsEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.contributors 2 | 3 | sealed interface ContributorsEvent { 4 | data object TryAgainButtonClicked : ContributorsEvent 5 | } 6 | -------------------------------------------------------------------------------- /screen/contributors/src/main/java/com/ivy/contributors/ProjectRepositoryInfo.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.contributors 2 | 3 | data class ProjectRepositoryInfo( 4 | val forks: String, 5 | val stars: String, 6 | val url: String 7 | ) 8 | -------------------------------------------------------------------------------- /screen/contributors/src/test/snapshots/images/com.ivy.contributors_ContributorsScreenPaparazziTest_snapshot Contributor Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/contributors/src/test/snapshots/images/com.ivy.contributors_ContributorsScreenPaparazziTest_snapshot Contributor Screen[Dark].png -------------------------------------------------------------------------------- /screen/contributors/src/test/snapshots/images/com.ivy.contributors_ContributorsScreenPaparazziTest_snapshot Contributor Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/contributors/src/test/snapshots/images/com.ivy.contributors_ContributorsScreenPaparazziTest_snapshot Contributor Screen[Light].png -------------------------------------------------------------------------------- /screen/disclaimer/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.disclaimer" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.data.core) 11 | implementation(projects.shared.ui.core) 12 | implementation(projects.shared.ui.navigation) 13 | 14 | testImplementation(projects.shared.ui.testing) 15 | } 16 | -------------------------------------------------------------------------------- /screen/disclaimer/src/main/java/com/ivy/disclaimer/DisclaimerViewState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.disclaimer 2 | 3 | import kotlinx.collections.immutable.ImmutableList 4 | 5 | data class DisclaimerViewState( 6 | val checkboxes: ImmutableList, 7 | val agreeButtonEnabled: Boolean, 8 | ) 9 | 10 | data class CheckboxViewState( 11 | val text: String, 12 | val checked: Boolean 13 | ) 14 | 15 | sealed interface DisclaimerViewEvent { 16 | data class OnCheckboxClick(val index: Int) : DisclaimerViewEvent 17 | data object OnAgreeClick : DisclaimerViewEvent 18 | } -------------------------------------------------------------------------------- /screen/disclaimer/src/main/java/com/ivy/disclaimer/composables/DisclaimerTopAppBar.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.disclaimer.composables 2 | 3 | import androidx.compose.material3.ExperimentalMaterial3Api 4 | import androidx.compose.material3.Text 5 | import androidx.compose.material3.TopAppBar 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.Modifier 8 | 9 | @OptIn(ExperimentalMaterial3Api::class) 10 | @Composable 11 | fun DisclaimerTopAppBar( 12 | modifier: Modifier = Modifier, 13 | ) { 14 | TopAppBar( 15 | modifier = modifier, 16 | title = { 17 | Text(text = "Important User Agreement") 18 | } 19 | ) 20 | } -------------------------------------------------------------------------------- /screen/disclaimer/src/test/snapshots/images/com.ivy.disclaimer_DisclaimerScreenPaparazziTest_all checked[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/disclaimer/src/test/snapshots/images/com.ivy.disclaimer_DisclaimerScreenPaparazziTest_all checked[Dark].png -------------------------------------------------------------------------------- /screen/disclaimer/src/test/snapshots/images/com.ivy.disclaimer_DisclaimerScreenPaparazziTest_all checked[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/disclaimer/src/test/snapshots/images/com.ivy.disclaimer_DisclaimerScreenPaparazziTest_all checked[Light].png -------------------------------------------------------------------------------- /screen/disclaimer/src/test/snapshots/images/com.ivy.disclaimer_DisclaimerScreenPaparazziTest_none checked[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/disclaimer/src/test/snapshots/images/com.ivy.disclaimer_DisclaimerScreenPaparazziTest_none checked[Dark].png -------------------------------------------------------------------------------- /screen/disclaimer/src/test/snapshots/images/com.ivy.disclaimer_DisclaimerScreenPaparazziTest_none checked[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/disclaimer/src/test/snapshots/images/com.ivy.disclaimer_DisclaimerScreenPaparazziTest_none checked[Light].png -------------------------------------------------------------------------------- /screen/edit-transaction/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.transaction" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | implementation(projects.widget.balance) 18 | 19 | testImplementation(projects.shared.ui.testing) 20 | } 21 | -------------------------------------------------------------------------------- /screen/exchange-rates/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.exchangerates" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | 18 | testImplementation(projects.shared.ui.testing) 19 | } 20 | -------------------------------------------------------------------------------- /screen/exchange-rates/src/main/java/com/ivy/exchangerates/RatesEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.exchangerates 2 | 3 | import com.ivy.exchangerates.data.RateUi 4 | 5 | sealed interface RatesEvent { 6 | data class Search(val query: String) : RatesEvent 7 | data class RemoveOverride(val rate: RateUi) : RatesEvent 8 | data class UpdateRate(val rate: RateUi, val newRate: Double) : RatesEvent 9 | data class AddRate(val rate: RateUi) : RatesEvent 10 | } 11 | -------------------------------------------------------------------------------- /screen/exchange-rates/src/main/java/com/ivy/exchangerates/RatesState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.exchangerates 2 | 3 | import com.ivy.exchangerates.data.RateUi 4 | import kotlinx.collections.immutable.ImmutableList 5 | 6 | data class RatesState( 7 | val baseCurrency: String, 8 | val manual: ImmutableList, 9 | val automatic: ImmutableList 10 | ) 11 | -------------------------------------------------------------------------------- /screen/exchange-rates/src/main/java/com/ivy/exchangerates/data/RateUi.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.exchangerates.data 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Immutable 6 | data class RateUi( 7 | val from: String, 8 | val to: String, 9 | val rate: Double 10 | ) 11 | -------------------------------------------------------------------------------- /screen/exchange-rates/src/test/snapshots/images/com.ivy.exchangerates_ExchangeRatesScreenPaparazziTest_snapshot Exchange Rates Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/exchange-rates/src/test/snapshots/images/com.ivy.exchangerates_ExchangeRatesScreenPaparazziTest_snapshot Exchange Rates Screen[Dark].png -------------------------------------------------------------------------------- /screen/exchange-rates/src/test/snapshots/images/com.ivy.exchangerates_ExchangeRatesScreenPaparazziTest_snapshot Exchange Rates Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/exchange-rates/src/test/snapshots/images/com.ivy.exchangerates_ExchangeRatesScreenPaparazziTest_snapshot Exchange Rates Screen[Light].png -------------------------------------------------------------------------------- /screen/features/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.features" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | implementation(projects.shared.ui.core) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | } -------------------------------------------------------------------------------- /screen/features/src/main/java/com/ivy/features/FeaturesUiEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.features 2 | 3 | sealed interface FeaturesUiEvent { 4 | data class ToggleFeature(val key: String) : FeaturesUiEvent 5 | } 6 | -------------------------------------------------------------------------------- /screen/features/src/main/java/com/ivy/features/FeaturesUiState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.features 2 | 3 | import kotlinx.collections.immutable.ImmutableList 4 | 5 | data class FeaturesUiState( 6 | val featureItemViewStates: ImmutableList, 7 | ) 8 | 9 | sealed interface FeatureItemViewState { 10 | data class FeatureToggleViewState( 11 | val key: String, 12 | val name: String, 13 | val enabled: Boolean, 14 | val description: String?, 15 | ) : FeatureItemViewState 16 | 17 | data class FeatureHeaderViewState(val name: String) : FeatureItemViewState 18 | } 19 | -------------------------------------------------------------------------------- /screen/home/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.home" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | implementation(projects.widget.addTransaction) 18 | 19 | testImplementation(projects.shared.ui.testing) 20 | } 21 | -------------------------------------------------------------------------------- /screen/home/src/main/java/com/ivy/home/Constants.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.home 2 | 3 | object Constants { 4 | const val SWIPE_HORIZONTAL_THRESHOLD = 200 5 | const val SWIPE_DOWN_THRESHOLD_OPEN_MORE_MENU = 200 6 | } 7 | -------------------------------------------------------------------------------- /screen/home/src/test/snapshots/images/com.ivy.home_HomePaparazziTest_snapshot Home Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/home/src/test/snapshots/images/com.ivy.home_HomePaparazziTest_snapshot Home Screen[Dark].png -------------------------------------------------------------------------------- /screen/home/src/test/snapshots/images/com.ivy.home_HomePaparazziTest_snapshot Home Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/home/src/test/snapshots/images/com.ivy.home_HomePaparazziTest_snapshot Home Screen[Light].png -------------------------------------------------------------------------------- /screen/import-data/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.importdata" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.screen.onboarding) 11 | implementation(projects.shared.base) 12 | implementation(projects.shared.data.core) 13 | implementation(projects.shared.domain) 14 | implementation(projects.shared.ui.core) 15 | implementation(projects.shared.ui.navigation) 16 | implementation(projects.temp.legacyCode) 17 | implementation(projects.temp.oldDesign) 18 | 19 | implementation(libs.bundles.opencsv) 20 | } -------------------------------------------------------------------------------- /screen/import-data/src/main/java/com/ivy/importdata/csvimport/ImportStep.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.importdata.csvimport 2 | 3 | enum class ImportStep { 4 | IMPORT_FROM, INSTRUCTIONS, LOADING, RESULT 5 | } 6 | -------------------------------------------------------------------------------- /screen/import-data/src/main/java/com/ivy/importdata/csvimport/flow/instructions/FortuneCitySteps.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.importdata.csvimport.flow.instructions 2 | 3 | import androidx.compose.runtime.Composable 4 | 5 | @Composable 6 | fun FortuneCitySteps( 7 | onUploadClick: () -> Unit 8 | ) { 9 | DefaultImportSteps( 10 | articleUrl = "https://fourdesire.helpshift.com/hc/en/5-fortune-city/faq/242-can-i-export-my-fortune-city-records/", 11 | onUploadClick = onUploadClick 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /screen/import-data/src/main/java/com/ivy/importdata/csvimport/flow/instructions/KTWMoneyMangerSteps.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.importdata.csvimport.flow.instructions 2 | 3 | import androidx.compose.runtime.Composable 4 | 5 | @Composable 6 | fun KTWMoneyManagerSteps( 7 | onUploadClick: () -> Unit 8 | ) { 9 | DefaultImportSteps( 10 | onUploadClick = onUploadClick 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /screen/import-data/src/main/java/com/ivy/importdata/csvimport/flow/instructions/OneMoneySteps.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.importdata.csvimport.flow.instructions 2 | 3 | import androidx.compose.runtime.Composable 4 | 5 | @Composable 6 | fun OneMoneySteps( 7 | onUploadClick: () -> Unit 8 | ) { 9 | DefaultImportSteps( 10 | onUploadClick = onUploadClick 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /screen/import-data/src/main/java/com/ivy/importdata/csvimport/flow/instructions/WalletByBudgetBakersSteps.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.importdata.csvimport.flow.instructions 2 | 3 | import androidx.compose.runtime.Composable 4 | 5 | @Composable 6 | fun WalletByBudgetBakersSteps( 7 | onUploadClick: () -> Unit 8 | ) { 9 | DefaultImportSteps( 10 | articleUrl = "https://support.budgetbakers.com/hc/en-us/articles/209753325-How-to-EXPORT-transactions-from-Wallet", 11 | onUploadClick = onUploadClick 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /screen/loans/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.loans" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | 18 | testImplementation(projects.shared.ui.testing) 19 | } 20 | -------------------------------------------------------------------------------- /screen/loans/src/main/java/com/ivy/loans/loan/Constants.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.loans.loan 2 | 3 | internal object Constants { 4 | const val SWIPE_HORIZONTAL_THRESHOLD = 200 5 | } 6 | -------------------------------------------------------------------------------- /screen/loans/src/main/java/com/ivy/loans/loan/LoanTab.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.loans.loan 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Immutable 6 | enum class LoanTab { 7 | PENDING, COMPLETED 8 | } -------------------------------------------------------------------------------- /screen/loans/src/main/java/com/ivy/loans/loan/data/DisplayLoanRecord.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.loans.loan.data 2 | 3 | import com.ivy.legacy.datamodel.Account 4 | import com.ivy.legacy.datamodel.LoanRecord 5 | 6 | data class DisplayLoanRecord( 7 | val loanRecord: LoanRecord, 8 | val account: Account? = null, 9 | val loanRecordCurrencyCode: String = "", 10 | val loanCurrencyCode: String = "", 11 | val loanRecordTransaction: Boolean = false, 12 | ) 13 | -------------------------------------------------------------------------------- /screen/loans/src/main/java/com/ivy/loans/loandetails/events/DeleteLoanModalEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.loans.loandetails.events 2 | 3 | sealed interface DeleteLoanModalEvent : LoanDetailsScreenEvent { 4 | data object OnDeleteLoan : DeleteLoanModalEvent 5 | data class OnDismissDeleteLoan(val isDeleteModalVisible: Boolean) : DeleteLoanModalEvent 6 | } 7 | -------------------------------------------------------------------------------- /screen/loans/src/main/java/com/ivy/loans/loandetails/events/LoanDetailsScreenEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.loans.loandetails.events 2 | 3 | import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData 4 | 5 | sealed interface LoanDetailsScreenEvent { 6 | data object OnEditLoanClick : LoanDetailsScreenEvent 7 | data object OnAmountClick : LoanDetailsScreenEvent 8 | data object OnAddRecord : LoanDetailsScreenEvent 9 | data class OnCreateAccount(val data: CreateAccountData) : LoanDetailsScreenEvent 10 | } 11 | -------------------------------------------------------------------------------- /screen/loans/src/main/java/com/ivy/loans/loandetails/events/LoanModalEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.loans.loandetails.events 2 | 3 | import com.ivy.legacy.datamodel.Loan 4 | 5 | sealed interface LoanModalEvent : LoanDetailsScreenEvent { 6 | data object OnDismissLoanModal : LoanModalEvent 7 | data class OnEditLoanModal(val loan: Loan, val createLoanTransaction: Boolean) : 8 | LoanModalEvent 9 | 10 | data object PerformCalculation : LoanModalEvent 11 | data object OnChangeDate : LoanModalEvent 12 | data object OnChangeTime : LoanModalEvent 13 | } 14 | -------------------------------------------------------------------------------- /screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen composable[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen composable[Dark].png -------------------------------------------------------------------------------- /screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen composable[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen composable[Light].png -------------------------------------------------------------------------------- /screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen non tabular composable[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen non tabular composable[Dark].png -------------------------------------------------------------------------------- /screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen non tabular composable[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen non tabular composable[Light].png -------------------------------------------------------------------------------- /screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen tabular composable[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen tabular composable[Dark].png -------------------------------------------------------------------------------- /screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen tabular composable[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/loans/src/test/snapshots/images/com.ivy.loans_LoanScreenPaparazziTest_snapshot loanScreen tabular composable[Light].png -------------------------------------------------------------------------------- /screen/main/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.main" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.screen.accounts) 11 | implementation(projects.screen.home) 12 | implementation(projects.shared.base) 13 | implementation(projects.shared.data.core) 14 | implementation(projects.shared.domain) 15 | implementation(projects.shared.ui.core) 16 | implementation(projects.shared.ui.navigation) 17 | implementation(projects.temp.legacyCode) 18 | implementation(projects.temp.oldDesign) 19 | } 20 | -------------------------------------------------------------------------------- /screen/onboarding/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.onboarding" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | } 18 | -------------------------------------------------------------------------------- /screen/onboarding/src/main/java/com/ivy/onboarding/OnboardingState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.onboarding 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Immutable 6 | enum class OnboardingState { 7 | SPLASH, 8 | LOGIN, 9 | CHOOSE_PATH, 10 | CURRENCY, 11 | ACCOUNTS, 12 | CATEGORIES 13 | } 14 | -------------------------------------------------------------------------------- /screen/piechart/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.piechart" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | } 18 | -------------------------------------------------------------------------------- /screen/piechart/src/main/java/com/ivy/piechart/CategoryAmount.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.piechart 2 | 3 | import androidx.compose.runtime.Immutable 4 | import com.ivy.base.legacy.Transaction 5 | import com.ivy.data.model.Category 6 | 7 | @Immutable 8 | data class CategoryAmount( 9 | val category: Category?, 10 | val amount: Double, 11 | val associatedTransactions: List = emptyList(), 12 | val isCategoryUnspecified: Boolean = false 13 | ) 14 | -------------------------------------------------------------------------------- /screen/piechart/src/main/java/com/ivy/piechart/SelectedCategory.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.piechart 2 | 3 | import androidx.compose.runtime.Immutable 4 | import com.ivy.data.model.Category 5 | 6 | @Immutable 7 | data class SelectedCategory( 8 | val category: Category // null - Unspecified 9 | ) 10 | -------------------------------------------------------------------------------- /screen/planned-payments/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.planned" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | } -------------------------------------------------------------------------------- /screen/planned-payments/src/main/java/com/ivy/planned/list/PlannedPaymentsScreenEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.planned.list 2 | 3 | sealed interface PlannedPaymentsScreenEvent { 4 | data class OnOneTimePaymentsExpanded(val isExpanded: Boolean) : PlannedPaymentsScreenEvent 5 | data class OnRecurringPaymentsExpanded(val isExpanded: Boolean) : PlannedPaymentsScreenEvent 6 | } 7 | -------------------------------------------------------------------------------- /screen/releases/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.releases" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | implementation(projects.shared.ui.core) 13 | implementation(projects.shared.ui.navigation) 14 | 15 | implementation(libs.bundles.ktor) 16 | } 17 | -------------------------------------------------------------------------------- /screen/releases/src/main/java/com/ivy/releases/ReleaseInfo.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.releases 2 | 3 | import kotlinx.collections.immutable.ImmutableList 4 | 5 | data class ReleaseInfo( 6 | val releaseName: String, 7 | val releaseUrl: String, 8 | val releaseDate: String, 9 | val releaseCommits: ImmutableList 10 | ) 11 | -------------------------------------------------------------------------------- /screen/releases/src/main/java/com/ivy/releases/ReleasesEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.releases 2 | 3 | sealed interface ReleasesEvent { 4 | data object OnTryAgainClick : ReleasesEvent 5 | } 6 | -------------------------------------------------------------------------------- /screen/releases/src/main/java/com/ivy/releases/ReleasesState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.releases 2 | 3 | import kotlinx.collections.immutable.ImmutableList 4 | 5 | sealed interface ReleasesState { 6 | data class Success(val releasesInfo: ImmutableList) : ReleasesState 7 | data class Loading(val loadingMessage: String) : ReleasesState 8 | data class Error(val errorMessage: String) : ReleasesState 9 | } 10 | -------------------------------------------------------------------------------- /screen/reports/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.reports" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | 18 | testImplementation(projects.shared.ui.testing) 19 | } -------------------------------------------------------------------------------- /screen/reports/src/test/snapshots/images/com.ivy.report_ReportPaparazziTest_snapshot Report Screen no filter[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/reports/src/test/snapshots/images/com.ivy.report_ReportPaparazziTest_snapshot Report Screen no filter[Dark].png -------------------------------------------------------------------------------- /screen/reports/src/test/snapshots/images/com.ivy.report_ReportPaparazziTest_snapshot Report Screen no filter[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/reports/src/test/snapshots/images/com.ivy.report_ReportPaparazziTest_snapshot Report Screen no filter[Light].png -------------------------------------------------------------------------------- /screen/reports/src/test/snapshots/images/com.ivy.report_ReportPaparazziTest_snapshot Report Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/reports/src/test/snapshots/images/com.ivy.report_ReportPaparazziTest_snapshot Report Screen[Dark].png -------------------------------------------------------------------------------- /screen/reports/src/test/snapshots/images/com.ivy.report_ReportPaparazziTest_snapshot Report Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/reports/src/test/snapshots/images/com.ivy.report_ReportPaparazziTest_snapshot Report Screen[Light].png -------------------------------------------------------------------------------- /screen/search/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.search" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | 18 | testImplementation(projects.shared.ui.testing) 19 | } 20 | -------------------------------------------------------------------------------- /screen/search/src/main/java/com/ivy/search/SearchEvent.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.search 2 | 3 | sealed interface SearchEvent { 4 | data class Search(val query: String) : SearchEvent 5 | } 6 | -------------------------------------------------------------------------------- /screen/search/src/main/java/com/ivy/search/SearchState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.search 2 | 3 | import com.ivy.base.legacy.TransactionHistoryItem 4 | import com.ivy.data.model.Category 5 | import com.ivy.legacy.datamodel.Account 6 | import kotlinx.collections.immutable.ImmutableList 7 | 8 | data class SearchState( 9 | val searchQuery: String, 10 | val transactions: ImmutableList, 11 | val baseCurrency: String, 12 | val accounts: ImmutableList, 13 | val categories: ImmutableList, 14 | val shouldShowAccountSpecificColorInTransactions: Boolean 15 | ) 16 | -------------------------------------------------------------------------------- /screen/search/src/test/snapshots/images/com.ivy.search_SearchPaparazziTest_snapshot Search Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/search/src/test/snapshots/images/com.ivy.search_SearchPaparazziTest_snapshot Search Screen[Dark].png -------------------------------------------------------------------------------- /screen/search/src/test/snapshots/images/com.ivy.search_SearchPaparazziTest_snapshot Search Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/search/src/test/snapshots/images/com.ivy.search_SearchPaparazziTest_snapshot Search Screen[Light].png -------------------------------------------------------------------------------- /screen/settings/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.settings" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | implementation(projects.widget.balance) 18 | 19 | testImplementation(projects.shared.ui.testing) 20 | } 21 | -------------------------------------------------------------------------------- /screen/settings/src/main/java/com/ivy/settings/SettingsState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.settings 2 | 3 | import com.ivy.base.legacy.Theme 4 | 5 | data class SettingsState( 6 | val currencyCode: String, 7 | val name: String, 8 | val currentTheme: Theme, 9 | val lockApp: Boolean, 10 | val showNotifications: Boolean, 11 | val hideCurrentBalance: Boolean, 12 | val hideIncome: Boolean, 13 | val treatTransfersAsIncomeExpense: Boolean, 14 | val startDateOfMonth: String, 15 | val progressState: Boolean, 16 | val languageOptionVisible: Boolean 17 | ) 18 | -------------------------------------------------------------------------------- /screen/transactions/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.transactions" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.data.core) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | implementation(projects.temp.legacyCode) 16 | implementation(projects.temp.oldDesign) 17 | 18 | testImplementation(projects.shared.ui.testing) 19 | } 20 | -------------------------------------------------------------------------------- /screen/transactions/src/test/snapshots/images/com.ivy.transactions_TransactionsPaparazziTest_snapshot Transactions Screen[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/transactions/src/test/snapshots/images/com.ivy.transactions_TransactionsPaparazziTest_snapshot Transactions Screen[Dark].png -------------------------------------------------------------------------------- /screen/transactions/src/test/snapshots/images/com.ivy.transactions_TransactionsPaparazziTest_snapshot Transactions Screen[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/screen/transactions/src/test/snapshots/images/com.ivy.transactions_TransactionsPaparazziTest_snapshot Transactions Screen[Light].png -------------------------------------------------------------------------------- /scripts/composeStability.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ------------------- 4 | # 0. ROOT DIRECTORY CHECK 5 | # ------------------- 6 | 7 | # Check if the script is being run from the root directory of the repo 8 | if [ ! -f "settings.gradle.kts" ]; then 9 | echo "ERROR:" 10 | echo "Please run this script from the root directory of the repo." 11 | exit 1 12 | fi 13 | 14 | ./gradlew assembleDemo -PcomposeCompilerReports=true || exit 1 15 | ./gradlew :ci-actions:compose-stability:run || exit 1 -------------------------------------------------------------------------------- /scripts/detekt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ------------------- 4 | # 0. ROOT DIRECTORY CHECK 5 | # ------------------- 6 | 7 | # Check if the script is being run from the root directory of the repo 8 | if [ ! -f "settings.gradle.kts" ]; then 9 | echo "ERROR:" 10 | echo "Please run this script from the root directory of the repo." 11 | exit 1 12 | fi 13 | 14 | 15 | ./gradlew detekt || exit 0 -------------------------------------------------------------------------------- /scripts/detektBaseline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ------------------- 4 | # 0. ROOT DIRECTORY CHECK 5 | # ------------------- 6 | 7 | # Check if the script is being run from the root directory of the repo 8 | if [ ! -f "settings.gradle.kts" ]; then 9 | echo "ERROR:" 10 | echo "Please run this script from the root directory of the repo." 11 | exit 1 12 | fi 13 | 14 | 15 | ./gradlew detektBaseline || exit 0 16 | git add config/detekt/baseline.yml || exit 0 17 | git commit -m "Add Detekt baseline" || exit 0 18 | echo "Detekt baseline added." 19 | echo "[SUCCESS] Detekt baseline committed. Do 'git push'." -------------------------------------------------------------------------------- /scripts/detektFormat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fetch changed and untracked Kotlin files 4 | CHANGED_FILES=$(git diff --name-only HEAD | grep '\.kt[s]*$' | tr '\n' ',') 5 | 6 | if [ -z "$CHANGED_FILES" ]; then 7 | echo "No Kotlin files have changed." 8 | exit 0 9 | fi 10 | 11 | # Run detektFormat only on those files 12 | ./gradlew detektFormat -Ddetekt.filesToCheck=$CHANGED_FILES 13 | -------------------------------------------------------------------------------- /scripts/integrationTests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ------------------- 4 | # 0. ROOT DIRECTORY CHECK 5 | # ------------------- 6 | 7 | # Check if the script is being run from the root directory of the repo 8 | if [ ! -f "settings.gradle.kts" ]; then 9 | echo "ERROR:" 10 | echo "Please run this script from the root directory of the repo." 11 | exit 1 12 | fi 13 | 14 | ./gradlew :shared:data:core:connectedDebugAndroidTest || exit 1 15 | ./gradlew :shared:domain:connectedDebugAndroidTest || exit 1 16 | 17 | -------------------------------------------------------------------------------- /scripts/lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ------------------- 4 | # 0. ROOT DIRECTORY CHECK 5 | # ------------------- 6 | 7 | # Check if the script is being run from the root directory of the repo 8 | if [ ! -f "settings.gradle.kts" ]; then 9 | echo "ERROR:" 10 | echo "Please run this script from the root directory of the repo." 11 | exit 1 12 | fi 13 | 14 | 15 | ./gradlew lintR 16 | open build/reports/lint/lint.html 17 | echo "[FINISHED] Lint report opened in your default browser." -------------------------------------------------------------------------------- /scripts/paparazziScreenshotTests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ------------------- 4 | # 0. ROOT DIRECTORY CHECK 5 | # ------------------- 6 | 7 | # Check if the script is being run from the root directory of the repo 8 | if [ ! -f "settings.gradle.kts" ]; then 9 | echo "ERROR:" 10 | echo "Please run this script from the root directory of the repo." 11 | exit 1 12 | fi 13 | 14 | ./gradlew verifyPaparazziDebug || exit 1 -------------------------------------------------------------------------------- /scripts/unitTests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ------------------- 4 | # 0. ROOT DIRECTORY CHECK 5 | # ------------------- 6 | 7 | # Check if the script is being run from the root directory of the repo 8 | if [ ! -f "settings.gradle.kts" ]; then 9 | echo "ERROR:" 10 | echo "Please run this script from the root directory of the repo." 11 | exit 1 12 | fi 13 | 14 | 15 | ./gradlew testDebugUnitTest || exit 0 -------------------------------------------------------------------------------- /shared/base/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.base" 7 | } 8 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/di/KotlinxSerializationModule.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.di 2 | 3 | import dagger.Module 4 | import dagger.Provides 5 | import dagger.hilt.InstallIn 6 | import dagger.hilt.components.SingletonComponent 7 | import kotlinx.serialization.json.Json 8 | 9 | @Module 10 | @InstallIn(SingletonComponent::class) 11 | object KotlinxSerializationModule { 12 | @Provides 13 | fun provideJson(): Json { 14 | return Json { 15 | ignoreUnknownKeys = true 16 | isLenient = true 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/legacy/LegacyTag.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.legacy 2 | 3 | import androidx.compose.runtime.Immutable 4 | import java.util.UUID 5 | 6 | @Immutable 7 | @Deprecated("Use Tag Data Model") 8 | @Suppress("DataClassTypedIDs") 9 | data class LegacyTag(val id: UUID, val name: String) 10 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/legacy/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.legacy 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Deprecated("Old design system. Use `:ivy-design` and Material3") 6 | @Immutable 7 | enum class Theme { 8 | LIGHT, DARK, AUTO, AMOLED_DARK 9 | } 10 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/legacy/TransactionHistoryItem.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.legacy 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Deprecated("Legacy data model. Will be deleted") 6 | @Immutable 7 | interface TransactionHistoryItem 8 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/model/IntervalType.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model 2 | 3 | import androidx.annotation.Keep 4 | 5 | @Keep 6 | enum class IntervalType { 7 | DAY, WEEK, MONTH, YEAR 8 | } 9 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/model/LoanRecordType.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.model 2 | 3 | import androidx.annotation.Keep 4 | import androidx.compose.runtime.Immutable 5 | import kotlinx.serialization.Serializable 6 | 7 | @Immutable 8 | @Keep 9 | @Serializable 10 | enum class LoanRecordType { 11 | INCREASE, DECREASE 12 | } 13 | 14 | fun LoanRecordType.processByType(decreaseAction: () -> T, increaseAction: () -> T): T { 15 | return when (this) { 16 | LoanRecordType.DECREASE -> decreaseAction() 17 | LoanRecordType.INCREASE -> increaseAction() 18 | } 19 | } -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/model/LoanType.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model 2 | 3 | import androidx.annotation.Keep 4 | 5 | @Keep 6 | enum class LoanType { 7 | BORROW, LEND 8 | } 9 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/model/TransactionType.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.model 2 | 3 | import androidx.annotation.Keep 4 | import androidx.compose.runtime.Immutable 5 | import kotlinx.serialization.Serializable 6 | 7 | @Immutable 8 | @Keep 9 | @Serializable 10 | enum class TransactionType { 11 | INCOME, EXPENSE, TRANSFER 12 | } 13 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/resource/ResourceProvider.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.resource 2 | 3 | import androidx.annotation.StringRes 4 | 5 | interface ResourceProvider { 6 | fun getString(@StringRes resId: Int): String 7 | fun getString(@StringRes resId: Int, vararg args: Any): String 8 | } -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/threading/DispatchersProvider.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.threading 2 | 3 | import kotlin.coroutines.CoroutineContext 4 | 5 | interface DispatchersProvider { 6 | val main: CoroutineContext 7 | val io: CoroutineContext 8 | val default: CoroutineContext 9 | } -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/threading/IvyDispatchersProvider.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.threading 2 | 3 | import kotlinx.coroutines.Dispatchers 4 | import javax.inject.Inject 5 | import kotlin.coroutines.CoroutineContext 6 | 7 | class IvyDispatchersProvider @Inject constructor() : DispatchersProvider { 8 | override val main: CoroutineContext = Dispatchers.Main 9 | override val io: CoroutineContext = Dispatchers.IO 10 | override val default: CoroutineContext = Dispatchers.Default 11 | } -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/time/TimeConversionExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.time 2 | 3 | import java.time.Instant 4 | import java.time.ZoneId 5 | import java.time.ZonedDateTime 6 | 7 | @Deprecated("Use the TimeConverter interface via DI") 8 | fun Instant.convertToLocal(): ZonedDateTime { 9 | return atZone(ZoneId.systemDefault()) 10 | } 11 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/time/TimeConverter.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.time 2 | 3 | import java.time.Instant 4 | import java.time.LocalDate 5 | import java.time.LocalDateTime 6 | import java.time.LocalTime 7 | 8 | interface TimeConverter { 9 | fun Instant.toLocalDateTime(): LocalDateTime 10 | fun Instant.toLocalDate(): LocalDate 11 | fun Instant.toLocalTime(): LocalTime 12 | 13 | fun LocalDateTime.toUTC(): Instant 14 | } -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/time/TimeProvider.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.time 2 | 3 | import java.time.Instant 4 | import java.time.LocalDate 5 | import java.time.LocalDateTime 6 | import java.time.LocalTime 7 | import java.time.ZoneId 8 | 9 | interface TimeProvider { 10 | fun getZoneId(): ZoneId 11 | fun utcNow(): Instant 12 | fun localNow(): LocalDateTime 13 | fun localDateNow(): LocalDate 14 | fun localTimeNow(): LocalTime 15 | } 16 | -------------------------------------------------------------------------------- /shared/base/src/main/java/com/ivy/base/time/TimeRange.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.time 2 | 3 | import java.time.Instant 4 | import java.util.concurrent.TimeUnit 5 | 6 | const val SafeOffsetDays = 365 * 10L 7 | 8 | val INSTANT_MIN_SAFE: Instant 9 | get() = Instant.ofEpochMilli(Long.MIN_VALUE) 10 | .plusSeconds(TimeUnit.DAYS.toSeconds(SafeOffsetDays)) 11 | 12 | val INSTANT_MAX_SAFE: Instant 13 | get() = Instant.ofEpochMilli(Long.MAX_VALUE) 14 | .minusSeconds(TimeUnit.DAYS.toSeconds(SafeOffsetDays)) -------------------------------------------------------------------------------- /shared/base/src/test/java/com/ivy/base/time/impl/DeviceTimeProviderTest.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.base.time.impl 2 | 3 | import org.junit.Before 4 | import org.junit.Test 5 | 6 | class DeviceTimeProviderTest { 7 | 8 | private lateinit var timeProvider: DeviceTimeProvider 9 | 10 | @Before 11 | fun setup() { 12 | timeProvider = DeviceTimeProvider() 13 | } 14 | 15 | @Test 16 | fun `validate no crashes`() { 17 | // When 18 | timeProvider.getZoneId() 19 | timeProvider.utcNow() 20 | timeProvider.localNow() 21 | 22 | // Then 23 | // there are no crashes 24 | } 25 | } -------------------------------------------------------------------------------- /shared/data/core-testing/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | id("ivy.room") 4 | } 5 | 6 | android { 7 | namespace = "com.ivy.data.testing" 8 | } 9 | 10 | dependencies { 11 | implementation(projects.shared.data.core) 12 | } 13 | -------------------------------------------------------------------------------- /shared/data/core/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | id("ivy.room") 4 | id("ivy.integration.testing") 5 | } 6 | 7 | android { 8 | namespace = "com.ivy.data" 9 | } 10 | 11 | dependencies { 12 | implementation(projects.shared.base) 13 | api(projects.shared.data.model) 14 | 15 | implementation(libs.datastore) 16 | implementation(libs.bundles.ktor) 17 | 18 | testImplementation(projects.shared.data.modelTesting) 19 | androidTestImplementation(libs.bundles.integration.testing) 20 | } 21 | -------------------------------------------------------------------------------- /shared/data/core/src/androidTest/assets/backups/450-150.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/data/core/src/androidTest/assets/backups/450-150.json -------------------------------------------------------------------------------- /shared/data/core/src/androidTest/assets/backups/450-150.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/data/core/src/androidTest/assets/backups/450-150.zip -------------------------------------------------------------------------------- /shared/data/core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/backup/CSVRow.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.backup 2 | 3 | data class CSVRow( 4 | val index: Int, 5 | val content: List 6 | ) 7 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/backup/ImportResult.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.backup 2 | 3 | import kotlinx.collections.immutable.ImmutableList 4 | 5 | data class ImportResult( 6 | val rowsFound: Int, 7 | val transactionsImported: Int, 8 | val accountsImported: Int, 9 | val categoriesImported: Int, 10 | val failedRows: ImmutableList, 11 | ) 12 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/datastore/Datastore.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.datastore 2 | 3 | import android.content.Context 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.platform.LocalContext 6 | import androidx.datastore.core.DataStore 7 | import androidx.datastore.preferences.core.Preferences 8 | import androidx.datastore.preferences.preferencesDataStore 9 | 10 | val Context.dataStore: DataStore by preferencesDataStore( 11 | name = "ivy_wallet_datastore_v1" 12 | ) 13 | 14 | @Composable 15 | fun datastore(): DataStore { 16 | return LocalContext.current.dataStore 17 | } 18 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/dao/read/AccountDao.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.dao.read 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import com.ivy.data.db.entity.AccountEntity 6 | import java.util.* 7 | 8 | @Dao 9 | interface AccountDao { 10 | @Query("SELECT * FROM accounts WHERE isDeleted = :deleted ORDER BY orderNum ASC") 11 | suspend fun findAll(deleted: Boolean = false): List 12 | 13 | @Query("SELECT * FROM accounts WHERE id = :id") 14 | suspend fun findById(id: UUID): AccountEntity? 15 | 16 | @Query("SELECT MAX(orderNum) FROM accounts") 17 | suspend fun findMaxOrderNum(): Double? 18 | } 19 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/dao/write/WriteAccountDao.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.dao.write 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import androidx.room.Upsert 6 | import com.ivy.data.db.entity.AccountEntity 7 | import java.util.UUID 8 | 9 | @Dao 10 | interface WriteAccountDao { 11 | @Upsert 12 | suspend fun save(value: AccountEntity) 13 | 14 | @Upsert 15 | suspend fun saveMany(values: List) 16 | 17 | @Query("DELETE FROM accounts WHERE id = :id") 18 | suspend fun deleteById(id: UUID) 19 | 20 | @Query("DELETE FROM accounts") 21 | suspend fun deleteAll() 22 | } 23 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/dao/write/WriteBudgetDao.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.dao.write 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import androidx.room.Upsert 6 | import com.ivy.data.db.entity.BudgetEntity 7 | import java.util.UUID 8 | 9 | @Dao 10 | interface WriteBudgetDao { 11 | @Upsert 12 | suspend fun save(value: BudgetEntity) 13 | 14 | @Upsert 15 | suspend fun saveMany(value: List) 16 | 17 | @Query("DELETE FROM budgets WHERE id = :id") 18 | suspend fun deleteById(id: UUID) 19 | 20 | @Query("DELETE FROM budgets") 21 | suspend fun deleteAll() 22 | } 23 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/dao/write/WriteCategoryDao.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.dao.write 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import androidx.room.Upsert 6 | import com.ivy.data.db.entity.CategoryEntity 7 | import java.util.UUID 8 | 9 | @Dao 10 | interface WriteCategoryDao { 11 | @Upsert 12 | suspend fun save(value: CategoryEntity) 13 | 14 | @Upsert 15 | suspend fun saveMany(values: List) 16 | 17 | @Query("DELETE FROM categories WHERE id = :id") 18 | suspend fun deleteById(id: UUID) 19 | 20 | @Query("DELETE FROM categories") 21 | suspend fun deleteAll() 22 | } 23 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/dao/write/WriteLoanDao.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.dao.write 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import androidx.room.Upsert 6 | import com.ivy.data.db.entity.LoanEntity 7 | import java.util.UUID 8 | 9 | @Dao 10 | interface WriteLoanDao { 11 | @Upsert 12 | suspend fun save(value: LoanEntity) 13 | 14 | @Upsert 15 | suspend fun saveMany(value: List) 16 | 17 | @Query("DELETE FROM loans WHERE id = :id") 18 | suspend fun deleteById(id: UUID) 19 | 20 | @Query("DELETE FROM loans") 21 | suspend fun deleteAll() 22 | } 23 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/dao/write/WriteSettingsDao.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.dao.write 2 | 3 | import androidx.room.Dao 4 | import androidx.room.Query 5 | import androidx.room.Upsert 6 | import com.ivy.data.db.entity.SettingsEntity 7 | import java.util.UUID 8 | 9 | @Dao 10 | interface WriteSettingsDao { 11 | @Upsert 12 | suspend fun save(value: SettingsEntity) 13 | 14 | @Upsert 15 | suspend fun saveMany(value: List) 16 | 17 | @Query("DELETE FROM settings WHERE id = :id") 18 | suspend fun deleteById(id: UUID) 19 | 20 | @Query("DELETE FROM settings") 21 | suspend fun deleteAll() 22 | } 23 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration108to109_Users.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration108to109_Users : Migration(108, 109) { 7 | override fun migrate(database: SupportSQLiteDatabase) { 8 | database.execSQL( 9 | "CREATE TABLE IF NOT EXISTS `users` (`email` TEXT NOT NULL, `authProviderType` TEXT NOT NULL, `firstName` TEXT NOT NULL, `lastName` TEXT, `profilePicture` TEXT, `color` INTEGER NOT NULL, `id` TEXT NOT NULL, PRIMARY KEY(`id`))" 10 | ) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration111to112_User_testUser.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration111to112_User_testUser : Migration(111, 112) { 7 | override fun migrate(database: SupportSQLiteDatabase) { 8 | database.execSQL("ALTER TABLE users ADD COLUMN testUser INTEGER NOT NULL DEFAULT 0") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration112to113_ExchangeRates.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration112to113_ExchangeRates : Migration(112, 113) { 7 | override fun migrate(database: SupportSQLiteDatabase) { 8 | database.execSQL( 9 | "CREATE TABLE IF NOT EXISTS `exchange_rates` (`baseCurrency` TEXT NOT NULL, `currency` TEXT NOT NULL, `rate` REAL NOT NULL, PRIMARY KEY(`baseCurrency`, `currency`))" 10 | ) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration113to114_Multi_Currency.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration113to114_Multi_Currency : Migration(113, 114) { 7 | override fun migrate(database: SupportSQLiteDatabase) { 8 | database.execSQL("ALTER TABLE accounts ADD COLUMN currency TEXT") 9 | database.execSQL("ALTER TABLE transactions ADD COLUMN toAmount REAL") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration114to115_Category_Account_Icons.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration114to115_Category_Account_Icons : Migration(114, 115) { 7 | override fun migrate(database: SupportSQLiteDatabase) { 8 | database.execSQL("ALTER TABLE accounts ADD COLUMN icon TEXT") 9 | database.execSQL("ALTER TABLE categories ADD COLUMN icon TEXT") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration115to116_Account_Include_In_Balance.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration115to116_Account_Include_In_Balance : Migration(115, 116) { 7 | override fun migrate(database: SupportSQLiteDatabase) { 8 | database.execSQL("ALTER TABLE accounts ADD COLUMN includeInBalance INTEGER NOT NULL DEFAULT 1") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration120to121_DropWishlistItem.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration120to121_DropWishlistItem : Migration(120, 121) { 7 | override fun migrate(database: SupportSQLiteDatabase) { 8 | database.execSQL("DROP TABLE wishlist_items") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration122to123_ExchangeRates.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration122to123_ExchangeRates : Migration(122, 123) { 7 | override fun migrate(database: SupportSQLiteDatabase) { 8 | database.execSQL("ALTER TABLE exchange_rates ADD COLUMN manualOverride INTEGER NOT NULL DEFAULT 0") 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration123to124_LoanIncludeDateTime.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration123to124_LoanIncludeDateTime : Migration(123, 124) { 7 | override fun migrate(db: SupportSQLiteDatabase) { 8 | db.execSQL("ALTER TABLE loans ADD COLUMN dateTime INTEGER NOT NULL DEFAULT 0") 9 | } 10 | } -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration126to127_LoanRecordType.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | @Suppress("MagicNumber", "ClassNaming") 7 | class Migration126to127_LoanRecordType : Migration(126, 127) { 8 | override fun migrate(db: SupportSQLiteDatabase) { 9 | db.execSQL("ALTER TABLE loan_records ADD COLUMN loanRecordType TEXT NOT NULL DEFAULT 'DECREASE'") 10 | } 11 | } -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration127to128_PaidForDateRecord.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | @Suppress("MagicNumber", "ClassNaming") 7 | class Migration127to128_PaidForDateRecord : Migration(127, 128) { 8 | override fun migrate(database: SupportSQLiteDatabase) { 9 | database.execSQL("ALTER TABLE transactions ADD COLUMN paidForDateTime INTEGER") 10 | } 11 | } -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/db/migration/Migration129to130_LoanIncludeNote.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.db.migration 2 | 3 | import androidx.room.migration.Migration 4 | import androidx.sqlite.db.SupportSQLiteDatabase 5 | 6 | class Migration129to130_LoanIncludeNote : Migration(129, 130) { 7 | override fun migrate(db: SupportSQLiteDatabase) { 8 | db.execSQL("ALTER TABLE loans ADD COLUMN note TEXT") 9 | } 10 | } -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/di/RemoteDataSourceModule.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.di 2 | 3 | import com.ivy.data.remote.RemoteExchangeRatesDataSource 4 | import com.ivy.data.remote.impl.RemoteExchangeRatesDataSourceImpl 5 | import dagger.Binds 6 | import dagger.Module 7 | import dagger.hilt.InstallIn 8 | import dagger.hilt.components.SingletonComponent 9 | 10 | @Module 11 | @InstallIn(SingletonComponent::class) 12 | abstract class RemoteDataSourceModule { 13 | @Binds 14 | abstract fun bindExchangeRatesDataSource( 15 | datasource: RemoteExchangeRatesDataSourceImpl 16 | ): RemoteExchangeRatesDataSource 17 | } 18 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/remote/RemoteExchangeRatesDataSource.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.remote 2 | 3 | import arrow.core.Either 4 | import com.ivy.data.remote.responses.ExchangeRatesResponse 5 | 6 | interface RemoteExchangeRatesDataSource { 7 | suspend fun fetchEurExchangeRates(): Either 8 | } 9 | -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/remote/responses/ExchangeRatesResponse.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.remote.responses 2 | 3 | import androidx.annotation.Keep 4 | import kotlinx.serialization.SerialName 5 | import kotlinx.serialization.Serializable 6 | 7 | @Serializable 8 | @Keep 9 | data class ExchangeRatesResponse( 10 | val date: String, 11 | @SerialName("eur") 12 | val rates: Map 13 | ) -------------------------------------------------------------------------------- /shared/data/core/src/main/java/com/ivy/data/repository/fake/FakeRepositoryMemo.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.repository.fake 2 | 3 | import com.ivy.base.TestDispatchersProvider 4 | import com.ivy.data.DataObserver 5 | import com.ivy.data.repository.RepositoryMemoFactory 6 | import org.jetbrains.annotations.VisibleForTesting 7 | 8 | @VisibleForTesting 9 | fun fakeRepositoryMemoFactory(): RepositoryMemoFactory = RepositoryMemoFactory( 10 | dataObserver = DataObserver(), 11 | dispatchers = TestDispatchersProvider 12 | ) -------------------------------------------------------------------------------- /shared/data/core/src/test/resources/backups/450-150.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/data/core/src/test/resources/backups/450-150.json -------------------------------------------------------------------------------- /shared/data/model-testing/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.data.model.testing" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.data.model) 11 | 12 | implementation(libs.bundles.testing) 13 | } -------------------------------------------------------------------------------- /shared/data/model-testing/src/main/java/com/ivy/data/model/testing/ModelFixtures.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model.testing 2 | 3 | import com.ivy.data.model.AccountId 4 | import com.ivy.data.model.CategoryId 5 | import com.ivy.data.model.TransactionId 6 | import java.util.UUID 7 | 8 | object ModelFixtures { 9 | val AccountId = AccountId(UUID.randomUUID()) 10 | val CategoryId = CategoryId(UUID.randomUUID()) 11 | val TransactionId = TransactionId(UUID.randomUUID()) 12 | } 13 | -------------------------------------------------------------------------------- /shared/data/model/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.data.model" 7 | } -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/ExchangeRate.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model 2 | 3 | import com.ivy.data.model.primitive.AssetCode 4 | import com.ivy.data.model.primitive.PositiveDouble 5 | 6 | data class ExchangeRate( 7 | val baseCurrency: AssetCode, 8 | val currency: AssetCode, 9 | val rate: PositiveDouble, 10 | val manualOverride: Boolean, 11 | ) 12 | -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/Reorderable.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model 2 | 3 | /** 4 | * Indicates that the item can be reordered by the user. 5 | * For the reordering to happen efficiently the item must have an [orderNum]. 6 | */ 7 | interface Reorderable { 8 | val orderNum: Double 9 | } 10 | -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/Value.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model 2 | 3 | import com.ivy.data.model.primitive.AssetCode 4 | import com.ivy.data.model.primitive.NonZeroDouble 5 | import com.ivy.data.model.primitive.PositiveDouble 6 | 7 | /** 8 | * Represents monetary value. (like 10 USD, 5 EUR, 0.005 BTC, 12 GOLD_GRAM) 9 | */ 10 | data class PositiveValue( 11 | val amount: PositiveDouble, 12 | val asset: AssetCode, 13 | ) 14 | 15 | data class Value( 16 | val amount: NonZeroDouble, 17 | val asset: AssetCode, 18 | ) -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/primitive/AssociationId.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model.primitive 2 | 3 | import com.ivy.data.model.sync.UniqueId 4 | import java.util.UUID 5 | 6 | @JvmInline 7 | value class AssociationId(override val value: UUID) : UniqueId -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/primitive/ColorInt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model.primitive 2 | 3 | @JvmInline 4 | value class ColorInt(val value: Int) 5 | -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/primitive/PositiveInt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model.primitive 2 | 3 | import arrow.core.raise.Raise 4 | import arrow.core.raise.ensure 5 | import com.ivy.data.model.exact.Exact 6 | 7 | @JvmInline 8 | value class PositiveInt private constructor(val value: Int) { 9 | companion object : Exact { 10 | override val exactName = "PositiveInt" 11 | 12 | override fun Raise.spec(raw: Int): PositiveInt { 13 | ensure(raw > 0) { "$raw is not > 0" } 14 | return PositiveInt(raw) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/sync/Identifiable.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model.sync 2 | 3 | interface Identifiable { 4 | val id: ID 5 | } 6 | -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/sync/UniqueId.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model.sync 2 | 3 | import java.util.UUID 4 | 5 | interface UniqueId { 6 | val value: UUID 7 | } 8 | -------------------------------------------------------------------------------- /shared/data/model/src/main/kotlin/com/ivy/data/model/util/ValueRounding.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.data.model.util 2 | 3 | import com.ivy.data.model.PositiveValue 4 | import com.ivy.data.model.primitive.PositiveDouble 5 | import java.math.BigDecimal 6 | import java.math.RoundingMode 7 | 8 | fun PositiveValue.round(decimalPlaces: Int): PositiveValue = PositiveValue( 9 | amount = PositiveDouble.unsafe(amount.value.roundTo(decimalPlaces)), 10 | asset = asset, 11 | ) 12 | 13 | fun Double.roundTo(decimalPlaces: Int): Double { 14 | return BigDecimal(this).setScale(decimalPlaces, RoundingMode.HALF_EVEN).toDouble() 15 | } -------------------------------------------------------------------------------- /shared/domain/src/main/java/com/ivy/domain/AppStarter.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain 2 | 3 | import android.content.Intent 4 | import com.ivy.base.model.TransactionType 5 | 6 | /** 7 | * A component used to start the **RootActivity** without knowing about it. 8 | */ 9 | interface AppStarter { 10 | fun getRootIntent(): Intent 11 | fun defaultStart() 12 | fun addTransactionStart(type: TransactionType) 13 | } 14 | -------------------------------------------------------------------------------- /shared/domain/src/main/java/com/ivy/domain/features/FeatureGroup.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.features 2 | 3 | enum class FeatureGroup { 4 | Category, Account, Other 5 | } -------------------------------------------------------------------------------- /shared/domain/src/main/java/com/ivy/domain/features/Features.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.features 2 | 3 | interface Features { 4 | val sortCategoriesAscending: BoolFeature 5 | val compactAccountsMode: BoolFeature 6 | val compactCategoriesMode: BoolFeature 7 | val showTitleSuggestions: BoolFeature 8 | val showCategorySearchBar: BoolFeature 9 | val hideTotalBalance: BoolFeature 10 | val showDecimalNumber: BoolFeature 11 | val standardKeypadLayout: BoolFeature 12 | val showAccountColorsInTransactions: BoolFeature 13 | 14 | val allFeatures: List 15 | } 16 | -------------------------------------------------------------------------------- /shared/domain/src/main/java/com/ivy/domain/model/StatSummary.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.model 2 | 3 | import com.ivy.data.model.primitive.AssetCode 4 | import com.ivy.data.model.primitive.NonNegativeInt 5 | import com.ivy.data.model.primitive.PositiveDouble 6 | 7 | data class StatSummary( 8 | val trnCount: NonNegativeInt, 9 | val values: Map, 10 | ) { 11 | companion object { 12 | val Zero = StatSummary( 13 | values = emptyMap(), 14 | trnCount = NonNegativeInt.Zero 15 | ) 16 | } 17 | } -------------------------------------------------------------------------------- /shared/domain/src/main/java/com/ivy/domain/model/TimeRange.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.model 2 | 3 | import java.time.Instant 4 | 5 | sealed interface TimeRange { 6 | data object AllTime : TimeRange 7 | 8 | /** 9 | * @param time before this point in time (inclusive) 10 | */ 11 | data class Before(val time: Instant) : TimeRange 12 | 13 | /** 14 | * @param time after this point in time (inclusive) 15 | */ 16 | data class After(val time: Instant) : TimeRange 17 | } -------------------------------------------------------------------------------- /shared/domain/src/test/java/com/ivy/domain/model/StatSummaryAssertion.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.domain.model 2 | 3 | import com.ivy.data.model.testing.shouldBeApprox 4 | import io.kotest.matchers.shouldBe 5 | 6 | infix fun StatSummary.shouldBeApprox(other: StatSummary) { 7 | trnCount shouldBe other.trnCount 8 | values.keys shouldBe other.values.keys 9 | values.keys.forEach { key -> 10 | values[key]!!.value shouldBeApprox other.values[key]!!.value 11 | } 12 | } -------------------------------------------------------------------------------- /shared/ui/core/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.ui" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | } -------------------------------------------------------------------------------- /shared/ui/core/src/main/java/com/ivy/design/system/colors/ColorShades.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.design.system.colors 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | data class ColorShades( 6 | val extraLight: Color, 7 | val light: Color, 8 | val kindaLight: Color, 9 | val primary: Color, 10 | val kindaDark: Color, 11 | val dark: Color, 12 | val extraDark: Color, 13 | ) 14 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/java/com/ivy/ui/time/DevicePreferences.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.ui.time 2 | 3 | import java.util.Locale 4 | 5 | interface DevicePreferences { 6 | fun is24HourFormat(): Boolean 7 | fun locale(): Locale 8 | } -------------------------------------------------------------------------------- /shared/ui/core/src/main/java/com/ivy/ui/time/impl/AndroidDevicePreferences.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.ui.time.impl 2 | 3 | import android.content.Context 4 | import android.text.format.DateFormat 5 | import com.ivy.ui.time.DevicePreferences 6 | import dagger.hilt.android.qualifiers.ApplicationContext 7 | import java.util.Locale 8 | import javax.inject.Inject 9 | 10 | class AndroidDevicePreferences @Inject constructor( 11 | @ApplicationContext 12 | private val context: Context, 13 | ) : DevicePreferences { 14 | override fun is24HourFormat(): Boolean = DateFormat.is24HourFormat(context) 15 | override fun locale(): Locale = Locale.getDefault() 16 | } -------------------------------------------------------------------------------- /shared/ui/core/src/main/java/com/ivy/ui/time/impl/DateTimePicker.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.ui.time.impl 2 | 3 | import androidx.compose.runtime.Composable 4 | import androidx.compose.runtime.Stable 5 | import java.time.Instant 6 | import java.time.LocalDate 7 | import java.time.LocalTime 8 | 9 | @Stable 10 | interface DateTimePicker { 11 | @Composable 12 | fun Content() 13 | 14 | fun pickDate( 15 | initialDate: Instant?, 16 | onDatePick: (LocalDate) -> Unit 17 | ) 18 | 19 | fun pickTime( 20 | initialTime: LocalTime?, 21 | onTimePick: (LocalTime) -> Unit 22 | ) 23 | } -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable-nodpi/donate_illustration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable-nodpi/donate_illustration.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable-nodpi/ivywallet_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable-nodpi/ivywallet_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable-nodpi/monefy_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable-nodpi/monefy_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable-nodpi/moneymanager_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable-nodpi/moneymanager_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable-nodpi/spendee_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable-nodpi/spendee_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable-nodpi/wallet_by_budgetbakers_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable-nodpi/wallet_by_budgetbakers_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/bluecoins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/bluecoins.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/expense_shape_widget_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/financisto_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/financisto_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/fortune_city_app_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/fortune_city_app_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_arrow_right.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_attachment.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_category_edit.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_custom_xrp_l.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_custom_xrp_m.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_custom_xrp_s.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_done.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_expand_less.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_expand_more.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_file.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_filter_l.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_filter_xs.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_hamburger.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_outline_clear_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_popup_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_priority_dropdown.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_recurring_upcoming.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_refresh.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_remove.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_sort_by_alpha_24.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_statistics_s.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_statistics_xs.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_telegram_24dp.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_time_tracking_play.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_visible.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_vue_crypto_thorchain.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_vue_files_folder.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_vue_main_timer.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ic_vue_weather_drop.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/income_shape_widget_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/ktw_money_manager_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/ktw_money_manager_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/onboarding_illustration_accounts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/onboarding_illustration_accounts.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/onboarding_illustration_categories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/onboarding_illustration_categories.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/onboarding_illustration_import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/onboarding_illustration_import.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/one_money_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/one_money_logo.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/preview_widget_add_trn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/preview_widget_add_trn.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/preview_widget_add_trn_compact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/preview_widget_add_trn_compact.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/preview_widget_wallet_balance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/preview_widget_wallet_balance.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/questions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/drawable/questions.png -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/drawable/shape_widget_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_bold.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_bolditalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_extrabold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_extrabold.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_extrabolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_extrabolditalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_italic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_light.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_lightitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_lightitalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_regular.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_semibold.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/opensans_semibolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/opensans_semibolditalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_black.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_blackitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_blackitalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_bold.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_bolditalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_extrabold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_extrabold.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_extrabolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_extrabolditalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_extralight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_extralight.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_extralightitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_extralightitalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_italic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_light.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_lightitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_lightitalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_medium.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_mediumitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_mediumitalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_regular.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_semibold.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_semibolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_semibolditalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_thin.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/main/res/font/raleway_thinitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/main/res/font/raleway_thinitalic.ttf -------------------------------------------------------------------------------- /shared/ui/core/src/test/snapshots/images/com.ivy.ui.component_OpenSourceCardPaparazziTest_default state[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/test/snapshots/images/com.ivy.ui.component_OpenSourceCardPaparazziTest_default state[Dark].png -------------------------------------------------------------------------------- /shared/ui/core/src/test/snapshots/images/com.ivy.ui.component_OpenSourceCardPaparazziTest_default state[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/core/src/test/snapshots/images/com.ivy.ui.component_OpenSourceCardPaparazziTest_default state[Light].png -------------------------------------------------------------------------------- /shared/ui/navigation/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.navigation" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | implementation(projects.shared.ui.core) 13 | } 14 | -------------------------------------------------------------------------------- /shared/ui/navigation/src/main/java/com/ivy/navigation/IvyPreview.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.navigation 2 | 3 | import androidx.compose.runtime.Composable 4 | import com.ivy.design.system.IvyMaterial3Theme 5 | 6 | @Composable 7 | fun IvyPreview( 8 | dark: Boolean = false, 9 | content: @Composable () -> Unit, 10 | ) { 11 | NavigationRoot(navigation = Navigation()) { 12 | IvyMaterial3Theme(dark = dark, isTrueBlack = false, content = content) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /shared/ui/navigation/src/main/java/com/ivy/navigation/Screen.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.navigation 2 | 3 | /** 4 | * Marks a screen in the Ivy Wallet's navigation graph. 5 | * Extend it when creating a new screen. 6 | */ 7 | sealed interface Screen { 8 | /** 9 | * Marks whether a given screen is a legacy Ivy Wallet one. 10 | * If it's a legacy screen, it automatically adds a Surface to make it work. 11 | * Do NOT mark new Material3 screens as legacy. 12 | */ 13 | val isLegacy: Boolean 14 | get() = false 15 | } 16 | -------------------------------------------------------------------------------- /shared/ui/testing/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.ui.testing" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.ui.core) 11 | 12 | // for this module we need test deps as "implementation" and not only "testImplementation" 13 | // because it'll be added as "testImplementation" 14 | implementation(libs.bundles.testing) 15 | implementation(libs.paparazzi) 16 | } 17 | -------------------------------------------------------------------------------- /shared/ui/testing/src/test/snapshots/images/com.ivy.ui.testing_DemoPaparazziTest_snapshot demo composable[Dark].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/testing/src/test/snapshots/images/com.ivy.ui.testing_DemoPaparazziTest_snapshot demo composable[Dark].png -------------------------------------------------------------------------------- /shared/ui/testing/src/test/snapshots/images/com.ivy.ui.testing_DemoPaparazziTest_snapshot demo composable[Light].png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/shared/ui/testing/src/test/snapshots/images/com.ivy.ui.testing_DemoPaparazziTest_snapshot demo composable[Light].png -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/LoanExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy 2 | 3 | import com.ivy.base.legacy.stringRes 4 | import com.ivy.data.model.LoanType 5 | import com.ivy.legacy.datamodel.Loan 6 | import com.ivy.ui.R 7 | 8 | fun Loan.humanReadableType(): String { 9 | return if (type == LoanType.BORROW) { 10 | stringRes(R.string.borrowed_uppercase) 11 | } else { 12 | stringRes(R.string.lent_uppercase) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/android/notification/IvyNotification.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.android.notification 2 | 3 | import android.content.Context 4 | import androidx.core.app.NotificationCompat 5 | 6 | class IvyNotification( 7 | context: Context, 8 | val ivyChannel: IvyNotificationChannel 9 | ) : NotificationCompat.Builder(context, ivyChannel.channelId) 10 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/data/AppBaseData.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.data 2 | 3 | import androidx.compose.runtime.Immutable 4 | import com.ivy.data.model.Category 5 | import com.ivy.legacy.datamodel.Account 6 | import kotlinx.collections.immutable.ImmutableList 7 | 8 | @Immutable 9 | data class AppBaseData( 10 | val baseCurrency: String, 11 | val accounts: ImmutableList, 12 | val categories: ImmutableList 13 | ) 14 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/data/BufferInfo.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.data 2 | 3 | import androidx.compose.runtime.Immutable 4 | import java.math.BigDecimal 5 | 6 | @Immutable 7 | data class BufferInfo( 8 | val amount: BigDecimal, 9 | val bufferDiff: BigDecimal 10 | ) 11 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/data/EditTransactionDisplayLoan.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.data 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Immutable 6 | data class EditTransactionDisplayLoan( 7 | val isLoan: Boolean = false, 8 | val isLoanRecord: Boolean = false, 9 | val loanCaption: String? = null, 10 | val loanWarningDescription: String = "" 11 | ) 12 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/data/model/AccountBalance.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.data.model 2 | 3 | import androidx.compose.runtime.Immutable 4 | import com.ivy.legacy.datamodel.Account 5 | 6 | @Immutable 7 | data class AccountBalance( 8 | val account: Account, 9 | val balance: Double 10 | ) 11 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/data/model/MainTab.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.data.model 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Immutable 6 | enum class MainTab { 7 | HOME, ACCOUNTS 8 | } 9 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/datamodel/ExchangeRate.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.datamodel 2 | 3 | import androidx.compose.runtime.Immutable 4 | import com.ivy.data.db.entity.ExchangeRateEntity 5 | 6 | @Deprecated("Legacy data model. Will be deleted") 7 | @Immutable 8 | data class ExchangeRate( 9 | val baseCurrency: String, 10 | val currency: String, 11 | val rate: Double, 12 | ) { 13 | fun toEntity(): ExchangeRateEntity = ExchangeRateEntity( 14 | baseCurrency = baseCurrency, 15 | currency = currency, 16 | rate = rate 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/datamodel/temp/AccountExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.datamodel.temp 2 | 3 | import com.ivy.data.db.entity.AccountEntity 4 | import com.ivy.legacy.datamodel.Account 5 | 6 | fun AccountEntity.toLegacyDomain(): Account = Account( 7 | name = name, 8 | currency = currency, 9 | color = color, 10 | icon = icon, 11 | orderNum = orderNum, 12 | includeInBalance = includeInBalance, 13 | isSynced = isSynced, 14 | isDeleted = isDeleted, 15 | id = id 16 | ) 17 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/datamodel/temp/CategoryExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.datamodel.temp 2 | 3 | import com.ivy.data.db.entity.CategoryEntity 4 | import com.ivy.legacy.datamodel.Category 5 | 6 | fun CategoryEntity.toLegacyDomain(): Category = Category( 7 | name = name, 8 | color = color, 9 | icon = icon, 10 | orderNum = orderNum, 11 | isSynced = isSynced, 12 | isDeleted = isDeleted, 13 | id = id 14 | ) 15 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/datamodel/temp/ExchangeRateExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.datamodel.temp 2 | 3 | import com.ivy.data.db.entity.ExchangeRateEntity 4 | import com.ivy.legacy.datamodel.ExchangeRate 5 | 6 | fun ExchangeRateEntity.toLegacyDomain(): ExchangeRate = ExchangeRate( 7 | baseCurrency = baseCurrency, 8 | currency = currency, 9 | rate = rate 10 | ) 11 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/datamodel/temp/LoanRecordExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.datamodel.temp 2 | 3 | import com.ivy.data.db.entity.LoanRecordEntity 4 | import com.ivy.legacy.datamodel.LoanRecord 5 | 6 | fun LoanRecordEntity.toLegacyDomain(): LoanRecord = LoanRecord( 7 | loanId = loanId, 8 | amount = amount, 9 | note = note, 10 | dateTime = dateTime, 11 | interest = interest, 12 | accountId = accountId, 13 | convertedAmount = convertedAmount, 14 | loanRecordType = loanRecordType, 15 | isSynced = isSynced, 16 | isDeleted = isDeleted, 17 | id = id 18 | ) 19 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/datamodel/temp/SettingsExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.datamodel.temp 2 | 3 | import com.ivy.data.db.entity.SettingsEntity 4 | import com.ivy.legacy.datamodel.Settings 5 | 6 | fun SettingsEntity.toLegacyDomain(): Settings = Settings( 7 | theme = theme, 8 | baseCurrency = currency, 9 | bufferAmount = bufferAmount.toBigDecimal(), 10 | name = name, 11 | id = id 12 | ) 13 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/action/loan/LoanByIdAct.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.action.loan 2 | 3 | import com.ivy.data.db.dao.read.LoanDao 4 | import com.ivy.frp.action.FPAction 5 | import com.ivy.legacy.datamodel.Loan 6 | import com.ivy.legacy.datamodel.temp.toLegacyDomain 7 | import java.util.UUID 8 | import javax.inject.Inject 9 | 10 | class LoanByIdAct @Inject constructor( 11 | private val loanDao: LoanDao 12 | ) : FPAction() { 13 | override suspend fun UUID.compose(): suspend () -> Loan? = suspend { 14 | loanDao.findById(this)?.toLegacyDomain() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/action/settings/BaseCurrencyAct.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.action.settings 2 | 3 | import com.ivy.data.db.dao.read.SettingsDao 4 | import com.ivy.frp.action.FPAction 5 | import javax.inject.Inject 6 | 7 | class BaseCurrencyAct @Inject constructor( 8 | private val settingsDao: SettingsDao 9 | ) : FPAction() { 10 | override suspend fun Unit.compose(): suspend () -> String = suspend { 11 | io { settingsDao.findFirst().currency } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/action/settings/CalcBufferDiffAct.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.action.settings 2 | 3 | import com.ivy.frp.action.FPAction 4 | import java.math.BigDecimal 5 | import javax.inject.Inject 6 | 7 | class CalcBufferDiffAct @Inject constructor() : FPAction() { 8 | 9 | override suspend fun Input.compose(): suspend () -> BigDecimal = { 10 | balance - buffer 11 | } 12 | 13 | data class Input( 14 | val balance: BigDecimal, 15 | val buffer: BigDecimal 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/action/settings/UpdateSettingsAct.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.domain.action.settings 2 | 3 | import com.ivy.data.db.dao.write.WriteSettingsDao 4 | import com.ivy.frp.action.FPAction 5 | import com.ivy.legacy.datamodel.Settings 6 | import javax.inject.Inject 7 | 8 | class UpdateSettingsAct @Inject constructor( 9 | private val writeSettingsDao: WriteSettingsDao 10 | ) : FPAction() { 11 | override suspend fun Settings.compose(): suspend () -> Settings = suspend { 12 | writeSettingsDao.save(this.toEntity()) 13 | this 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/action/transaction/AllTrnsAct.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.action.transaction 2 | 3 | import com.ivy.data.model.Transaction 4 | import com.ivy.data.repository.TransactionRepository 5 | import com.ivy.frp.action.FPAction 6 | import javax.inject.Inject 7 | 8 | class AllTrnsAct @Inject constructor( 9 | private val transactionRepository: TransactionRepository 10 | ) : FPAction>() { 11 | override suspend fun Unit.compose(): suspend () -> List = suspend { 12 | transactionRepository.findAll() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/action/viewmodel/home/HasTrnsAct.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.action.viewmodel.home 2 | 3 | import com.ivy.data.db.dao.read.TransactionDao 4 | import com.ivy.frp.action.FPAction 5 | import javax.inject.Inject 6 | 7 | class HasTrnsAct @Inject constructor( 8 | private val transactionDao: TransactionDao 9 | ) : FPAction() { 10 | override suspend fun Unit.compose(): suspend () -> Boolean = suspend { 11 | io { 12 | transactionDao.findAll_LIMIT_1().isNotEmpty() 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/action/viewmodel/home/ShouldHideBalanceAct.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.action.viewmodel.home 2 | 3 | import com.ivy.frp.action.FPAction 4 | import com.ivy.base.legacy.SharedPrefs 5 | import javax.inject.Inject 6 | 7 | class ShouldHideBalanceAct @Inject constructor( 8 | private val sharedPrefs: SharedPrefs 9 | ) : FPAction() { 10 | override suspend fun Unit.compose(): suspend () -> Boolean = { 11 | sharedPrefs.getBoolean( 12 | SharedPrefs.HIDE_CURRENT_BALANCE, 13 | false 14 | ) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/action/viewmodel/home/ShouldHideIncomeAct.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.domain.action.viewmodel.home 2 | 3 | import com.ivy.frp.action.FPAction 4 | import com.ivy.base.legacy.SharedPrefs 5 | import javax.inject.Inject 6 | 7 | class ShouldHideIncomeAct @Inject constructor( 8 | private val sharedPrefs: SharedPrefs 9 | ) : FPAction() { 10 | override suspend fun Unit.compose(): suspend () -> Boolean = { 11 | sharedPrefs.getBoolean( 12 | SharedPrefs.HIDE_INCOME, 13 | false 14 | ) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/data/CustomExchangeRateState.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.data 2 | 3 | import androidx.compose.runtime.Immutable 4 | 5 | @Immutable 6 | data class CustomExchangeRateState( 7 | val showCard: Boolean = false, 8 | val toCurrencyCode: String? = null, 9 | val fromCurrencyCode: String? = null, 10 | val exchangeRate: Double = 1.0, 11 | val convertedAmount: Double? = null 12 | ) 13 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/data/Reorderable.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.data 2 | 3 | interface Reorderable { 4 | fun getItemOrderNum(): Double 5 | 6 | fun withNewOrderNum(newOrderNum: Double): Reorderable 7 | } 8 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/data/SortOrder.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.data 2 | 3 | enum class SortOrder(val orderNum: Int, val displayName: String) { 4 | DEFAULT(0, "Default"), 5 | BALANCE_AMOUNT(1, "Balance Amount"), 6 | EXPENSES(2, "Expenses"), 7 | ALPHABETICAL(3, "Alphabetical"); 8 | 9 | companion object { 10 | fun from(orderNum: Int): SortOrder { 11 | return values().firstOrNull { it.orderNum == orderNum } ?: DEFAULT 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/data/TransactionHistoryDateDivider.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.data 2 | 3 | import androidx.compose.runtime.Immutable 4 | import com.ivy.base.legacy.TransactionHistoryItem 5 | import java.time.LocalDate 6 | 7 | @Immutable 8 | data class TransactionHistoryDateDivider( 9 | val date: LocalDate, 10 | val income: Double, 11 | val expenses: Double 12 | ) : TransactionHistoryItem 13 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/deprecated/logic/model/CreateAccountData.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.deprecated.logic.model 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | data class CreateAccountData( 6 | val name: String, 7 | val currency: String, 8 | val color: Color, 9 | val icon: String?, 10 | val balance: Double, 11 | val includeBalance: Boolean = true, 12 | ) 13 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/deprecated/logic/model/CreateBudgetData.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.deprecated.logic.model 2 | 3 | data class CreateBudgetData( 4 | val name: String, 5 | val amount: Double, 6 | val categoryIdsSerialized: String, 7 | val accountIdsSerialized: String 8 | ) 9 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/deprecated/logic/model/CreateCategoryData.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.deprecated.logic.model 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | data class CreateCategoryData( 6 | val name: String, 7 | val color: Color, 8 | val icon: String? 9 | ) 10 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/deprecated/logic/model/CreateLoanData.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.deprecated.logic.model 2 | 3 | import androidx.compose.ui.graphics.Color 4 | import com.ivy.data.model.LoanType 5 | import com.ivy.legacy.datamodel.Account 6 | import java.time.LocalDateTime 7 | 8 | data class CreateLoanData( 9 | val name: String, 10 | val amount: Double, 11 | val type: LoanType, 12 | val color: Color, 13 | val icon: String?, 14 | val account: Account? = null, 15 | val note: String?, 16 | val createLoanTransaction: Boolean = false, 17 | val dateTime: LocalDateTime 18 | ) 19 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/deprecated/logic/model/CreateLoanRecordData.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.deprecated.logic.model 2 | 3 | import com.ivy.base.model.LoanRecordType 4 | import com.ivy.legacy.datamodel.Account 5 | import java.time.Instant 6 | 7 | data class CreateLoanRecordData( 8 | val note: String?, 9 | val amount: Double, 10 | val dateTime: Instant, 11 | val interest: Boolean = false, 12 | val account: Account? = null, 13 | val createLoanRecordTransaction: Boolean = false, 14 | val convertedAmount: Double? = null, 15 | val loanRecordType: LoanRecordType 16 | ) 17 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/deprecated/logic/model/EditLoanRecordData.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.deprecated.logic.model 2 | 3 | import com.ivy.legacy.datamodel.LoanRecord 4 | 5 | data class EditLoanRecordData( 6 | val newLoanRecord: LoanRecord, 7 | val originalLoanRecord: LoanRecord, 8 | val createLoanRecordTransaction: Boolean = false, 9 | val reCalculateLoanAmount: Boolean = false 10 | ) 11 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/pure/account/AccountFunctions.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.pure.account 2 | 3 | import com.ivy.legacy.datamodel.Account 4 | 5 | fun filterExcluded(accounts: List): List = 6 | accounts.filter { it.includeInBalance } 7 | 8 | fun accountCurrency(account: Account, baseCurrency: String): String = 9 | account.currency ?: baseCurrency 10 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/pure/data/IncomeExpensePair.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.pure.data 2 | 3 | import androidx.compose.runtime.Immutable 4 | import java.math.BigDecimal 5 | 6 | @Immutable 7 | data class IncomeExpensePair( 8 | val income: BigDecimal, 9 | val expense: BigDecimal 10 | ) { 11 | companion object { 12 | fun zero(): IncomeExpensePair = IncomeExpensePair(BigDecimal.ZERO, BigDecimal.ZERO) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/pure/data/IncomeExpenseTransferPair.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.pure.data 2 | 3 | import java.math.BigDecimal 4 | 5 | data class IncomeExpenseTransferPair( 6 | val income: BigDecimal, 7 | val expense: BigDecimal, 8 | val transferIncome: BigDecimal, 9 | val transferExpense: BigDecimal 10 | ) { 11 | companion object { 12 | fun zero(): IncomeExpenseTransferPair = IncomeExpenseTransferPair( 13 | BigDecimal.ZERO, 14 | BigDecimal.ZERO, 15 | BigDecimal.ZERO, 16 | BigDecimal.ZERO 17 | ) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/pure/data/WalletDAOs.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.pure.data 2 | 3 | import com.ivy.data.db.dao.read.AccountDao 4 | import com.ivy.data.db.dao.read.ExchangeRatesDao 5 | import com.ivy.data.db.dao.read.TransactionDao 6 | import javax.inject.Inject 7 | 8 | data class WalletDAOs @Inject constructor( 9 | val accountDao: AccountDao, 10 | val transactionDao: TransactionDao, 11 | val exchangeRatesDao: ExchangeRatesDao 12 | ) 13 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/domain/pure/util/IvyDomainUtils.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.wallet.domain.pure.util 2 | 3 | fun Double?.nextOrderNum(): Double = this?.plus(1) ?: 0.0 4 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/frp/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.frp 2 | 3 | @Deprecated("Legacy code. Don't use it, please.") 4 | suspend fun List.sumOfSuspend( 5 | selector: suspend (A) -> Double 6 | ): Double { 7 | var sum = 0.0 8 | for (item in this) { 9 | sum += selector(item) 10 | } 11 | return sum 12 | } 13 | 14 | @Deprecated("Legacy code. Don't use it, please.") 15 | suspend fun Collection.filterSuspend( 16 | predicate: suspend (A) -> Boolean 17 | ): Collection { 18 | return this.filter { a -> 19 | predicate(a) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/frp/test/TestingContext.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.frp.test 2 | 3 | @Deprecated("Legacy code. Don't use it, please.") 4 | object TestingContext { 5 | var inTest = false 6 | } 7 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/frp/viewmodel/ViewmodelUtils.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.frp.viewmodel 2 | 3 | import kotlinx.coroutines.flow.MutableStateFlow 4 | import kotlinx.coroutines.flow.StateFlow 5 | 6 | @Deprecated("Legacy code. Don't use it, please.") 7 | fun MutableStateFlow.readOnly(): StateFlow { 8 | return this 9 | } 10 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/utils/InputError.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.utils 2 | 3 | open class InputError(msg: String) : Exception(msg) 4 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/utils/OpResult.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.utils 2 | 3 | sealed class OpResult { 4 | object Loading : OpResult() 5 | data class Success(val data: T) : OpResult() 6 | data class Failure(val exception: Exception) : OpResult() { 7 | fun error() = exception.message ?: exception.cause?.message ?: "unknown" 8 | } 9 | 10 | companion object { 11 | fun success(data: T) = Success(data) 12 | fun loading() = Loading 13 | fun failure(e: Exception) = Failure(e) 14 | fun faliure(errMsg: String) = Failure(Exception(errMsg)) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /temp/legacy-code/src/main/java/com/ivy/legacy/utils/ValidationExt.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.legacy.utils 2 | 3 | fun String?.isNotNullOrBlank(): Boolean { 4 | return this != null && this.isNotBlank() 5 | } 6 | -------------------------------------------------------------------------------- /temp/old-design/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.feature") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.design" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.ui.core) 12 | 13 | implementation(projects.shared.domain) 14 | } -------------------------------------------------------------------------------- /temp/old-design/src/main/java/com/ivy/design/l0_system/IvyTypography.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.design.l0_system 2 | 3 | import androidx.compose.ui.text.TextStyle 4 | 5 | @Deprecated("Old design system. Use `:ivy-design` and Material3") 6 | interface IvyTypography { 7 | val h1: TextStyle 8 | val h2: TextStyle 9 | val b1: TextStyle 10 | val b2: TextStyle 11 | val c: TextStyle 12 | 13 | val nH1: TextStyle 14 | val nH2: TextStyle 15 | val nB1: TextStyle 16 | val nB2: TextStyle 17 | val nC: TextStyle 18 | } 19 | -------------------------------------------------------------------------------- /temp/old-design/src/main/java/com/ivy/design/l1_buildingBlocks/data/IvyPadding.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.design.l1_buildingBlocks.data 2 | 3 | import androidx.compose.ui.unit.Dp 4 | 5 | @Deprecated("Old design system. Use `:ivy-design` and Material3") 6 | data class IvyPadding( 7 | val top: Dp?, 8 | val bottom: Dp?, 9 | val start: Dp?, 10 | val end: Dp? 11 | ) 12 | -------------------------------------------------------------------------------- /temp/old-design/src/main/java/com/ivy/design/utils/Android.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.design.utils 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | 6 | @Deprecated("Old design system. Use `:ivy-design` and Material3") 7 | fun postDelayed(delayMs: Long, run: () -> Unit) { 8 | Handler(Looper.getMainLooper()).postDelayed({ run() }, delayMs) 9 | } 10 | -------------------------------------------------------------------------------- /temp/old-design/src/main/java/com/ivy/design/utils/Animation.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.design.utils 2 | 3 | import androidx.compose.animation.core.spring 4 | 5 | @Deprecated("Old design system. Use `:ivy-design` and Material3") 6 | fun springBounce( 7 | stiffness: Float = 500f, 8 | ) = spring( 9 | dampingRatio = 0.75f, 10 | stiffness = stiffness, 11 | ) 12 | -------------------------------------------------------------------------------- /temp/old-design/src/main/java/com/ivy/design/utils/View.kt: -------------------------------------------------------------------------------- 1 | package com.ivy.design.utils 2 | 3 | import android.content.Context 4 | import android.util.DisplayMetrics 5 | import kotlin.math.roundToInt 6 | 7 | @Deprecated("Old design system. Use `:ivy-design` and Material3") 8 | fun Float.dpToPx(context: Context): Float { 9 | return this * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT) 10 | } 11 | 12 | @Deprecated("Old design system. Use `:ivy-design` and Material3") 13 | fun Int.dpToPx(context: Context): Int { 14 | return this.toFloat().dpToPx(context).roundToInt() 15 | } 16 | -------------------------------------------------------------------------------- /temp/old-design/src/main/res/drawable/ic_android_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /temp/old-design/src/main/res/drawable/ic_baseline_add_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_bold.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_bolditalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_extrabold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_extrabold.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_extrabolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_extrabolditalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_italic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_light.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_lightitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_lightitalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_regular.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_semibold.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/opensans_semibolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/opensans_semibolditalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_black.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_blackitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_blackitalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_bold.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_bolditalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_extrabold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_extrabold.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_extrabolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_extrabolditalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_extralight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_extralight.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_extralightitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_extralightitalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_italic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_light.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_lightitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_lightitalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_medium.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_mediumitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_mediumitalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_regular.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_semibold.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_semibolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_semibolditalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_thin.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/font/raleway_thinitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ivy-Apps/ivy-wallet/2c26ed1703b7308c26121f01c606e0f4cb50b7e4/temp/old-design/src/main/res/font/raleway_thinitalic.ttf -------------------------------------------------------------------------------- /temp/old-design/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFC34CFF 4 | -------------------------------------------------------------------------------- /widget/add-transaction/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.widget") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.widget.transaction" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.base) 12 | implementation(projects.shared.domain) 13 | implementation(projects.shared.ui.core) 14 | implementation(projects.shared.ui.navigation) 15 | 16 | implementation(projects.widget.sharedBase) 17 | } 18 | -------------------------------------------------------------------------------- /widget/add-transaction/src/main/res/drawable/widget_compact_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /widget/add-transaction/src/main/res/xml/add_transaction_widget_compact_info.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /widget/add-transaction/src/main/res/xml/add_transaction_widget_info.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /widget/add-transaction/src/main/res/xml/wallet_balance_widget_info.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /widget/balance/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.widget") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.widget.balance" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | implementation(projects.shared.ui.core) 13 | implementation(projects.shared.ui.navigation) 14 | 15 | implementation(projects.temp.oldDesign) 16 | implementation(projects.widget.sharedBase) 17 | implementation(projects.temp.legacyCode) 18 | } 19 | -------------------------------------------------------------------------------- /widget/shared-base/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("ivy.widget") 3 | } 4 | 5 | android { 6 | namespace = "com.ivy.widget" 7 | } 8 | 9 | dependencies { 10 | implementation(projects.shared.base) 11 | implementation(projects.shared.domain) 12 | } 13 | --------------------------------------------------------------------------------