From f637897dc3f52522978d9a165a2831a5dbdc0807 Mon Sep 17 00:00:00 2001 From: dankito Date: Fri, 11 Feb 2022 23:53:35 +0100 Subject: [PATCH] Removed ui, persistence and rest projects (will be moved to separate repositories) and deactivated tools projects. Removed Android target and using now JVM instead of JVM6. Updated to Kotlin 1.6.10 which works much better for KMPP. Could therefore remove packForXcode() tasks --- build.gradle | 122 +- common/build.gradle | 132 +- common/src/main/AndroidManifest.xml | 5 - fints4k-jvm/build.gradle | 10 - fints4k/build.gradle | 194 +- .../fints/messages/MessageBuilderResult.kt | 2 +- .../banking/fints/webclient/KtorWebClient.kt | 13 +- .../fints/messages/MessageBuilderTest.kt | 2 + .../fints/response/ResponseParserTest.kt | 10 +- .../dankito/banking/fints/JavaShowcase.java | 184 - .../banking/fints/FinTsClientTestBase.kt | 269 - .../bankdetails/BanksFinTsDetailsRetriever.kt | 317 - .../banking/fints/util/JavaThreadPool.kt | 0 .../banking/fints/FinTsClientTestBase.kt | 270 + .../dankito/banking/fints/FinTsTestBaseJvm.kt | 0 .../bankdetails/BanksFinTsDetailsRetriever.kt | 317 + .../fints/response/ResponseParserTestJvm.kt | 2 +- .../Mt940AccountTransactionsParserTest.kt | 2 +- .../fints/transactions/Mt940ParserTestJvm.kt | 2 +- .../resources/logback-test.xml | 0 ..._TanChallengeHhdUc_WithMaskedCharacter.txt | Bin .../test_files/TransactionsMt940.txt | 0 .../test_files/TransactionsMt940_2.txt | 0 fints4k/src/main/AndroidManifest.xml | 7 - gradle.properties | 7 +- .../LuceneBankingPersistence/build.gradle | 30 - .../net/dankito/banking/LuceneConfig.kt | 39 - .../persistence/LuceneBankingPersistence.kt | 109 - .../search/LuceneTransactionPartySearcher.kt | 45 - .../LuceneTransactionPartySearcherTest.kt | 235 - .../RoomBankingPersistence/build.gradle | 39 - .../RoomBankingPersistence/consumer-rules.pro | 0 .../RoomBankingPersistence/proguard-rules.pro | 21 - .../src/main/AndroidManifest.xml | 5 - .../banking/persistence/BankingDatabase.kt | 33 - .../persistence/RoomBankingPersistence.kt | 286 - .../banking/persistence/TypeConverters.kt | 91 - .../persistence/dao/AccountTransactionDao.kt | 18 - .../banking/persistence/dao/AppSettingsDao.kt | 13 - .../banking/persistence/dao/BankAccountDao.kt | 14 - .../banking/persistence/dao/BankDao.kt | 13 - .../banking/persistence/dao/BaseDao.kt | 35 - .../persistence/dao/BaseDaoExtensions.kt | 58 - .../banking/persistence/dao/TanMediumDao.kt | 14 - .../banking/persistence/dao/TanMethodDao.kt | 14 - .../persistence/dao/TanMethodSettingsDao.kt | 13 - .../persistence/model/AccountTransaction.kt | 94 - .../banking/persistence/model/AppSettings.kt | 24 - .../dankito/banking/persistence/model/Bank.kt | 63 - .../banking/persistence/model/BankAccount.kt | 82 - .../persistence/model/RoomModelCreator.kt | 75 - .../banking/persistence/model/TanMedium.kt | 24 - .../persistence/model/TanMediumType.kt | 12 - .../banking/persistence/model/TanMethod.kt | 29 - .../persistence/model/TanMethodSettings.kt | 21 - .../persistence/model/TransactionParty.kt | 12 - .../json/BankingPersistenceJson/README.md | 7 - .../json/BankingPersistenceJson/build.gradle | 27 - .../persistence/BankingPersistenceJson.kt | 101 - .../mapper/EntitiesModelCreator.kt | 74 - .../model/AccountTransactionEntity.kt | 77 - .../persistence/model/BankAccountEntity.kt | 51 - .../persistence/model/BankDataEntity.kt | 40 - .../persistence/BankingPersistenceJsonTest.kt | 238 - rest/BankFinderRest/.dockerignore | 5 - rest/BankFinderRest/build.gradle | 66 - .../src/main/docker/Dockerfile.fast-jar | 57 - .../src/main/docker/Dockerfile.jvm | 54 - .../src/main/docker/Dockerfile.native | 27 - .../bankfinder/rest/BankFinderResource.kt | 25 - .../src/main/resources/application.properties | 1 - .../rest/NativeBankFinderResourceIT.kt | 6 - .../bankfinder/rest/BankFinderResourceTest.kt | 22 - rest/fints4kRest/.dockerignore | 5 - rest/fints4kRest/build.gradle | 65 - .../src/main/docker/Dockerfile.fast-jar | 57 - .../src/main/docker/Dockerfile.jvm | 54 - .../src/main/docker/Dockerfile.native | 27 - .../fints/rest/AccessControlResponseFilter.kt | 26 - .../banking/fints/rest/LoggingFilter.kt | 58 - .../banking/fints/rest/fints4kResource.kt | 72 - .../banking/fints/rest/mapper/DtoMapper.kt | 166 - .../fints/rest/model/BankAccessData.kt | 13 - .../fints/rest/model/EnterTanContext.kt | 14 - .../fints/rest/model/EnteringTanRequested.kt | 9 - .../fints/rest/model/ResponseHolder.kt | 63 - .../model/dto/request/AccountRequestDto.kt | 6 - .../model/dto/request/AddAccountRequestDto.kt | 4 - .../dto/request/BankAccessDataRequestDto.kt | 6 - .../GetAccountsTransactionsRequestDto.kt | 14 - .../rest/model/dto/request/TanResponseDto.kt | 9 - .../response/AccountTransactionResponseDto.kt | 17 - .../dto/response/AddAccountResponseDto.kt | 9 - .../dto/response/BankAccountResponseDto.kt | 26 - .../model/dto/response/BankResponseDto.kt | 22 - .../GetAccountTransactionsResponseDto.kt | 14 - .../GetAccountsTransactionsResponseDto.kt | 6 - .../model/dto/response/ResponseDtoBase.kt | 7 - .../rest/model/dto/response/ResponseType.kt | 12 - .../rest/model/dto/response/RestResponse.kt | 29 - .../dto/response/TanMethodResponseDto.kt | 15 - .../fints/rest/service/fints4kService.kt | 202 - .../model/GetAccountsTransactionsResponse.kt | 9 - .../src/main/resources/application.properties | 11 - .../src/main/resources/logback.xml | 36 - .../banking/fints/rest/NativeFints4kIT.kt | 6 - .../banking/fints/rest/fints4kResourceTest.kt | 20 - settings.gradle | 69 - tools/BankFinder/build.gradle | 131 +- tools/EpcQrCodeParser/build.gradle | 137 +- ui/BankingAndroidApp/build.gradle | 184 - ui/BankingAndroidApp/debug-keystore.jks | Bin 2251 -> 0 bytes ui/BankingAndroidApp/proguard-rules.pro | 21 - .../src/main/AndroidManifest.xml | 61 - .../src/main/ic_launcher-playstore.png | Bin 9744 -> 0 bytes .../dankito/banking/ui/android/BankingApp.kt | 25 - .../banking/ui/android/MainActivity.kt | 160 - .../banking/ui/android/RouterAndroid.kt | 57 - .../android/activities/ActivityExtensions.kt | 20 - .../ui/android/activities/BaseActivity.kt | 78 - .../ui/android/activities/LandingActivity.kt | 42 - .../ui/android/activities/LoginActivity.kt | 89 - .../adapter/AccountTransactionAdapter.kt | 81 - .../ui/android/adapter/BankDataAdapterItem.kt | 25 - .../ui/android/adapter/BankListAdapter.kt | 43 - .../adapter/CheckableValueAdapterItem.kt | 27 - .../DraggableBankAccountAdapterItem.kt | 25 - .../adapter/FastAdapterRecyclerView.kt | 86 - .../adapter/IconedBankAccountsAdapter.kt | 32 - .../android/adapter/RecipientListAdapter.kt | 34 - .../ui/android/adapter/TanMediumAdapter.kt | 25 - .../android/adapter/TanMethodAdapterItem.kt | 7 - .../ui/android/adapter/TanMethodsAdapter.kt | 25 - .../adapter/presenter/BankInfoPresenter.kt | 38 - .../adapter/presenter/RecipientPresenter.kt | 38 - .../AccountTransactionViewHolder.kt | 22 - .../adapter/viewholder/BankDataViewHolder.kt | 28 - .../adapter/viewholder/BankInfoViewHolder.kt | 20 - .../viewholder/CheckableValueViewHolder.kt | 31 - .../DraggableBankAccountViewHolder.kt | 23 - .../adapter/viewholder/RecipientViewHolder.kt | 19 - .../android/alerts/AskDeleteAccountAlert.kt | 25 - .../android/alerts/AskDismissChangesAlert.kt | 24 - .../authentication/AuthenticationResult.kt | 18 - .../authentication/AuthenticationService.kt | 305 - .../authentication/AuthenticationSettings.kt | 14 - .../authentication/AuthenticationType.kt | 12 - .../BiometricAuthenticationService.kt | 60 - .../IBiometricAuthenticationService.kt | 13 - .../banking/ui/android/di/BankingComponent.kt | 55 - .../banking/ui/android/di/BankingModule.kt | 209 - .../AccountTransactionDetailsDialog.kt | 80 - .../ui/android/dialogs/AddAccountDialog.kt | 222 - .../ui/android/dialogs/EnterAtcDialog.kt | 91 - .../ui/android/dialogs/EnterTanDialog.kt | 272 - .../android/dialogs/SendMessageLogDialog.kt | 165 - .../ui/android/dialogs/TransferMoneyDialog.kt | 485 - .../settings/BankAccountSettingsDialog.kt | 125 - .../dialogs/settings/BankSettingsDialog.kt | 143 - .../settings/ProtectAppSettingsDialog.kt | 183 - .../dialogs/settings/SettingsDialog.kt | 200 - .../dialogs/settings/SettingsDialogBase.kt | 149 - .../extensions/AutocompleteExtensions.kt | 28 - .../android/extensions/ByteArrayExtensions.kt | 16 - .../android/extensions/ContextExtensions.kt | 16 - .../android/extensions/EditTextExtensions.kt | 19 - .../extensions/IDrawerItemExtensions.kt | 20 - .../android/extensions/ImageViewExtensions.kt | 28 - .../extensions/RecyclerViewExtensions.kt | 9 - .../android/extensions/TextViewExtensions.kt | 30 - .../banking/ui/android/home/HomeFragment.kt | 363 - .../android/listener/ItemSelectedListener.kt | 15 - .../listener/ListItemSelectedListener.kt | 16 - .../android/security/CryptographyManager.kt | 181 - .../security/SecurityProviderServiceType.kt | 44 - .../ui/android/util/CurrentActivityTracker.kt | 53 - .../util/StandardAutocompleteCallback.kt | 20 - .../ui/android/util/StandardTextWatcher.kt | 27 - .../ui/android/views/AccountDrawerItem.kt | 6 - .../views/BankCredentialsPasswordView.kt | 41 - .../views/BiometricAuthenticationButton.kt | 57 - .../views/ChipTanFlickerCodeStripeView.kt | 60 - .../android/views/ChipTanFlickerCodeView.kt | 242 - .../ui/android/views/CollapsibleTextView.kt | 73 - .../banking/ui/android/views/DrawerView.kt | 218 - .../android/views/FloatingActionMenuButton.kt | 78 - .../banking/ui/android/views/FormEditText.kt | 62 - .../ui/android/views/FormLabelledValue.kt | 76 - .../ui/android/views/FormSectionTitle.kt | 50 - .../ui/android/views/FormSelectPeriod.kt | 102 - .../ui/android/views/InfoPopupWindow.kt | 38 - .../MainActivityFloatingActionMenuButton.kt | 145 - .../android/views/SecondaryIconDrawerItem.kt | 124 - .../android/views/TanImageSizeControlsView.kt | 24 - .../banking/ui/android/views/TanImageView.kt | 116 - .../src/main/res/anim/jump_from_down.xml | 12 - .../src/main/res/anim/jump_to_down.xml | 14 - ...color_primary_including_disabled_state.xml | 8 - ...lor_secondary_including_disabled_state.xml | 8 - .../drawable-hdpi/ic_cached_white_24dp.png | Bin 347 -> 0 bytes .../ic_check_circle_white_48dp.png | Bin 628 -> 0 bytes .../res/drawable-hdpi/ic_clear_white_48dp.png | Bin 347 -> 0 bytes .../drawable-hdpi/ic_search_white_24dp.png | Bin 396 -> 0 bytes .../drawable-mdpi/ic_cached_white_24dp.png | Bin 245 -> 0 bytes .../ic_check_circle_white_48dp.png | Bin 428 -> 0 bytes .../res/drawable-mdpi/ic_clear_white_48dp.png | Bin 257 -> 0 bytes .../drawable-mdpi/ic_search_white_24dp.png | Bin 247 -> 0 bytes .../drawable-xhdpi/ic_cached_white_24dp.png | Bin 457 -> 0 bytes .../ic_check_circle_white_48dp.png | Bin 872 -> 0 bytes .../drawable-xhdpi/ic_clear_white_48dp.png | Bin 436 -> 0 bytes .../drawable-xhdpi/ic_search_white_24dp.png | Bin 465 -> 0 bytes .../drawable-xxhdpi/ic_cached_white_24dp.png | Bin 663 -> 0 bytes .../ic_check_circle_white_48dp.png | Bin 1307 -> 0 bytes .../drawable-xxhdpi/ic_clear_white_48dp.png | Bin 524 -> 0 bytes .../drawable-xxhdpi/ic_search_white_24dp.png | Bin 728 -> 0 bytes .../drawable-xxxhdpi/ic_cached_white_24dp.png | Bin 861 -> 0 bytes .../ic_check_circle_white_48dp.png | Bin 1788 -> 0 bytes .../drawable-xxxhdpi/ic_clear_white_48dp.png | Bin 702 -> 0 bytes .../drawable-xxxhdpi/ic_search_white_24dp.png | Bin 915 -> 0 bytes ...conditionally_disabled_view_background.xml | 14 - .../res/drawable/fab_label_background.xml | 16 - .../src/main/res/drawable/ic_accounts.xml | 10 - .../main/res/drawable/ic_baseline_add_24.xml | 10 - .../res/drawable/ic_baseline_check_24.xml | 10 - .../res/drawable/ic_baseline_close_24.xml | 10 - .../ic_baseline_directions_run_24.xml | 10 - .../ic_baseline_directions_walk_24.xml | 10 - .../drawable/ic_baseline_drag_handle_24.xml | 10 - .../drawable/ic_baseline_expand_less_24.xml | 10 - .../drawable/ic_baseline_expand_more_24.xml | 10 - .../drawable/ic_baseline_fingerprint_24.xml | 10 - .../main/res/drawable/ic_baseline_info_24.xml | 10 - .../res/drawable/ic_baseline_pause_24.xml | 10 - .../drawable/ic_baseline_play_arrow_24.xml | 10 - .../main/res/drawable/ic_baseline_save_24.xml | 10 - .../main/res/drawable/ic_baseline_send_24.xml | 10 - .../res/drawable/ic_baseline_settings_24.xml | 10 - .../res/drawable/ic_baseline_share_24.xml | 10 - .../res/drawable/ic_baseline_zoom_in_24.xml | 13 - .../res/drawable/ic_baseline_zoom_out_24.xml | 10 - .../res/drawable/ic_launcher_foreground.xml | 61 - .../src/main/res/drawable/side_nav_bar.xml | 9 - .../src/main/res/layout/activity_login.xml | 110 - .../src/main/res/layout/activity_main.xml | 26 - .../src/main/res/layout/app_bar_main.xml | 39 - .../src/main/res/layout/content_main.xml | 20 - .../dialog_account_transaction_details.xml | 156 - .../main/res/layout/dialog_add_account.xml | 84 - .../layout/dialog_bank_account_settings.xml | 189 - .../main/res/layout/dialog_bank_settings.xml | 201 - .../src/main/res/layout/dialog_enter_atc.xml | 106 - .../src/main/res/layout/dialog_enter_tan.xml | 163 - .../layout/dialog_protect_app_settings.xml | 173 - .../res/layout/dialog_send_message_log.xml | 88 - .../src/main/res/layout/dialog_settings.xml | 153 - .../main/res/layout/dialog_transfer_money.xml | 210 - .../src/main/res/layout/fragment_home.xml | 224 - .../layout/list_item_account_transaction.xml | 93 - .../main/res/layout/list_item_bank_data.xml | 54 - .../main/res/layout/list_item_bank_info.xml | 86 - .../res/layout/list_item_checkable_value.xml | 43 - .../list_item_draggable_bank_account.xml | 40 - .../layout/list_item_iconed_bank_account.xml | 31 - .../main/res/layout/list_item_recipient.xml | 65 - .../main/res/layout/list_item_tan_medium.xml | 13 - .../main/res/layout/list_item_tan_method.xml | 13 - .../material_drawer_item_secondary_icon.xml | 68 - .../src/main/res/layout/nav_header_main.xml | 49 - .../layout/view_bank_credentials_password.xml | 20 - .../view_biometric_authentication_button.xml | 22 - .../main/res/layout/view_collapsible_text.xml | 40 - .../src/main/res/layout/view_flicker_code.xml | 156 - .../view_floating_action_button_main.xml | 52 - .../main/res/layout/view_form_edit_text.xml | 17 - .../src/main/res/layout/view_form_label.xml | 12 - .../res/layout/view_form_labelled_value.xml | 17 - .../res/layout/view_form_section_title.xml | 18 - .../res/layout/view_form_select_period.xml | 27 - .../src/main/res/layout/view_form_value.xml | 11 - .../src/main/res/layout/view_info_popup.xml | 45 - .../src/main/res/layout/view_tan_image.xml | 26 - .../layout/view_tan_image_size_controls.xml | 33 - .../context_menu_account_transactions.xml | 14 - .../src/main/res/menu/menu_main.xml | 23 - .../main/res/menu/menu_settings_dialog.xml | 16 - .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 979 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 1987 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 650 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 1339 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 1237 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 2561 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1820 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 3799 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 2476 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 5102 -> 0 bytes .../main/res/navigation/mobile_navigation.xml | 14 - .../src/main/res/values-de/strings.xml | 235 - .../src/main/res/values-sw600dp/attrs.xml | 4 - .../src/main/res/values-v21/styles.xml | 8 - .../src/main/res/values/attrs.xml | 49 - .../src/main/res/values/colors.xml | 55 - .../src/main/res/values/dimens.xml | 234 - .../res/values/ic_launcher_background.xml | 4 - .../src/main/res/values/ids.xml | 13 - .../src/main/res/values/strings.xml | 236 - .../src/main/res/values/styles.xml | 93 - ui/BankingJavaFxApp/build.gradle | 73 - .../ui/javafx/BankingJavaFXApplication.kt | 23 - .../javafx/dialogs/mainwindow/MainWindow.kt | 88 - .../mainwindow/controls/MainMenuBar.kt | 169 - .../src/main/resources/Messages.properties | 85 - .../src/main/resources/Messages_de.properties | 85 - .../src/main/resources/icons/AppIconRound.png | Bin 3380 -> 0 bytes .../src/main/resources/logback.xml | 36 - ui/BankingJavaFxControls/build.gradle | 27 - .../dankito/banking/ui/javafx/RouterJavaFx.kt | 45 - .../AccountTransactionsControlView.kt | 150 - .../controls/AccountTransactionsTable.kt | 117 - .../controls/AccountTransactionsView.kt | 158 - .../ui/javafx/controls/AccountsTreeView.kt | 79 - .../ui/javafx/controls/AccountsView.kt | 79 - .../ui/javafx/dialogs/AddAccountDialog.kt | 283 - .../ui/javafx/dialogs/JavaFxDialogService.kt | 139 - .../addaccount/BankInfoListCellFragment.kt | 84 - .../dialogs/addaccount/BankInfoViewModel.kt | 19 - .../cashtransfer/RecipientListCellFragment.kt | 29 - .../cashtransfer/RecipientViewModel.kt | 16 - .../cashtransfer/TransferMoneyDialog.kt | 381 - .../ui/javafx/dialogs/tan/EnterTanDialog.kt | 275 - .../controls/ChipTanFlickerCodeStripeView.kt | 55 - .../tan/controls/ChipTanFlickerCodeView.kt | 282 - .../tan/controls/TanGeneratorMarkerView.kt | 21 - .../dialogs/tan/controls/TanImageSizeView.kt | 44 - .../dialogs/tan/controls/TanImageView.kt | 102 - .../javafx/extensions/BankDataExtensions.kt | 17 - .../javafx/extensions/ByteArrayExtensions.kt | 9 - .../javafx/extensions/TextfieldExtensions.kt | 9 - .../javafx/model/AccountsAccountTreeItem.kt | 29 - .../model/AccountsBankAccountTreeItem.kt | 6 - .../ui/javafx/model/AccountsRootTreeItem.kt | 27 - .../ui/javafx/model/AccountsTreeItemBase.kt | 6 - .../icons/bank_does_not_support_fints_3_0.png | Bin 3788 -> 0 bytes .../icons/bank_supports_fints_3_0.png | Bin 3904 -> 0 bytes ui/BankingUiCommon/build.gradle | 173 - .../persistence/IBankingPersistence.kt | 34 - .../persistence/NoOpBankingPersistence.kt | 54 - .../search/ITransactionPartySearcher.kt | 8 - .../search/NoOpTransactionPartySearcher.kt | 10 - .../banking/search/TransactionParty.kt | 38 - .../testaccess/TestAccessBankingClient.kt | 201 - .../TestAccessBankingClientCreator.kt | 28 - .../banking/ui/BankingClientCallback.kt | 19 - .../net/dankito/banking/ui/IBankingClient.kt | 27 - .../banking/ui/IBankingClientCreator.kt | 17 - .../kotlin/net/dankito/banking/ui/IRouter.kt | 24 - .../ui/comparator/BankAccountComparator.kt | 16 - .../banking/ui/model/AccountTransaction.kt | 81 - .../dankito/banking/ui/model/BankAccount.kt | 67 - .../banking/ui/model/BankAccountType.kt | 26 - .../net/dankito/banking/ui/model/BankData.kt | 54 - .../dankito/banking/ui/model/Displayable.kt | 8 - .../banking/ui/model/IAccountTransaction.kt | 117 - .../dankito/banking/ui/model/IBankAccount.kt | 82 - .../net/dankito/banking/ui/model/IBankData.kt | 67 - .../banking/ui/model/MessageLogEntry.kt | 18 - .../banking/ui/model/MessageLogEntryType.kt | 12 - .../banking/ui/model/OrderedDisplayable.kt | 8 - .../banking/ui/model/RetrievedAccountData.kt | 29 - .../banking/ui/model/SelectedAccountType.kt | 12 - .../ui/model/TransactionsRetrievalState.kt | 16 - .../ui/model/issues/CreateTicketRequestDto.kt | 15 - .../ui/model/issues/IssueDescriptionFormat.kt | 10 - .../ui/model/mapper/DefaultModelCreator.kt | 68 - .../banking/ui/model/mapper/IModelCreator.kt | 76 - .../ExtractTransferMoneyDataFromPdfResult.kt | 13 - ...tractTransferMoneyDataFromPdfResultType.kt | 14 - .../parameters/GetTransactionsParameter.kt | 16 - .../ui/model/parameters/TransferMoneyData.kt | 43 - .../ui/model/responses/AddAccountResponse.kt | 30 - .../model/responses/BankingClientResponse.kt | 27 - .../responses/GetTransactionsResponse.kt | 31 - .../banking/ui/model/settings/AppSettings.kt | 28 - .../banking/ui/model/settings/ITanView.kt | 10 - .../ui/model/settings/TanMethodSettings.kt | 23 - .../banking/ui/model/tan/AllowedTanFormat.kt | 12 - .../model/tan/EnterTanGeneratorAtcResult.kt | 30 - .../banking/ui/model/tan/EnterTanResult.kt | 45 - .../banking/ui/model/tan/FlickerCode.kt | 22 - .../ui/model/tan/FlickerCodeTanChallenge.kt | 15 - .../banking/ui/model/tan/ImageTanChallenge.kt | 15 - .../ui/model/tan/MobilePhoneTanMedium.kt | 15 - .../banking/ui/model/tan/TanChallenge.kt | 13 - .../ui/model/tan/TanGeneratorTanMedium.kt | 15 - .../dankito/banking/ui/model/tan/TanImage.kt | 22 - .../dankito/banking/ui/model/tan/TanMedium.kt | 23 - .../banking/ui/model/tan/TanMediumStatus.kt | 10 - .../dankito/banking/ui/model/tan/TanMethod.kt | 55 - .../banking/ui/model/tan/TanMethodType.kt | 26 - .../banking/ui/presenter/BankingPresenter.kt | 1258 - .../kotlin/net/dankito/banking/ui/util/Bit.kt | 29 - .../dankito/banking/ui/util/CurrencyInfo.kt | 16 - .../banking/ui/util/CurrencyInfoProvider.kt | 270 - .../banking/ui/util/FlickerCodeAnimator.kt | 86 - .../ui/util/FlickerCodeStepsCalculator.kt | 81 - .../banking/ui/util/ICurrencyInfoProvider.kt | 19 - .../net/dankito/banking/ui/util/Step.kt | 14 - .../banking/util/CoroutinesAsyncRunner.kt | 15 - .../net/dankito/banking/util/Extensions.kt | 52 - .../net/dankito/banking/util/IAsyncRunner.kt | 8 - .../dankito/banking/util/IBankIconFinder.kt | 10 - .../net/dankito/banking/util/ISerializer.kt | 24 - .../dankito/banking/util/InputValidator.kt | 279 - .../banking/util/NoOpBankIconFinder.kt | 14 - .../dankito/banking/util/NoOpSerializer.kt | 34 - .../dankito/banking/util/ValidationResult.kt | 15 - .../util/extraction/ExtractionResult.kt | 11 - .../util/extraction/IInvoiceDataExtractor.kt | 8 - .../util/extraction/ITextExtractorRegistry.kt | 10 - .../banking/util/extraction/InvoiceData.kt | 13 - .../extraction/NoOpInvoiceDataExtractor.kt | 10 - .../extraction/NoOpTextExtractorRegistry.kt | 12 - .../kotlin/net/dankito/banking/Extensions.kt | 10 - .../dankito/banking/util/BankIconFinder.kt | 308 - .../banking/util/JacksonJsonSerializer.kt | 47 - .../banking/util/ThreadPoolAsyncRunner.kt | 12 - .../extraction/JavaInvoiceDataExtractor.kt | 23 - .../extraction/JavaTextExtractorRegistry.kt | 23 - .../IBankingPersistenceExtensions.kt | 21 - .../persistence/JacksonClassNameIdResolver.kt | 38 - .../banking/util/BankIconFinderTest.kt | 269 - .../banking/util/InputValidatorTest.kt | 687 - .../src/main/AndroidManifest.xml | 7 - ui/BankingUiNativeIntegration/build.gradle | 102 - .../dankito/banking/BankingPresenterSwift.kt | 22 - .../net/dankito/banking/UiExtensions.kt | 30 - .../BankingiOSApp.xcodeproj/project.pbxproj | 1439 - .../xcschemes/BankingiOSApp.xcscheme | 108 - .../contents.xcworkspacedata | 10 - .../BankingiOSApp/AppDelegate.swift | 28 - .../AppIcon.appiconset/Contents.json | 112 - .../AppIcon.appiconset/icon-ios-1024@1x.png | Bin 11734 -> 0 bytes .../AppIcon.appiconset/icon-ios-20@2x-1.png | Bin 494 -> 0 bytes .../AppIcon.appiconset/icon-ios-20@2x.png | Bin 494 -> 0 bytes .../AppIcon.appiconset/icon-ios-20@3x.png | Bin 687 -> 0 bytes .../AppIcon.appiconset/icon-ios-29@2x-1.png | Bin 685 -> 0 bytes .../AppIcon.appiconset/icon-ios-29@2x.png | Bin 685 -> 0 bytes .../AppIcon.appiconset/icon-ios-29@3x.png | Bin 926 -> 0 bytes .../AppIcon.appiconset/icon-ios-40@2x-2.png | Bin 840 -> 0 bytes .../AppIcon.appiconset/icon-ios-40@2x.png | Bin 840 -> 0 bytes .../AppIcon.appiconset/icon-ios-40@3x.png | Bin 1146 -> 0 bytes .../AppIcon.appiconset/icon-ios-60@2x.png | Bin 1146 -> 0 bytes .../AppIcon.appiconset/icon-ios-60@3x.png | Bin 1715 -> 0 bytes .../AppIcon.appiconset/icon-ios-76@2x.png | Bin 1538 -> 0 bytes .../AppIcon.appiconset/icon-ios-83.5@2x.png | Bin 1589 -> 0 bytes .../AppIconInApp.imageset/Contents.json | 12 - .../AppIconInApp.imageset/icon-ios.svg | 21 - .../BankTransfer.imageset/BankTransfer.pdf | 362 - .../BankTransfer.imageset/Contents.json | 16 - .../Assets.xcassets/Contents.json | 6 - .../Settings.imageset/Contents.json | 16 - .../Settings.imageset/gear.fill.pdf | 170 - .../accounts.imageset/Contents.json | 16 - .../accounts.imageset/accounts.pdf | 111 - .../new.imageset/Contents.json | 15 - .../Assets.xcassets/new.imageset/new.pdf | 88 - .../BankIconFinder/Favicon.swift | 23 - .../BankIconFinder/FaviconFinder.swift | 190 - .../BankIconFinder/FaviconType.swift | 18 - .../BankingiOSApp/BankIconFinder/Size.swift | 42 - .../BankIconFinder/SwiftBankIconFinder.swift | 279 - .../BankIconFinder/UrlUtil.swift | 56 - .../.xccurrentversion | 8 - .../BankingiOSApp.xcdatamodel/contents | 122 - .../Base.lproj/LaunchScreen.storyboard | 25 - .../Base.lproj/Localizable.strings | 237 - ui/BankingiOSApp/BankingiOSApp/Info.plist | 77 - .../InterceptTabClickViewController.swift | 15 - .../Preview Assets.xcassets/Contents.json | 6 - .../Preview Content/PreviewData.swift | 51 - .../BankingiOSApp/SceneDelegate.swift | 103 - .../Security/AuthenticationService.swift | 485 - .../Security/AuthenticationType.swift | 12 - .../BiometricAuthenticationService.swift | 86 - .../Security/KeychainPasswordItem.swift | 244 - .../BankingiOSApp/TabBarController.swift | 135 - .../de.lproj/Localizable.strings | 238 - .../BankingiOSApp/extensions/Extensions.swift | 186 - .../extensions/SwiftExtensions.swift | 278 - .../extensions/UIKitExtensions.swift | 102 - .../extensions/ViewExtensions.swift | 266 - .../fints4k/DispatchQueueAsyncRunner.swift | 15 - .../fints4k/UrlSessionWebClient.swift | 129 - .../BankingiOSApp/persistence/AppData.swift | 39 - .../CoreDataBankingPersistence.swift | 297 - .../persistence/EnterTanState.swift | 22 - .../BankingiOSApp/persistence/Mapper.swift | 474 - .../BankingiOSApp/ui/AdaptsToKeyboard.swift | 39 - .../BankingiOSApp/ui/DependencyInjector.swift | 25 - .../BankingiOSApp/ui/Message.swift | 39 - .../BankingiOSApp/ui/Messages.swift | 21 - .../BankingiOSApp/ui/SelectorWrapper.swift | 19 - .../BankingiOSApp/ui/Styles.swift | 21 - .../BankingiOSApp/ui/SwiftUiRouter.swift | 30 - .../BankingiOSApp/ui/UIKit/ActionSheet.swift | 28 - .../ui/UIKit/LabelledUIKitTextField.swift | 108 - ...ledUIKitTextFieldWithValidationLabel.swift | 87 - .../ui/UIKit/SelectableUILabel.swift | 51 - .../BankingiOSApp/ui/UIKit/UIAlert.swift | 23 - .../BankingiOSApp/ui/UIKit/UIAlertBase.swift | 33 - .../ui/UIKit/UIKitActivityIndicator.swift | 40 - .../BankingiOSApp/ui/UIKit/UIKitButton.swift | 47 - .../ui/UIKit/UIKitImageView.swift | 24 - .../ui/UIKit/UIKitSearchBar.swift | 125 - .../ui/UIKit/UIKitTextField.swift | 270 - .../AccountTransactionDetailsDialog.swift | 68 - .../dialogs/AccountTransactionsDialog.swift | 298 - .../ui/dialogs/AccountsDialog.swift | 56 - .../ui/dialogs/AddAccountDialog.swift | 135 - .../dialogs/BankAccountSettingsDialog.swift | 184 - .../ui/dialogs/BankSettingsDialog.swift | 153 - .../ui/dialogs/EnterTanDialog.swift | 229 - .../ui/dialogs/LoginDialog.swift | 143 - .../ui/dialogs/ProtectAppSettingsDialog.swift | 235 - .../ui/dialogs/ScanQrCodeViewController.swift | 131 - .../ui/dialogs/SelectBankDialog.swift | 117 - .../ui/dialogs/SettingsDialog.swift | 205 - .../ui/dialogs/TransferMoneyDialog.swift | 434 - .../ui/views/AddAccountButtonView.swift | 42 - .../BankingiOSApp/ui/views/AmountLabel.swift | 31 - .../views/BankCredentialsPasswordView.swift | 32 - .../ui/views/CollapsibleText.swift | 76 - .../BankingiOSApp/ui/views/Divider.swift | 29 - .../BankingiOSApp/ui/views/FaceIDButton.swift | 38 - .../BankingiOSApp/ui/views/IconView.swift | 41 - .../ui/views/IconedTitleView.swift | 64 - .../BankingiOSApp/ui/views/InfoButton.swift | 60 - .../BankingiOSApp/ui/views/InfoLabel.swift | 46 - .../ui/views/LabelledAmount.swift | 40 - .../ui/views/LabelledObject.swift | 37 - .../ui/views/LabelledValue.swift | 41 - .../BankingiOSApp/ui/views/LazyView.swift | 24 - .../ui/views/RealTimeTransferInfoView.swift | 36 - .../ui/views/SearchBarWithLabel.swift | 61 - ...tionHeaderWithRightAlignedEditButton.swift | 34 - .../ui/views/SectionWithoutBackground.swift | 35 - .../ui/views/SelectableText.swift | 47 - .../ui/views/TextWithScrollView.swift | 64 - .../ui/views/TouchIDButton.swift | 27 - .../BankingiOSApp/ui/views/UpdateButton.swift | 48 - .../ui/views/ValidationLabel.swift | 41 - .../ui/views/VerticalLabelledValue.swift | 45 - .../AccountTransactionListItem.swift | 106 - .../ui/views/listitems/AllBanksListItem.swift | 40 - .../views/listitems/BankAccountListItem.swift | 45 - .../ui/views/listitems/BankInfoListItem.swift | 65 - .../ui/views/listitems/BankListItem.swift | 84 - .../views/listitems/CheckmarkListItem.swift | 61 - .../views/listitems/RecipientListItem.swift | 55 - .../ui/views/tan/FlickerCodeAnimator.swift | 89 - .../ui/views/tan/FlickerCodeStripe.swift | 69 - .../ui/views/tan/FlickerCodeTanView.swift | 214 - .../ui/views/tan/ImageTanView.swift | 72 - .../ui/views/tan/ScaleImageView.swift | 64 - .../tan/TanGeneratorPositionMarker.swift | 26 - .../ui/views/tan/TanMethodPicker.swift | 72 - .../ui/views/tan/TrianglePointingDown.swift | 27 - .../BankingiOSApp/util/Stopwatch.swift | 65 - .../SwiftBankIconFinderTest.swift | 29 - .../BankingiOSAppTests.swift | 27 - .../BankingiOSAppTests/Info.plist | 22 - .../BankingiOSAppUITests.swift | 37 - .../BankingiOSAppUITests/Info.plist | 22 - ui/BankingiOSApp/Podfile | 21 - ui/BankingiOSApp/Podfile.lock | 32 - .../Incremental Store/EncryptedStore.h | 222 - .../Incremental Store/EncryptedStore.m | 4379 - .../Pods/EncryptedCoreData/LICENSE | 13 - .../Pods/EncryptedCoreData/README.md | 190 - .../EncryptedCoreData.podspec.json | 34 - ui/BankingiOSApp/Pods/Manifest.lock | 32 - .../Pods/Pods.xcodeproj/project.pbxproj | 1211 - ui/BankingiOSApp/Pods/SQLCipher/LICENSE | 24 - ui/BankingiOSApp/Pods/SQLCipher/README.md | 122 - ui/BankingiOSApp/Pods/SQLCipher/sqlite3.c | 207737 --------------- ui/BankingiOSApp/Pods/SQLCipher/sqlite3.h | 10694 - .../EncryptedCoreData-Info.plist | 26 - .../EncryptedCoreData-dummy.m | 5 - .../EncryptedCoreData-prefix.pch | 12 - .../EncryptedCoreData-umbrella.h | 17 - .../EncryptedCoreData.debug.xcconfig | 12 - .../EncryptedCoreData.modulemap | 6 - .../EncryptedCoreData.release.xcconfig | 12 - ...kingiOSApp-BankingiOSAppUITests-Info.plist | 26 - ...ingiOSAppUITests-acknowledgements.markdown | 48 - ...ankingiOSAppUITests-acknowledgements.plist | 86 - ...BankingiOSApp-BankingiOSAppUITests-dummy.m | 5 - ...ts-frameworks-Debug-input-files.xcfilelist | 3 - ...s-frameworks-Debug-output-files.xcfilelist | 2 - ...-frameworks-Release-input-files.xcfilelist | 3 - ...frameworks-Release-output-files.xcfilelist | 2 - ...giOSApp-BankingiOSAppUITests-frameworks.sh | 209 - ...kingiOSApp-BankingiOSAppUITests-umbrella.h | 16 - ...iOSApp-BankingiOSAppUITests.debug.xcconfig | 11 - ...nkingiOSApp-BankingiOSAppUITests.modulemap | 6 - ...SApp-BankingiOSAppUITests.release.xcconfig | 11 - .../Pods-BankingiOSApp-Info.plist | 26 - ...ds-BankingiOSApp-acknowledgements.markdown | 48 - .../Pods-BankingiOSApp-acknowledgements.plist | 86 - .../Pods-BankingiOSApp-dummy.m | 5 - ...pp-frameworks-Debug-input-files.xcfilelist | 3 - ...p-frameworks-Debug-output-files.xcfilelist | 2 - ...-frameworks-Release-input-files.xcfilelist | 3 - ...frameworks-Release-output-files.xcfilelist | 2 - .../Pods-BankingiOSApp-frameworks.sh | 209 - .../Pods-BankingiOSApp-umbrella.h | 16 - .../Pods-BankingiOSApp.debug.xcconfig | 11 - .../Pods-BankingiOSApp.modulemap | 6 - .../Pods-BankingiOSApp.release.xcconfig | 11 - .../Pods-BankingiOSAppTests-Info.plist | 26 - ...nkingiOSAppTests-acknowledgements.markdown | 3 - ...-BankingiOSAppTests-acknowledgements.plist | 29 - .../Pods-BankingiOSAppTests-dummy.m | 5 - .../Pods-BankingiOSAppTests-umbrella.h | 16 - .../Pods-BankingiOSAppTests.debug.xcconfig | 10 - .../Pods-BankingiOSAppTests.modulemap | 6 - .../Pods-BankingiOSAppTests.release.xcconfig | 10 - .../SQLCipher/SQLCipher-Info.plist | 26 - .../SQLCipher/SQLCipher-dummy.m | 5 - .../SQLCipher/SQLCipher-prefix.pch | 12 - .../SQLCipher/SQLCipher-umbrella.h | 17 - .../SQLCipher/SQLCipher.debug.xcconfig | 11 - .../SQLCipher/SQLCipher.modulemap | 6 - .../SQLCipher/SQLCipher.release.xcconfig | 11 - ui/fints4kBankingClient/build.gradle | 124 - .../banking/extensions/AmountExtensions.kt | 14 - .../dankito/banking/fints4kBankingClient.kt | 292 - .../banking/fints4kBankingClientCreator.kt | 31 - .../banking/mapper/fints4kModelMapper.kt | 499 - .../src/main/AndroidManifest.xml | 7 - ui/hbci4jBankingClient/build.gradle | 26 - .../net/dankito/banking/HbciCallback.kt | 215 - .../dankito/banking/hbci4jBankingClient.kt | 374 - .../banking/hbci4jBankingClientCreator.kt | 26 - .../banking/model/AccountCredentials.kt | 14 - .../dankito/banking/model/ConnectResult.kt | 12 - .../banking/util/AccountTransactionMapper.kt | 89 - .../dankito/banking/util/hbci4jModelMapper.kt | 127 - 649 files changed, 750 insertions(+), 265091 deletions(-) delete mode 100644 common/src/main/AndroidManifest.xml delete mode 100644 fints4k-jvm/build.gradle delete mode 100644 fints4k/src/jvm6Test/java/net/dankito/banking/fints/JavaShowcase.java delete mode 100644 fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt delete mode 100644 fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt rename fints4k/src/{jvm6Main => jvmMain}/kotlin/net/dankito/banking/fints/util/JavaThreadPool.kt (100%) create mode 100644 fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt rename fints4k/src/{jvm6Test => jvmTest}/kotlin/net/dankito/banking/fints/FinTsTestBaseJvm.kt (100%) create mode 100644 fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt rename fints4k/src/{jvm6Test => jvmTest}/kotlin/net/dankito/banking/fints/response/ResponseParserTestJvm.kt (96%) rename fints4k/src/{jvm6Test => jvmTest}/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt (95%) rename fints4k/src/{jvm6Test => jvmTest}/kotlin/net/dankito/banking/fints/transactions/Mt940ParserTestJvm.kt (94%) rename fints4k/src/{jvm6Test => jvmTest}/resources/logback-test.xml (100%) rename fints4k/src/{jvm6Test => jvmTest}/resources/test_files/Decode_TanChallengeHhdUc_WithMaskedCharacter.txt (100%) rename fints4k/src/{jvm6Test => jvmTest}/resources/test_files/TransactionsMt940.txt (100%) rename fints4k/src/{jvm6Test => jvmTest}/resources/test_files/TransactionsMt940_2.txt (100%) delete mode 100644 fints4k/src/main/AndroidManifest.xml delete mode 100644 persistence/LuceneBankingPersistence/build.gradle delete mode 100644 persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/LuceneConfig.kt delete mode 100644 persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/persistence/LuceneBankingPersistence.kt delete mode 100644 persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/search/LuceneTransactionPartySearcher.kt delete mode 100644 persistence/LuceneBankingPersistence/src/test/kotlin/net/dankito/banking/search/LuceneTransactionPartySearcherTest.kt delete mode 100644 persistence/database/RoomBankingPersistence/build.gradle delete mode 100644 persistence/database/RoomBankingPersistence/consumer-rules.pro delete mode 100644 persistence/database/RoomBankingPersistence/proguard-rules.pro delete mode 100644 persistence/database/RoomBankingPersistence/src/main/AndroidManifest.xml delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/BankingDatabase.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/RoomBankingPersistence.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/TypeConverters.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/AccountTransactionDao.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/AppSettingsDao.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BankAccountDao.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BankDao.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BaseDao.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BaseDaoExtensions.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMediumDao.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMethodDao.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMethodSettingsDao.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/AccountTransaction.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/AppSettings.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/Bank.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/BankAccount.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/RoomModelCreator.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMedium.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMediumType.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMethod.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMethodSettings.kt delete mode 100644 persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TransactionParty.kt delete mode 100644 persistence/json/BankingPersistenceJson/README.md delete mode 100644 persistence/json/BankingPersistenceJson/build.gradle delete mode 100644 persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/BankingPersistenceJson.kt delete mode 100644 persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/mapper/EntitiesModelCreator.kt delete mode 100644 persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/AccountTransactionEntity.kt delete mode 100644 persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/BankAccountEntity.kt delete mode 100644 persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/BankDataEntity.kt delete mode 100644 persistence/json/BankingPersistenceJson/src/test/kotlin/net/dankito/banking/persistence/BankingPersistenceJsonTest.kt delete mode 100644 rest/BankFinderRest/.dockerignore delete mode 100644 rest/BankFinderRest/build.gradle delete mode 100644 rest/BankFinderRest/src/main/docker/Dockerfile.fast-jar delete mode 100644 rest/BankFinderRest/src/main/docker/Dockerfile.jvm delete mode 100644 rest/BankFinderRest/src/main/docker/Dockerfile.native delete mode 100644 rest/BankFinderRest/src/main/kotlin/net/dankito/banking/bankfinder/rest/BankFinderResource.kt delete mode 100644 rest/BankFinderRest/src/main/resources/application.properties delete mode 100644 rest/BankFinderRest/src/native-test/kotlin/net/dankito/banking/bankfinder/rest/NativeBankFinderResourceIT.kt delete mode 100644 rest/BankFinderRest/src/test/kotlin/net/dankito/banking/bankfinder/rest/BankFinderResourceTest.kt delete mode 100644 rest/fints4kRest/.dockerignore delete mode 100644 rest/fints4kRest/build.gradle delete mode 100644 rest/fints4kRest/src/main/docker/Dockerfile.fast-jar delete mode 100644 rest/fints4kRest/src/main/docker/Dockerfile.jvm delete mode 100644 rest/fints4kRest/src/main/docker/Dockerfile.native delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/AccessControlResponseFilter.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/LoggingFilter.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/fints4kResource.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/mapper/DtoMapper.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/BankAccessData.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/EnterTanContext.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/EnteringTanRequested.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/ResponseHolder.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/AccountRequestDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/AddAccountRequestDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/BankAccessDataRequestDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/GetAccountsTransactionsRequestDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/TanResponseDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/AccountTransactionResponseDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/AddAccountResponseDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/BankAccountResponseDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/BankResponseDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/GetAccountTransactionsResponseDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/GetAccountsTransactionsResponseDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/ResponseDtoBase.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/ResponseType.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/RestResponse.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/TanMethodResponseDto.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/service/fints4kService.kt delete mode 100644 rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/service/model/GetAccountsTransactionsResponse.kt delete mode 100644 rest/fints4kRest/src/main/resources/application.properties delete mode 100755 rest/fints4kRest/src/main/resources/logback.xml delete mode 100644 rest/fints4kRest/src/native-test/kotlin/net/dankito/banking/fints/rest/NativeFints4kIT.kt delete mode 100644 rest/fints4kRest/src/test/kotlin/net/dankito/banking/fints/rest/fints4kResourceTest.kt delete mode 100644 ui/BankingAndroidApp/build.gradle delete mode 100644 ui/BankingAndroidApp/debug-keystore.jks delete mode 100644 ui/BankingAndroidApp/proguard-rules.pro delete mode 100644 ui/BankingAndroidApp/src/main/AndroidManifest.xml delete mode 100644 ui/BankingAndroidApp/src/main/ic_launcher-playstore.png delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/BankingApp.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/MainActivity.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/RouterAndroid.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/ActivityExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/BaseActivity.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LandingActivity.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LoginActivity.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/AccountTransactionAdapter.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/BankDataAdapterItem.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/BankListAdapter.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/CheckableValueAdapterItem.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/DraggableBankAccountAdapterItem.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/FastAdapterRecyclerView.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/IconedBankAccountsAdapter.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/RecipientListAdapter.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMediumAdapter.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMethodAdapterItem.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMethodsAdapter.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/presenter/BankInfoPresenter.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/presenter/RecipientPresenter.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/AccountTransactionViewHolder.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/BankDataViewHolder.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/BankInfoViewHolder.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/CheckableValueViewHolder.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/DraggableBankAccountViewHolder.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/RecipientViewHolder.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/alerts/AskDeleteAccountAlert.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/alerts/AskDismissChangesAlert.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationResult.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationService.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationSettings.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationType.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/BiometricAuthenticationService.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/IBiometricAuthenticationService.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingComponent.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingModule.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/AccountTransactionDetailsDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/AddAccountDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterAtcDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterTanDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/SendMessageLogDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/TransferMoneyDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/BankAccountSettingsDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/BankSettingsDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/ProtectAppSettingsDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/SettingsDialog.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/SettingsDialogBase.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/AutocompleteExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ByteArrayExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ContextExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/EditTextExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/IDrawerItemExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ImageViewExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/RecyclerViewExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/TextViewExtensions.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/listener/ItemSelectedListener.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/listener/ListItemSelectedListener.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/security/CryptographyManager.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/security/SecurityProviderServiceType.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/CurrentActivityTracker.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/StandardAutocompleteCallback.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/StandardTextWatcher.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/AccountDrawerItem.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/BankCredentialsPasswordView.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/BiometricAuthenticationButton.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/ChipTanFlickerCodeStripeView.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/ChipTanFlickerCodeView.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/CollapsibleTextView.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/DrawerView.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FloatingActionMenuButton.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormEditText.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormLabelledValue.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormSectionTitle.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormSelectPeriod.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/InfoPopupWindow.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/MainActivityFloatingActionMenuButton.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/SecondaryIconDrawerItem.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/TanImageSizeControlsView.kt delete mode 100644 ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/TanImageView.kt delete mode 100755 ui/BankingAndroidApp/src/main/res/anim/jump_from_down.xml delete mode 100755 ui/BankingAndroidApp/src/main/res/anim/jump_to_down.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/color/text_color_primary_including_disabled_state.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/color/text_color_secondary_including_disabled_state.xml delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-hdpi/ic_cached_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-hdpi/ic_check_circle_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-hdpi/ic_clear_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-hdpi/ic_search_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-mdpi/ic_cached_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-mdpi/ic_check_circle_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-mdpi/ic_clear_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-mdpi/ic_search_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xhdpi/ic_cached_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xhdpi/ic_check_circle_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xhdpi/ic_clear_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xhdpi/ic_search_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xxhdpi/ic_cached_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xxhdpi/ic_check_circle_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xxhdpi/ic_clear_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xxxhdpi/ic_cached_white_24dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xxxhdpi/ic_check_circle_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xxxhdpi/ic_clear_white_48dp.png delete mode 100755 ui/BankingAndroidApp/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/conditionally_disabled_view_background.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/fab_label_background.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_accounts.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_add_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_check_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_close_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_directions_run_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_directions_walk_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_drag_handle_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_expand_less_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_expand_more_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_fingerprint_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_info_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_pause_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_play_arrow_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_save_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_send_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_settings_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_share_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_zoom_in_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_baseline_zoom_out_24.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/ic_launcher_foreground.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/drawable/side_nav_bar.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/activity_login.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/activity_main.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/app_bar_main.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/content_main.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_account_transaction_details.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_add_account.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_bank_account_settings.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_bank_settings.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_enter_atc.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_enter_tan.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_protect_app_settings.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_send_message_log.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_settings.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/dialog_transfer_money.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/fragment_home.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_account_transaction.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_bank_data.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_bank_info.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_checkable_value.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_draggable_bank_account.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_iconed_bank_account.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_recipient.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_tan_medium.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/list_item_tan_method.xml delete mode 100755 ui/BankingAndroidApp/src/main/res/layout/material_drawer_item_secondary_icon.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/nav_header_main.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_bank_credentials_password.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_biometric_authentication_button.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_collapsible_text.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_flicker_code.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_floating_action_button_main.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_form_edit_text.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_form_label.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_form_labelled_value.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_form_section_title.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_form_select_period.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_form_value.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_info_popup.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_tan_image.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/layout/view_tan_image_size_controls.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/menu/context_menu_account_transactions.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/menu/menu_main.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/menu/menu_settings_dialog.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 ui/BankingAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 ui/BankingAndroidApp/src/main/res/navigation/mobile_navigation.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values-de/strings.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values-sw600dp/attrs.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values-v21/styles.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values/attrs.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values/colors.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values/dimens.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values/ic_launcher_background.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values/ids.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values/strings.xml delete mode 100644 ui/BankingAndroidApp/src/main/res/values/styles.xml delete mode 100644 ui/BankingJavaFxApp/build.gradle delete mode 100755 ui/BankingJavaFxApp/src/main/kotlin/net/dankito/banking/ui/javafx/BankingJavaFXApplication.kt delete mode 100755 ui/BankingJavaFxApp/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/mainwindow/MainWindow.kt delete mode 100644 ui/BankingJavaFxApp/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/mainwindow/controls/MainMenuBar.kt delete mode 100755 ui/BankingJavaFxApp/src/main/resources/Messages.properties delete mode 100755 ui/BankingJavaFxApp/src/main/resources/Messages_de.properties delete mode 100644 ui/BankingJavaFxApp/src/main/resources/icons/AppIconRound.png delete mode 100755 ui/BankingJavaFxApp/src/main/resources/logback.xml delete mode 100644 ui/BankingJavaFxControls/build.gradle delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/RouterJavaFx.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsControlView.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsTable.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountsTreeView.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountsView.kt delete mode 100755 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/AddAccountDialog.kt delete mode 100755 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/JavaFxDialogService.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoListCellFragment.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoViewModel.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/cashtransfer/RecipientListCellFragment.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/cashtransfer/RecipientViewModel.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/cashtransfer/TransferMoneyDialog.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/tan/EnterTanDialog.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/tan/controls/ChipTanFlickerCodeStripeView.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/tan/controls/ChipTanFlickerCodeView.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/tan/controls/TanGeneratorMarkerView.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/tan/controls/TanImageSizeView.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/tan/controls/TanImageView.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/extensions/BankDataExtensions.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/extensions/ByteArrayExtensions.kt delete mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/extensions/TextfieldExtensions.kt delete mode 100755 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/model/AccountsAccountTreeItem.kt delete mode 100755 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/model/AccountsBankAccountTreeItem.kt delete mode 100755 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/model/AccountsRootTreeItem.kt delete mode 100755 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/model/AccountsTreeItemBase.kt delete mode 100755 ui/BankingJavaFxControls/src/main/resources/icons/bank_does_not_support_fints_3_0.png delete mode 100755 ui/BankingJavaFxControls/src/main/resources/icons/bank_supports_fints_3_0.png delete mode 100644 ui/BankingUiCommon/build.gradle delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/persistence/IBankingPersistence.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/persistence/NoOpBankingPersistence.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/search/ITransactionPartySearcher.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/search/NoOpTransactionPartySearcher.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/search/TransactionParty.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/service/testaccess/TestAccessBankingClient.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/service/testaccess/TestAccessBankingClientCreator.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/BankingClientCallback.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/IBankingClient.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/IBankingClientCreator.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/IRouter.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/comparator/BankAccountComparator.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/AccountTransaction.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/BankAccount.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/BankAccountType.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/BankData.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/Displayable.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/IAccountTransaction.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/IBankAccount.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/IBankData.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/MessageLogEntry.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/MessageLogEntryType.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/OrderedDisplayable.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/RetrievedAccountData.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/SelectedAccountType.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/TransactionsRetrievalState.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/issues/CreateTicketRequestDto.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/issues/IssueDescriptionFormat.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/mapper/DefaultModelCreator.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/mapper/IModelCreator.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/moneytransfer/ExtractTransferMoneyDataFromPdfResult.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/moneytransfer/ExtractTransferMoneyDataFromPdfResultType.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/parameters/GetTransactionsParameter.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/parameters/TransferMoneyData.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/responses/AddAccountResponse.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/responses/BankingClientResponse.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/responses/GetTransactionsResponse.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/settings/AppSettings.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/settings/ITanView.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/settings/TanMethodSettings.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/AllowedTanFormat.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/EnterTanGeneratorAtcResult.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/EnterTanResult.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/FlickerCode.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/FlickerCodeTanChallenge.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/ImageTanChallenge.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/MobilePhoneTanMedium.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanChallenge.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanGeneratorTanMedium.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanImage.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanMedium.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanMediumStatus.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanMethod.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/model/tan/TanMethodType.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/presenter/BankingPresenter.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/util/Bit.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/util/CurrencyInfo.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/util/CurrencyInfoProvider.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/util/FlickerCodeAnimator.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/util/FlickerCodeStepsCalculator.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/util/ICurrencyInfoProvider.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/ui/util/Step.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/CoroutinesAsyncRunner.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/Extensions.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/IAsyncRunner.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/IBankIconFinder.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/ISerializer.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/InputValidator.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/NoOpBankIconFinder.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/NoOpSerializer.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/ValidationResult.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/extraction/ExtractionResult.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/extraction/IInvoiceDataExtractor.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/extraction/ITextExtractorRegistry.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/extraction/InvoiceData.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/extraction/NoOpInvoiceDataExtractor.kt delete mode 100644 ui/BankingUiCommon/src/commonMain/kotlin/net/dankito/banking/util/extraction/NoOpTextExtractorRegistry.kt delete mode 100644 ui/BankingUiCommon/src/iosMain/kotlin/net/dankito/banking/Extensions.kt delete mode 100644 ui/BankingUiCommon/src/jvmMain/kotlin/net/dankito/banking/util/BankIconFinder.kt delete mode 100644 ui/BankingUiCommon/src/jvmMain/kotlin/net/dankito/banking/util/JacksonJsonSerializer.kt delete mode 100644 ui/BankingUiCommon/src/jvmMain/kotlin/net/dankito/banking/util/ThreadPoolAsyncRunner.kt delete mode 100644 ui/BankingUiCommon/src/jvmMain/kotlin/net/dankito/banking/util/extraction/JavaInvoiceDataExtractor.kt delete mode 100644 ui/BankingUiCommon/src/jvmMain/kotlin/net/dankito/banking/util/extraction/JavaTextExtractorRegistry.kt delete mode 100644 ui/BankingUiCommon/src/jvmMain/kotlin/net/dankito/banking/util/persistence/IBankingPersistenceExtensions.kt delete mode 100644 ui/BankingUiCommon/src/jvmMain/kotlin/net/dankito/banking/util/persistence/JacksonClassNameIdResolver.kt delete mode 100644 ui/BankingUiCommon/src/jvmTest/kotlin/net/dankito/banking/util/BankIconFinderTest.kt delete mode 100644 ui/BankingUiCommon/src/jvmTest/kotlin/net/dankito/banking/util/InputValidatorTest.kt delete mode 100644 ui/BankingUiCommon/src/main/AndroidManifest.xml delete mode 100644 ui/BankingUiNativeIntegration/build.gradle delete mode 100644 ui/BankingUiNativeIntegration/src/iosMain/kotlin/net/dankito/banking/BankingPresenterSwift.kt delete mode 100644 ui/BankingUiNativeIntegration/src/iosMain/kotlin/net/dankito/banking/UiExtensions.kt delete mode 100644 ui/BankingiOSApp/BankingiOSApp.xcodeproj/project.pbxproj delete mode 100644 ui/BankingiOSApp/BankingiOSApp.xcodeproj/xcshareddata/xcschemes/BankingiOSApp.xcscheme delete mode 100644 ui/BankingiOSApp/BankingiOSApp.xcworkspace/contents.xcworkspacedata delete mode 100644 ui/BankingiOSApp/BankingiOSApp/AppDelegate.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-1024@1x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-20@2x-1.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-20@2x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-20@3x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-29@2x-1.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-29@2x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-29@3x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-40@2x-2.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-40@2x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-40@3x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-60@2x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-60@3x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-76@2x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIcon.appiconset/icon-ios-83.5@2x.png delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIconInApp.imageset/Contents.json delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/AppIconInApp.imageset/icon-ios.svg delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/BankTransfer.imageset/BankTransfer.pdf delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/BankTransfer.imageset/Contents.json delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/Contents.json delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/Settings.imageset/Contents.json delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/Settings.imageset/gear.fill.pdf delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/accounts.imageset/Contents.json delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/accounts.imageset/accounts.pdf delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/new.imageset/Contents.json delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Assets.xcassets/new.imageset/new.pdf delete mode 100644 ui/BankingiOSApp/BankingiOSApp/BankIconFinder/Favicon.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/BankIconFinder/FaviconFinder.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/BankIconFinder/FaviconType.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/BankIconFinder/Size.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/BankIconFinder/SwiftBankIconFinder.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/BankIconFinder/UrlUtil.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/BankingiOSApp.xcdatamodeld/.xccurrentversion delete mode 100644 ui/BankingiOSApp/BankingiOSApp/BankingiOSApp.xcdatamodeld/BankingiOSApp.xcdatamodel/contents delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Base.lproj/LaunchScreen.storyboard delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Base.lproj/Localizable.strings delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Info.plist delete mode 100644 ui/BankingiOSApp/BankingiOSApp/InterceptTabClickViewController.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Preview Content/Preview Assets.xcassets/Contents.json delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Preview Content/PreviewData.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/SceneDelegate.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Security/AuthenticationService.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Security/AuthenticationType.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Security/BiometricAuthenticationService.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/Security/KeychainPasswordItem.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/TabBarController.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/de.lproj/Localizable.strings delete mode 100644 ui/BankingiOSApp/BankingiOSApp/extensions/Extensions.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/extensions/SwiftExtensions.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/extensions/UIKitExtensions.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/extensions/ViewExtensions.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/fints4k/DispatchQueueAsyncRunner.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/fints4k/UrlSessionWebClient.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/persistence/AppData.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/persistence/CoreDataBankingPersistence.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/persistence/EnterTanState.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/persistence/Mapper.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/AdaptsToKeyboard.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/DependencyInjector.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/Message.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/Messages.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/SelectorWrapper.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/Styles.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/SwiftUiRouter.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/ActionSheet.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/LabelledUIKitTextField.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/LabelledUIKitTextFieldWithValidationLabel.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/SelectableUILabel.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/UIAlert.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/UIAlertBase.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/UIKitActivityIndicator.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/UIKitButton.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/UIKitImageView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/UIKitSearchBar.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/UIKit/UIKitTextField.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/AccountTransactionDetailsDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/AccountTransactionsDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/AccountsDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/AddAccountDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/BankAccountSettingsDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/BankSettingsDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/EnterTanDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/LoginDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/ProtectAppSettingsDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/ScanQrCodeViewController.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/SelectBankDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/SettingsDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/dialogs/TransferMoneyDialog.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/AddAccountButtonView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/AmountLabel.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/BankCredentialsPasswordView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/CollapsibleText.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/Divider.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/FaceIDButton.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/IconView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/IconedTitleView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/InfoButton.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/InfoLabel.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/LabelledAmount.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/LabelledObject.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/LabelledValue.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/LazyView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/RealTimeTransferInfoView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/SearchBarWithLabel.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/SectionHeaderWithRightAlignedEditButton.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/SectionWithoutBackground.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/SelectableText.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/TextWithScrollView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/TouchIDButton.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/UpdateButton.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/ValidationLabel.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/VerticalLabelledValue.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/listitems/AccountTransactionListItem.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/listitems/AllBanksListItem.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/listitems/BankAccountListItem.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/listitems/BankInfoListItem.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/listitems/BankListItem.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/listitems/CheckmarkListItem.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/listitems/RecipientListItem.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/tan/FlickerCodeAnimator.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/tan/FlickerCodeStripe.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/tan/FlickerCodeTanView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/tan/ImageTanView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/tan/ScaleImageView.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/tan/TanGeneratorPositionMarker.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/tan/TanMethodPicker.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/ui/views/tan/TrianglePointingDown.swift delete mode 100644 ui/BankingiOSApp/BankingiOSApp/util/Stopwatch.swift delete mode 100644 ui/BankingiOSApp/BankingiOSAppTests/BankIconFinder/SwiftBankIconFinderTest.swift delete mode 100644 ui/BankingiOSApp/BankingiOSAppTests/BankingiOSAppTests.swift delete mode 100644 ui/BankingiOSApp/BankingiOSAppTests/Info.plist delete mode 100644 ui/BankingiOSApp/BankingiOSAppUITests/BankingiOSAppUITests.swift delete mode 100644 ui/BankingiOSApp/BankingiOSAppUITests/Info.plist delete mode 100644 ui/BankingiOSApp/Podfile delete mode 100644 ui/BankingiOSApp/Podfile.lock delete mode 100755 ui/BankingiOSApp/Pods/EncryptedCoreData/Incremental Store/EncryptedStore.h delete mode 100755 ui/BankingiOSApp/Pods/EncryptedCoreData/Incremental Store/EncryptedStore.m delete mode 100644 ui/BankingiOSApp/Pods/EncryptedCoreData/LICENSE delete mode 100644 ui/BankingiOSApp/Pods/EncryptedCoreData/README.md delete mode 100644 ui/BankingiOSApp/Pods/Local Podspecs/EncryptedCoreData.podspec.json delete mode 100644 ui/BankingiOSApp/Pods/Manifest.lock delete mode 100644 ui/BankingiOSApp/Pods/Pods.xcodeproj/project.pbxproj delete mode 100644 ui/BankingiOSApp/Pods/SQLCipher/LICENSE delete mode 100644 ui/BankingiOSApp/Pods/SQLCipher/README.md delete mode 100644 ui/BankingiOSApp/Pods/SQLCipher/sqlite3.c delete mode 100644 ui/BankingiOSApp/Pods/SQLCipher/sqlite3.h delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/EncryptedCoreData/EncryptedCoreData-Info.plist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/EncryptedCoreData/EncryptedCoreData-dummy.m delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/EncryptedCoreData/EncryptedCoreData-prefix.pch delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/EncryptedCoreData/EncryptedCoreData-umbrella.h delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/EncryptedCoreData/EncryptedCoreData.debug.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/EncryptedCoreData/EncryptedCoreData.modulemap delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/EncryptedCoreData/EncryptedCoreData.release.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-Info.plist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-acknowledgements.markdown delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-acknowledgements.plist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-dummy.m delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-frameworks-Debug-input-files.xcfilelist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-frameworks-Debug-output-files.xcfilelist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-frameworks-Release-input-files.xcfilelist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-frameworks-Release-output-files.xcfilelist delete mode 100755 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-frameworks.sh delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests-umbrella.h delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests.debug.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests.modulemap delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp-BankingiOSAppUITests/Pods-BankingiOSApp-BankingiOSAppUITests.release.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-Info.plist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-acknowledgements.markdown delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-acknowledgements.plist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-dummy.m delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-frameworks-Debug-input-files.xcfilelist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-frameworks-Debug-output-files.xcfilelist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-frameworks-Release-input-files.xcfilelist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-frameworks-Release-output-files.xcfilelist delete mode 100755 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-frameworks.sh delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp-umbrella.h delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp.debug.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp.modulemap delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSApp/Pods-BankingiOSApp.release.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSAppTests/Pods-BankingiOSAppTests-Info.plist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSAppTests/Pods-BankingiOSAppTests-acknowledgements.markdown delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSAppTests/Pods-BankingiOSAppTests-acknowledgements.plist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSAppTests/Pods-BankingiOSAppTests-dummy.m delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSAppTests/Pods-BankingiOSAppTests-umbrella.h delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSAppTests/Pods-BankingiOSAppTests.debug.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSAppTests/Pods-BankingiOSAppTests.modulemap delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/Pods-BankingiOSAppTests/Pods-BankingiOSAppTests.release.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/SQLCipher/SQLCipher-Info.plist delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/SQLCipher/SQLCipher-dummy.m delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/SQLCipher/SQLCipher-prefix.pch delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/SQLCipher/SQLCipher-umbrella.h delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/SQLCipher/SQLCipher.debug.xcconfig delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/SQLCipher/SQLCipher.modulemap delete mode 100644 ui/BankingiOSApp/Pods/Target Support Files/SQLCipher/SQLCipher.release.xcconfig delete mode 100644 ui/fints4kBankingClient/build.gradle delete mode 100644 ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/extensions/AmountExtensions.kt delete mode 100644 ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClient.kt delete mode 100644 ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/fints4kBankingClientCreator.kt delete mode 100644 ui/fints4kBankingClient/src/commonMain/kotlin/net/dankito/banking/mapper/fints4kModelMapper.kt delete mode 100644 ui/fints4kBankingClient/src/main/AndroidManifest.xml delete mode 100644 ui/hbci4jBankingClient/build.gradle delete mode 100644 ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/HbciCallback.kt delete mode 100644 ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/hbci4jBankingClient.kt delete mode 100644 ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/hbci4jBankingClientCreator.kt delete mode 100644 ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/model/AccountCredentials.kt delete mode 100755 ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/model/ConnectResult.kt delete mode 100644 ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/util/AccountTransactionMapper.kt delete mode 100644 ui/hbci4jBankingClient/src/main/kotlin/net/dankito/banking/util/hbci4jModelMapper.kt diff --git a/build.gradle b/build.gradle index 0a418aa8..3892b7e0 100644 --- a/build.gradle +++ b/build.gradle @@ -2,99 +2,12 @@ ext { appVersionName = '1.0.0-Alpha-10' - appVersionCode = 10 - /* MPP / basic dependencies */ - kotlinVersion = '1.4.21' - kotlinCoroutinesVersion = "1.3.7" - - - ktorVersion = "1.4.2" - javaUtilsVersion = '1.0.18' - luceneUtilsVersion = "0.6.0" - - - textExtractorVersion = "0.6.0" - - textInfoExtractorVersion = "1.0.1" - - commonsCsvVersion = "1.8" - - - hbci4jVersion = '3.1.37' - - - /* iOS */ - - iOSIsRealDevice = false - embedBitcodeValue = "marker" // Use "marker" to embed the bitcode marker (for debug builds) -// embedBitcodeValue = "bitcode" // for release binaries - - - /* Java */ - - faviconFinderVersion = "1.0.0" - - - /* Android */ - - androidCompileSdkVersion = 30 - - androidBuildToolsVersion = "30.0.3" - - androidMinSdkVersion = 21 // TODO: fix SSLv3 / TLS and set back to 16 - - androidTargetSdkVersion = 30 - - - fileChooserDialogVersion = "1.3.1-androidx" - - androidUtilsVersion = '1.1.2' - - fastAdapterVersion = "5.2.4" - - materialDrawerVersion = "8.1.6" - - clansFloatingActionButtonVersion = '1.6.4' - - autocompleteVersion = "1.1.0" - - zxingVersion = "3.3.0" - - scytaleVersion = "1.0.1" - - multiDexVersion = "2.0.1" - - appCompatVersion = "1.1.0" - - androidXCoreVersion = "1.3.1" - - androidXNavigationVersion = "2.3.0" - - androidXBiometricVersion = "1.0.1" - - constraintLayoutVersion = "1.1.3" - - materialComponentsVersion = "1.1.0" - - daggerVersion = "2.27" - - roomVersion = "2.2.5" - - sqlCipherVersion = "4.4.0" - - bcryptVersion = "0.9.0" - - - /* JavaFX */ - - javaFxUtilsVersion = '1.0.9' - /* Test */ @@ -113,17 +26,13 @@ ext { } buildscript { - ext.kotlin_version = '1.3.72' -// ext.kotlin_version = '1.4.10' - repositories { + mavenCentral() google() - jcenter() } + dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" -// classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" // Nexus staging plugin has to be downgraded to 0.10.0 to be applicable to sub projects, see https://github.com/UweTrottmann/SeriesGuide/commit/ca33e8ad2fa6cc5c426450c8aef3417ba073ca7f classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.10.0" @@ -142,10 +51,9 @@ allprojects { mavenLocal() mavenCentral() google() - jcenter() } - group 'net.dankito.banking' + group 'net.codinux.banking' version appVersionName } @@ -154,26 +62,6 @@ allprojects { task jarAll { dependsOn = [ "common:jvmJar", - "fints4k:jvm6Jar", - "fints4k-jvm:jar", - "BankFinder:jvmJar", - "EpcQrCodeParser:jvmJar", - "BankingUiCommon:jvmJar", - "fints4kBankingClient:jvmJar", - "BankingUiCommon:jvmJar", - "BankingJavaFxControls:jar", - "BankingJavaFxApp:jar" - ] -} - -task packAllForXcode { - dependsOn = [ - "common:packForXcode", - "fints4k:packForXcode", - "BankFinder:packForXcode", - "EpcQrCodeParser:packForXcode", - "BankingUiCommon:packForXcode", - "fints4kBankingClient:packForXcode", - "BankingUiNativeIntegration:packForXcode" + "fints4k:jvmJar", ] } \ No newline at end of file diff --git a/common/build.gradle b/common/build.gradle index 6b146195..66bb7f9a 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -1,41 +1,52 @@ plugins { id "org.jetbrains.kotlin.multiplatform" - id "com.android.library" id "maven-publish" } ext.artifactName = "multiplatform-utils" -def frameworkName = "MultiplatformUtils" - kotlin { jvm { - compilations.main.kotlinOptions { - jvmTarget = "1.6" + compilations.all { + kotlinOptions.jvmTarget = '1.8' + } + withJava() + testRuns["test"].executionTask.configure { + useJUnitPlatform() } } - targets { - final def iOSTarget = iOSIsRealDevice ? presets.iosArm64 : presets.iosX64 +// js(BOTH) { +// browser { +// commonWebpackConfig { +// cssSupport.enabled = true +// } +// } +// } - fromPreset(iOSTarget, 'ios') { - binaries { - framework { - baseName = frameworkName - - embedBitcode(embedBitcodeValue) - } + ios { + binaries { + framework { + baseName = "MultiplatformUtils" } } } +// def hostOs = System.getProperty("os.name") +// def isMingwX64 = hostOs.startsWith("Windows") +// def nativeTarget +// if (hostOs == "Mac OS X") nativeTarget = macosX64('native') { binaries.executable() } +// else if (hostOs == "Linux") nativeTarget = linuxX64("native") { binaries.executable() } +// else if (isMingwX64) nativeTarget = mingwX64("native") { binaries.executable() } +// else throw new GradleException("Host OS is not supported in Kotlin/Native.") + sourceSets { commonMain { dependencies { - implementation kotlin("stdlib-common") + } } @@ -51,7 +62,6 @@ kotlin { jvmMain { dependencies { - api kotlin("stdlib-jdk7") compileOnly "org.slf4j:slf4j-api:$slf4jVersion" @@ -79,97 +89,9 @@ kotlin { iosMain { dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion" + } } } -} - - -task copyFramework { - def buildType = project.findProperty('kotlin.build.type') ?: 'DEBUG' - def target = project.findProperty('kotlin.target') ?: 'ios' - def framework = kotlin.targets."$target".binaries.getFramework(buildType) - - dependsOn framework.linkTask - - doLast { - def srcFile = framework.outputFile - def targetDir = getProperty('configuration.build.dir') - - copy { - from srcFile.parent - into targetDir - include "${frameworkName}.framework/**" - include "${frameworkName}.framework.dSYM" - } - } -} - -// Task to generate iOS framework for xcode projects. -task packForXcode(type: Sync) { - - final File frameworkDir = new File(buildDir, "xcode-frameworks") - final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG' - - final def framework = kotlin.targets.ios.binaries.getFramework("", mode) - - inputs.property "mode", mode - dependsOn framework.linkTask - - from { framework.outputFile.parentFile } - into frameworkDir - - doLast { - new File(frameworkDir, 'gradlew').with { - text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n" - setExecutable(true) - } - } -} - -// Run packForXcode when building. -tasks.build.dependsOn packForXcode - - -android { - compileSdkVersion androidCompileSdkVersion - - - defaultConfig { - minSdkVersion androidMinSdkVersion - targetSdkVersion androidTargetSdkVersion - - versionName version - versionCode appVersionCode - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - packagingOptions { - pickFirst 'META-INF/ktor-http.kotlin_module' - pickFirst 'META-INF/kotlinx-io.kotlin_module' - pickFirst 'META-INF/atomicfu.kotlin_module' - pickFirst 'META-INF/ktor-utils.kotlin_module' - pickFirst 'META-INF/kotlinx-coroutines-io.kotlin_module' - pickFirst 'META-INF/ktor-client-core.kotlin_module' - pickFirst 'META-INF/DEPENDENCIES' - pickFirst 'META-INF/NOTICE' - pickFirst 'META-INF/LICENSE' - pickFirst 'META-INF/LICENSE.txt' - pickFirst 'META-INF/NOTICE.txt' - } - - lintOptions { - abortOnError false - } - } \ No newline at end of file diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml deleted file mode 100644 index d7b5d1bf..00000000 --- a/common/src/main/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/fints4k-jvm/build.gradle b/fints4k-jvm/build.gradle deleted file mode 100644 index 377323fc..00000000 --- a/fints4k-jvm/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -apply plugin: 'java-library' -apply plugin: 'kotlin' - -sourceCompatibility = "1.7" -targetCompatibility = "1.7" - - -dependencies { - api project(":fints4k") -} \ No newline at end of file diff --git a/fints4k/build.gradle b/fints4k/build.gradle index f10bf355..ac9b8aaa 100644 --- a/fints4k/build.gradle +++ b/fints4k/build.gradle @@ -1,96 +1,75 @@ - -buildscript { - repositories { - jcenter() - } -} - plugins { id "org.jetbrains.kotlin.multiplatform" - id "com.android.library" id "maven-publish" } kotlin { - jvm("jvm6") { - compilations.main.kotlinOptions { - jvmTarget = "1.6" + jvm { + compilations.all { + kotlinOptions.jvmTarget = '1.8' + } + withJava() + testRuns["test"].executionTask.configure { + useJUnitPlatform() } } - android() +// js(BOTH) { +// browser { +// commonWebpackConfig { +// cssSupport.enabled = true +// } +// } +// } - targets { - final def iOSTarget = iOSIsRealDevice ? presets.iosArm64 : presets.iosX64 - - fromPreset(iOSTarget, 'ios') { - binaries { - framework { - baseName = "fints4k" - - embedBitcode(embedBitcodeValue) - - export(project(":common")) - } + ios { + binaries { + framework { + baseName = "fints4k" } } } - js() { - - nodejs { - testTask { - enabled = false - } - } - - browser { - testTask { - enabled = false - } - - } - } +// def hostOs = System.getProperty("os.name") +// def isMingwX64 = hostOs.startsWith("Windows") +// def nativeTarget +// if (hostOs == "Mac OS X") nativeTarget = macosX64('native') { binaries.executable() } +// else if (hostOs == "Linux") nativeTarget = linuxX64("native") { binaries.executable() } +// else if (isMingwX64) nativeTarget = mingwX64("native") { binaries.executable() } +// else throw new GradleException("Host OS is not supported in Kotlin/Native.") sourceSets { commonMain { dependencies { - implementation kotlin("stdlib-common") - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$kotlinCoroutinesVersion" - api project(":common") + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion" + implementation "io.ktor:ktor-client-core:$ktorVersion" } } commonTest { dependencies { - implementation kotlin("test-common") - implementation kotlin("test-annotations-common") + implementation kotlin("test") implementation "ch.tutteli.atrium:atrium-fluent-en_GB-common:$atriumVersion" } } - jvm6Main { + jvmMain { dependencies { -// implementation "io.ktor:ktor-client-cio:$ktorVersion" implementation "io.ktor:ktor-client-okhttp:$ktorVersion" implementation "org.slf4j:slf4j-api:$slf4jVersion" } } - jvm6Test { + jvmTest { dependencies { - implementation kotlin("test-junit") - - implementation "org.junit.jupiter:junit-jupiter:$junit5Version" - runtimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" implementation "org.assertj:assertj-core:$assertJVersion" implementation "org.mockito:mockito-core:$mockitoVersion" @@ -98,9 +77,9 @@ kotlin { implementation "ch.tutteli.atrium:atrium-fluent-en_GB:$atriumVersion" - implementation project(":BankingUiCommon") - implementation project(":BankFinder") - implementation project(":fints4kBankingClient") +// implementation project(":BankingUiCommon") +// implementation project(":BankFinder") +// implementation project(":fints4kBankingClient") implementation "org.apache.commons:commons-csv:1.8" @@ -111,111 +90,36 @@ kotlin { } - androidMain { - dependsOn jvm6Main +// jsMain { +// dependencies { +// implementation "io.ktor:ktor-client-js:$ktorVersion" +// } +// } +// +// jsTest { +// +// } - dependencies { - implementation "io.ktor:ktor-client-android:$ktorVersion" - } - } iosMain { dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion" + // ktor Native needs "-native-mt" coroutines version. Export it so that referencing applications don't need to import it on their own + api("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion-native-mt") implementation "io.ktor:ktor-client-ios:$ktorVersion" - implementation "io.ktor:ktor-client-core-native:$ktorVersion" } } - jsMain { - dependsOn commonMain - + nativeMain { dependencies { - api kotlin("stdlib-js") + // ktor Native needs "-native-mt" coroutines version. Export it so that referencing applications don't need to import it on their own + api"org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion-native-mt" - implementation "io.ktor:ktor-client-js:$ktorVersion" - implementation "io.ktor:ktor-client-encoding-js:$ktorVersion" - implementation "io.ktor:ktor-client-js-kotlinMultiplatform:$ktorVersion" - } - } - - jsTest { - dependencies { - implementation kotlin("test-js") - - implementation "ch.tutteli.atrium:atrium-fluent-en_GB-js:$atriumVersion" + // requires cURL to be installed on your system + implementation "io.ktor:ktor-client-curl:$ktorVersion" } } } -} - - -// Task to generate iOS framework for xcode projects. -task packForXcode(type: Sync) { - - final File frameworkDir = new File(buildDir, "xcode-frameworks") - final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG' - - final def framework = kotlin.targets.ios.binaries.getFramework("", mode) - - inputs.property "mode", mode - dependsOn framework.linkTask - - from { framework.outputFile.parentFile } - into frameworkDir - - doLast { - new File(frameworkDir, 'gradlew').with { - text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n" - setExecutable(true) - } - } -} - -// Run packForXcode when building. -tasks.build.dependsOn packForXcode - - -android { - compileSdkVersion androidCompileSdkVersion - - - defaultConfig { - minSdkVersion androidMinSdkVersion - targetSdkVersion androidTargetSdkVersion - - versionName version - versionCode appVersionCode - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - packagingOptions { - pickFirst 'META-INF/ktor-http.kotlin_module' - pickFirst 'META-INF/kotlinx-io.kotlin_module' - pickFirst 'META-INF/atomicfu.kotlin_module' - pickFirst 'META-INF/ktor-utils.kotlin_module' - pickFirst 'META-INF/kotlinx-coroutines-io.kotlin_module' - pickFirst 'META-INF/ktor-client-core.kotlin_module' - pickFirst 'META-INF/DEPENDENCIES' - pickFirst 'META-INF/NOTICE' - pickFirst 'META-INF/LICENSE' - pickFirst 'META-INF/LICENSE.txt' - pickFirst 'META-INF/NOTICE.txt' - } - - lintOptions { - abortOnError false - } - } \ No newline at end of file diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/MessageBuilderResult.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/MessageBuilderResult.kt index a6497ce6..278c71c4 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/MessageBuilderResult.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/messages/MessageBuilderResult.kt @@ -24,7 +24,7 @@ open class MessageBuilderResult( } open val getHighestAllowedVersion: Int? - get() = allowedVersions.max() + get() = allowedVersions.maxOrNull() open fun isSendEnteredTanMessage(): Boolean { // contains only a ZweiSchrittTanEinreichung segment diff --git a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/webclient/KtorWebClient.kt b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/webclient/KtorWebClient.kt index e4e911b6..4137579c 100644 --- a/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/webclient/KtorWebClient.kt +++ b/fints4k/src/commonMain/kotlin/net/dankito/banking/fints/webclient/KtorWebClient.kt @@ -2,10 +2,10 @@ package net.dankito.banking.fints.webclient import io.ktor.client.HttpClient import io.ktor.client.request.post -import io.ktor.client.statement.HttpResponse -import io.ktor.client.statement.readText -import io.ktor.content.TextContent +import io.ktor.client.request.setBody +import io.ktor.client.statement.bodyAsText import io.ktor.http.ContentType +import io.ktor.http.contentType import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.cancel @@ -38,11 +38,12 @@ open class KtorWebClient : IWebClient { override fun post(url: String, body: String, contentType: String, userAgent: String, callback: (WebClientResponse) -> Unit) { GlobalScope.async { try { - val clientResponse = client.post(url) { - this.body = TextContent(body, contentType = ContentType.Application.OctetStream) + val clientResponse = client.post(url) { + contentType(ContentType.Application.OctetStream) + setBody(body) } - val responseBody = clientResponse.readText() + val responseBody = clientResponse.bodyAsText() callback(WebClientResponse(clientResponse.status.value == 200, clientResponse.status.value, body = responseBody)) } catch (e: Exception) { diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/MessageBuilderTest.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/MessageBuilderTest.kt index fb5708ea..b8413ad5 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/MessageBuilderTest.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/messages/MessageBuilderTest.kt @@ -15,6 +15,7 @@ import net.dankito.banking.fints.util.FinTsUtils import net.dankito.utils.multiplatform.Date import net.dankito.utils.multiplatform.Month import kotlin.test.AfterTest +import kotlin.test.Ignore import kotlin.test.Test @@ -191,6 +192,7 @@ class MessageBuilderTest : FinTsTestBase() { )) } + @Ignore @Test fun createGetTransactionsMessage_WithContinuationIdSet() { diff --git a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/response/ResponseParserTest.kt b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/response/ResponseParserTest.kt index 6c69c463..79a9e288 100644 --- a/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/response/ResponseParserTest.kt +++ b/fints4k/src/commonTest/kotlin/net/dankito/banking/fints/response/ResponseParserTest.kt @@ -17,6 +17,7 @@ import net.dankito.banking.fints.extensions.isFalse import net.dankito.banking.fints.extensions.isTrue import net.dankito.banking.fints.model.Amount import net.dankito.utils.multiplatform.Date +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.fail @@ -460,6 +461,7 @@ class ResponseParserTest : FinTsTestBase() { ?: run { fail("No segment of type UserParameters found in ${result.receivedSegments}") } } + @Ignore @Test fun parseAccountInfo() { @@ -1315,9 +1317,9 @@ class ResponseParserTest : FinTsTestBase() { assertCouldParseSegment(segment, segmentId, segmentNumber, segmentVersion, referenceSegmentNumber) } - private fun assertCouldParseSegment(segment: ReceivedSegment?, segmentId: ISegmentId, segmentNumber: Int, + private fun assertCouldParseSegment(segment: ReceivedSegment?, segmentId: ISegmentId, segmentNumber: Int, segmentVersion: Int, referenceSegmentNumber: Int?) { - + expect(segment).notToBeNull() segment?.let { @@ -1328,10 +1330,10 @@ class ResponseParserTest : FinTsTestBase() { } } - private fun assertCouldParseJobParametersSegment(segment: JobParameters?, segmentId: ISegmentId, segmentNumber: Int, + private fun assertCouldParseJobParametersSegment(segment: JobParameters?, segmentId: ISegmentId, segmentNumber: Int, segmentVersion: Int, referenceSegmentNumber: Int?, jobName: String, maxCountJobs: Int, minimumCountSignatures: Int, securityClass: Int?) { - + assertCouldParseSegment(segment, segmentId, segmentNumber, segmentVersion, referenceSegmentNumber) segment?.let { diff --git a/fints4k/src/jvm6Test/java/net/dankito/banking/fints/JavaShowcase.java b/fints4k/src/jvm6Test/java/net/dankito/banking/fints/JavaShowcase.java deleted file mode 100644 index 6803de47..00000000 --- a/fints4k/src/jvm6Test/java/net/dankito/banking/fints/JavaShowcase.java +++ /dev/null @@ -1,184 +0,0 @@ -package net.dankito.banking.fints; - -import net.dankito.banking.fints.banks.IBankFinder; -import net.dankito.banking.fints.banks.InMemoryBankFinder; -import net.dankito.banking.fints.callback.FinTsClientCallback; -import net.dankito.banking.fints.callback.SimpleFinTsClientCallback; -import net.dankito.banking.fints.model.AccountData; -import net.dankito.banking.fints.model.AccountFeature; -import net.dankito.banking.fints.model.AccountTransaction; -import net.dankito.banking.fints.model.BankData; -import net.dankito.banking.bankfinder.BankInfo; -import net.dankito.banking.fints.model.BankTransferData; -import net.dankito.banking.fints.model.CustomerData; -import net.dankito.banking.fints.model.EnterTanGeneratorAtcResult; -import net.dankito.banking.fints.model.EnterTanResult; -import net.dankito.banking.fints.model.TanChallenge; -import net.dankito.banking.fints.model.TanMethod; -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium; -import net.dankito.banking.fints.model.mapper.BankDataMapper; -import net.dankito.banking.fints.response.client.AddAccountResponse; -import net.dankito.banking.fints.response.client.FinTsClientResponse; -import net.dankito.banking.fints.response.client.GetTransactionsResponse; -import net.dankito.banking.fints.util.Java8Base64Service; - -import java.math.BigDecimal; -import java.util.List; - - -public class JavaShowcase { - - public static void main(String[] args) { - JavaShowcase showcase = new JavaShowcase(); - - showcase.basicShowcase(); - - showcase.advancedShowcase(); - } - - private void basicShowcase() { - // Set your bank code (Bankleitzahl) here. - // BankInfo contains e.g. a bank's FinTS server address, country code and BIC (needed for money transfer) - List foundBanks = new InMemoryBankFinder().findBankByNameBankCodeOrCity(""); - - if (foundBanks.isEmpty() == false) { // please also check if bank supports FinTS 3.0 - BankData bank = new BankDataMapper().mapFromBankInfo(foundBanks.get(0)); - - // set your customer data (customerId = username you use to log in; pin = online banking pin / password) - CustomerData customer = new CustomerData("", ""); - - FinTsClientCallback callback = new SimpleFinTsClientCallback(); // see advanced showcase for configuring callback - - FinTsClient finTsClient = new FinTsClient(callback, new Java8Base64Service()); - - AddAccountResponse addAccountResponse = finTsClient.addAccount(bank, customer); - - if (addAccountResponse.isSuccessful()) { - System.out.println("Successfully added account for " + bank.getBankCode() + " " + customer.getCustomerId()); - - if (addAccountResponse.getBookedTransactions().isEmpty() == false) { - System.out.println("Account transactions of last 90 days:"); - showGetTransactionsResponse(addAccountResponse); - } - } - else { - System.out.println("Could not add account for " + bank.getBankCode() + " " + customer.getCustomerId() + ":"); - showResponseError(addAccountResponse); - } - - // see advanced show case what else you can do with this library, e.g. retrieving all account transactions and transferring money - } - } - - private void advancedShowcase() { - IBankFinder bankFinder = new InMemoryBankFinder(); - - // Set your bank code (Bankleitzahl) here. Or create BankData manually. Required fields are: - // bankCode, bankCountryCode (Germany = 280), finTs3ServerAddress and for bank transfers bic - List foundBanks = bankFinder.findBankByBankCode(""); - - if (foundBanks.isEmpty() == false) { // please also check if bank supports FinTS 3.0 - BankData bank = new BankDataMapper().mapFromBankInfo(foundBanks.get(0)); - - // set your customer data (customerId = Kontonummer in most cases, pin = online banking pin) - CustomerData customer = new CustomerData("", ""); - - FinTsClientCallback callback = new FinTsClientCallback() { - - @Override - public TanMethod askUserForTanMethod(List supportedTanMethods, TanMethod suggestedTanMethod) { - // E.g. show a dialog to ask for user's TAN method. - // In most cases it's senseful to simply return suggestedTanMethod and to let - // user select TAN method when entering TAN is required (see enterTan() below) - return suggestedTanMethod; - } - - @Override - public EnterTanResult enterTan(CustomerData customer, TanChallenge tanChallenge) { - // e.g. show - // - Android: net.dankito.banking.ui.android.dialogs.EnterTanDialog - // - JavaFX: net.dankito.banking.ui.javafx.dialogs.tan.EnterTanDialog - return EnterTanResult.Companion.userDidNotEnterTan(); // user did not enter TAN. aborts operation - } - - @Override - public EnterTanGeneratorAtcResult enterTanGeneratorAtc(CustomerData customer, TanGeneratorTanMedium tanMedium) { - // needed only in rare cases to synchronize TAN generator for chipTAN methods. E.g. show - // - Android: net.dankito.banking.ui.android.dialogs.EnterAtcDialog - return EnterTanGeneratorAtcResult.Companion.userDidNotEnterAtc(); // user did not enter TAN and ATC. aborts operation - } - }; - - - // may also check if FinTsClientForCustomer fits your needs, avoids passing bank and customer to each method - FinTsClient finTsClient = new FinTsClient(callback, new Java8Base64Service()); - - AddAccountResponse addAccountResponse = finTsClient.addAccount(bank, customer); - if (addAccountResponse.isSuccessful() == false) { - System.out.println("Could not add account for " + bank.getBankCode() + " " + customer.getCustomerId() + ":"); - showResponseError(addAccountResponse); - return; - } - - System.out.println("Successfully added account for " + bank.getBankCode() + " " + customer.getCustomerId()); - - - for (AccountData account : customer.getAccounts()) { // accounts are now retrieved - if (account.supportsFeature(AccountFeature.RetrieveAccountTransactions)) { - // Most banks support retrieving account transactions of last 90 without TAN, may also your bank. - // Alternatively call getTransactions() to retrieve all account transactions. But then entering a TAN is required. - GetTransactionsResponse response = finTsClient.tryGetTransactionsOfLast90DaysWithoutTan(bank, customer, account); - - showGetTransactionsResponse(response); - } - - if (account.supportsFeature(AccountFeature.TransferMoney)) { - // Transfer 0.01 € to yourself. Transferring money to one self doesn't require a TAN. - BankTransferData data = new BankTransferData(customer.getName(), account.getIban(), bank.getBic(), - new BigDecimal("0.01"), "Give me some money", false); - FinTsClientResponse transferMoneyResponse = finTsClient.doBankTransfer(data, bank, customer, account); - - if (transferMoneyResponse.isSuccessful()) { - System.out.println("Successfully transferred " + data.getAmount() + " to " + data.getCreditorIban()); - } - else { - showResponseError(transferMoneyResponse); - } - } - } - } - } - - private static void showGetTransactionsResponse(GetTransactionsResponse response) { - if (response.isSuccessful()) { - System.out.println("Balance (Saldo) = " + response.getBalance()); - - System.out.println("Account transactions (Umsätze):"); - for (AccountTransaction transaction : response.getBookedTransactions()) { - System.out.println(transaction.toString()); - } - } - else { - if (response.isStrongAuthenticationRequired()) { - System.out.println("Sorry, your bank doesn't support retrieving account " + - "transactions of last 90 days without TAN"); - } - else { - System.out.println("An error occurred:"); - showResponseError(response); - } - } - } - - private static void showResponseError(FinTsClientResponse response) { - if (response.getException() != null) { // something severe occurred - System.out.println(response.getException().getMessage()); - } - - // error messages retrieved from bank (e.g. PIN is wrong, message contains errors, ...) - for (String retrievedErrorMessage : response.getErrorsToShowToUser()) { - System.out.println(retrievedErrorMessage); - } - } - -} diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt b/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt deleted file mode 100644 index a47a82d4..00000000 --- a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt +++ /dev/null @@ -1,269 +0,0 @@ -package net.dankito.banking.fints - -import ch.tutteli.atrium.api.fluent.en_GB.* -import ch.tutteli.atrium.api.verbs.expect -import net.dankito.banking.bankfinder.InMemoryBankFinder -import net.dankito.banking.fints.callback.FinTsClientCallback -import net.dankito.banking.fints.extensions.isTrue -import net.dankito.banking.fints.extensions.isFalse -import net.dankito.banking.fints.messages.datenelemente.implementierte.Dialogsprache -import net.dankito.banking.fints.messages.datenelemente.implementierte.KundensystemStatus -import net.dankito.banking.fints.messages.datenelemente.implementierte.KundensystemStatusWerte -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanEinsatzOption -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse -import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId -import net.dankito.banking.fints.model.* -import net.dankito.banking.fints.response.client.* -import net.dankito.utils.multiplatform.Date -import net.dankito.utils.multiplatform.DateFormatter -import net.dankito.utils.multiplatform.UUID -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicReference -import kotlin.test.DefaultAsserter.fail -import kotlin.test.Ignore -import kotlin.test.Test - - -@Ignore // not an automatic test, supply your settings below -open class FinTsClientTestBase { - - companion object { - - // TODO: add your settings here: - val BankCode = "" - - val CustomerId = "" - - val Password = "" - - - val DateTimeFormatForUniqueBankTransferReference = DateFormatter("yyyy-MM-dd'T'HH:mm:ss.SSS") - } - - - private var didAskUserForTanMethod = false - - private var didAskUserToEnterTan = false - - - private val callback = object : FinTsClientCallback { - - override fun askUserForTanMethod(supportedTanMethods: List, suggestedTanMethod: TanMethod?, callback: (TanMethod?) -> Unit) { - didAskUserForTanMethod = true - callback(suggestedTanMethod) // simply return suggestedTanMethod as in most cases it's the best fitting one - } - - override fun enterTan(bank: BankData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { - didAskUserToEnterTan = true - - callback(EnterTanResult.userDidNotEnterTan()) - } - - override fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { - fail("Bank asks you to synchronize your TAN generator for card ${tanMedium.cardNumber} " + - "(card sequence number ${tanMedium.cardSequenceNumber}). Please do this via your online banking portal or Banking UI.") - } - - } - - - private val underTest = FinTsClient(callback) - - - private val BankDataAnonymous = BankData.anonymous("10070000", "https://fints.deutsche-bank.de/", "DEUTDEBBXXX") - - private val bankInfo = InMemoryBankFinder().findBankByBankCode(BankCode).first() - private val Bank = BankData(bankInfo.bankCode, CustomerId, Password, bankInfo.pinTanAddress ?: "", bankInfo.bic, bankInfo.name) - - - - @Test - fun getAnonymousBankInfo() { - - // when - underTest.getAnonymousBankInfo(BankDataAnonymous) { result -> - - // then - expect(result.successful).isTrue() - expect(BankDataAnonymous.supportedHbciVersions).isNotEmpty() - expect(BankDataAnonymous.tanMethodsSupportedByBank).isNotEmpty() - expect(BankDataAnonymous.supportedJobs).isNotEmpty() - expect(BankDataAnonymous.supportedLanguages).isNotEmpty() - expect(BankDataAnonymous.bankName).isNotEmpty() - } - } - - - @Test - fun addAccount() { - - // given - val response = AtomicReference() - val countDownLatch = CountDownLatch(1) - - - // when - underTest.addAccountAsync(Bank.toAddAccountParameter()) { - response.set(it) - countDownLatch.countDown() - } - - - // then - countDownLatch.await(30, TimeUnit.SECONDS) - val result = response.get() - - expect(result.successful).isTrue() - - expect(didAskUserForTanMethod).isFalse() - - expect(Bank.bankName).isNotEmpty() - expect(Bank.supportedJobs).isNotEmpty() // supported jobs are now known - expect(Bank.tanMethodsSupportedByBank).isNotEmpty() // supported tan methods are now known - expect(Bank.supportedHbciVersions).isNotEmpty() // supported HBIC versions are now known - expect(Bank.supportedLanguages).isNotEmpty() // supported languages are now known - - expect(Bank.customerName).isNotEmpty() - expect(Bank.tanMethodsAvailableForUser).isNotEmpty() - expect(Bank.selectedLanguage).notToBe(Dialogsprache.Default) // language is set now - expect(Bank.customerSystemId).notToBe(KundensystemStatus.SynchronizingCustomerSystemId.code) // customer system id is now set - expect(Bank.customerSystemStatus).toBe(KundensystemStatusWerte.Benoetigt) // customerSystemStatus is set now - expect(Bank.accounts).isNotEmpty() // accounts are now known - expect(Bank.accounts.first().allowedJobs).isNotEmpty() // allowed jobs are now known - } - - - @ExperimentalWithOptions - @Test - fun getTransactions() { - - // given - val response = AtomicReference() - val countDownLatch = CountDownLatch(1) - - underTest.addAccountAsync(Bank.toAddAccountParameter(false)) { // retrieve basic data, e.g. accounts - val account = Bank.accounts.firstOrNull { it.supportsFeature(AccountFeature.RetrieveAccountTransactions) } - expect(account).withRepresentation("We need at least one account that supports retrieving account transactions (${CustomerSegmentId.AccountTransactionsMt940.id})").notToBeNull() - - // when - - // some banks support retrieving account transactions of last 90 days without TAN - underTest.tryGetAccountTransactionsOfLast90DaysWithoutTan(Bank, account!!) { - response.set(it) - countDownLatch.countDown() - } - } - - - // then - countDownLatch.await(30, TimeUnit.SECONDS) - val result = response.get() - - expect(result.successful).isTrue() - expect(result.retrievedData.map { it.bookedTransactions }).isNotEmpty() - } - - - @Test - fun getTanMediaList() { - - // this test is only senseful for accounts using chipTAN / TAN generator as TAN method - - // given - val response = AtomicReference() - val countDownLatch = CountDownLatch(1) - val anonymousBankInfoCountDownLatch = CountDownLatch(1) - - - underTest.getAnonymousBankInfo(Bank) { - anonymousBankInfoCountDownLatch.countDown() - } - anonymousBankInfoCountDownLatch.await(30, TimeUnit.SECONDS) - - - val supportsRetrievingTanMedia = Bank.supportedJobs.firstOrNull { it.jobName == "HKTAB" } != null - - if (supportsRetrievingTanMedia == false) { // accounts with appTAN, pushTAN, smsTAN, ... would fail here -> simply return - println("Bank ${Bank.bankName} does not support retrieving TAN media. Therefore cannot execute test getTanMediaList()") - return - } - - expect(Bank.tanMedia).isEmpty() - - - // when - underTest.getTanMediaList(Bank, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien) { result -> - response.set(result) - countDownLatch.countDown() - } - - // then - countDownLatch.await(30, TimeUnit.SECONDS) - val result = response.get() - - expect(result.successful).isTrue() - - expect(result.tanMediaList).notToBeNull() - expect(result.tanMediaList!!.usageOption).toBe(TanEinsatzOption.KundeKannGenauEinMediumZuEinerZeitNutzen) // TODO: may adjust to your value - expect(result.tanMediaList!!.tanMedia).isNotEmpty() - - expect(Bank.tanMedia).isNotEmpty() - } - - @Ignore // only works with banks that don't support HKTAB version 5 - @Test - fun getTanMediaList_UnsupportedTanMediumClass() { - - // when - expect { - underTest.getTanMediaList(Bank, TanMedienArtVersion.Alle, TanMediumKlasse.BilateralVereinbart) { } - }.toThrow() - - - // then - // exception gets thrown - } - - - @ExperimentalWithOptions - @Test - fun testBankTransfer() { - - // given - val response = AtomicReference() - val countDownLatch = CountDownLatch(1) - - underTest.addAccountAsync(Bank.toAddAccountParameter(false)) { // retrieve basic data, e.g. accounts - // we need at least one account that supports cash transfer - val account = Bank.accounts.firstOrNull { it.supportsFeature(AccountFeature.TransferMoney) } - expect(account).withRepresentation("We need at least one account that supports cash transfer (${CustomerSegmentId.SepaBankTransfer.id})").notToBeNull() - - // IBAN should be set - expect(account?.iban).withRepresentation("Account IBAN must be set").notToBeNull() - - // transfer 1 cent to yourself. Transferring money to oneself also doesn't require to enter a TAN according to PSD2 - val BankTransferData = BankTransferData(Bank.customerName, account?.iban!!, Bank.bic, Money(Amount("0,01"), "EUR"), - "${DateTimeFormatForUniqueBankTransferReference.format(Date())} Test transaction ${UUID.random()}") - - - // when - underTest.doBankTransferAsync(BankTransferData, Bank, account) { result -> - response.set(result) - countDownLatch.countDown() - } - - } - - - // then - countDownLatch.await(30, TimeUnit.SECONDS) - val result = response.get() - - expect(result.successful).isTrue() - - } - -} \ No newline at end of file diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt b/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt deleted file mode 100644 index 8cb41eb7..00000000 --- a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt +++ /dev/null @@ -1,317 +0,0 @@ -package net.dankito.banking.fints.bankdetails - -import kotlinx.coroutines.runBlocking -import net.dankito.banking.bankfinder.InMemoryBankFinder -import net.dankito.banking.fints.callback.NoOpFinTsClientCallback -import net.dankito.banking.fints.messages.MessageBuilder -import net.dankito.banking.fints.messages.MessageBuilderResult -import net.dankito.banking.fints.messages.Separators -import net.dankito.banking.fints.messages.datenelemente.implementierte.Dialogsprache -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AuftraggeberkontoErforderlich -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.BezeichnungDesTanMediumsErforderlich -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.SmsAbbuchungskontoErforderlich -import net.dankito.banking.fints.model.* -import net.dankito.banking.bankfinder.BankInfo -import net.dankito.banking.fints.FinTsJobExecutor -import net.dankito.banking.fints.callback.SimpleFinTsClientCallback -import net.dankito.banking.fints.model.mapper.ModelMapper -import net.dankito.banking.fints.response.BankResponse -import net.dankito.banking.fints.response.segments.SepaAccountInfoParameters -import net.dankito.banking.fints.response.segments.TanInfo -import net.dankito.banking.fints.response.segments.TanMethodParameters -import net.dankito.banking.fints.util.* -import org.apache.commons.csv.CSVFormat -import org.apache.commons.csv.CSVPrinter -import org.junit.Ignore -import kotlin.test.Test -import org.slf4j.LoggerFactory -import java.io.File -import java.io.FileWriter -import java.text.SimpleDateFormat -import java.util.* -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicReference - - -@Ignore // not a real test, run manually to retrieve FinTS information from all banks -class BanksFinTsDetailsRetriever { - - companion object { - private val OutputFolderDateFormat = SimpleDateFormat("yyyy_MM_dd_HH_mm_ss") - - private val log = LoggerFactory.getLogger(BanksFinTsDetailsRetriever::class.java) - } - - - private val bankFinder = InMemoryBankFinder() - - private val product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically - - private val messageBuilder = MessageBuilder() - - private val modelMapper = object : ModelMapper(messageBuilder) { - - fun mapToTanMethodTypePublic(parameters: TanMethodParameters): TanMethodType? { - return super.mapToTanMethodType(parameters) - } - - } - - private val jobExecutor = object : FinTsJobExecutor(modelMapper = modelMapper) { - - fun getAndHandleResponseForMessagePublic(context: JobContext, message: MessageBuilderResult, callback: (BankResponse) -> Unit) { - getAndHandleResponseForMessage(context, message, callback) - } - } - - - private val requestNotSuccessful = mutableListOf() - - private val tanMethodParameter = mutableMapOf>() - private val tanMethodTypes = mutableMapOf>() - - private val tanMethodParameterTechnicalIdentification = mutableSetOf() - private val tanMethodParameterVersionDkTanMethod = mutableSetOf() - - private val requiresSmsAbbuchungskonto = mutableListOf() - private val requiresAuftraggeberkonto = mutableListOf() - private val requiresChallengeClass = mutableListOf() - private val signatureStructured = mutableListOf() - private val requiresNameOfTanMedia = mutableListOf() - private val requiresHhdUcResponse = mutableListOf() - - private val doesNotSupportHKTAN6 = mutableListOf() - private val doesNotSupportHKSAL5or7 = mutableListOf() - private val doesNotSupportHKKAZ5to7 = mutableListOf() - private val doesNotSupportHKCCS1 = mutableListOf() - - private val supportsHhd13 = mutableListOf() - private val supportsHhd14 = mutableListOf() - - private val doesNotSupportPain_001_001_or_003_03 = mutableListOf() - - - @Test - fun retrieveAllBanksFinTsDetails() { - - val allBanks = bankFinder.getBankList() - val banksSupportingFinTs = allBanks.filter { it.supportsFinTs3_0 } - - val outputFolder = File("bankData", OutputFolderDateFormat.format(Date())) - val responsesFolder = File(outputFolder, "responses") - responsesFolder.mkdirs() - - val csvFile = FileWriter(File(outputFolder, "bank_details.csv")) - val csvPrinter = CSVPrinter(csvFile, CSVFormat.DEFAULT.withHeader( - "BLZ", "Name", "Ort", "BPD", "Tanverfahren", "Technische Tanverfahrennamen", "HHD 1.3?", "HHD 1.4?", - "HKTAN 6?", "HKTAN", "HKSAL 5?", "HKSAL", "HKKAZ 5-7?", "HKKAZ", "HKCAZ", "HKCCS 1?", "HKCCS", - "pain.001.001.03?", "SEPA Formate", "Sprachen", "Untersstützte Geschäftsvorfälle" - )) - - - val uniqueBanks = banksSupportingFinTs.associateBy { "${it.bankCode}_${it.name}" } - var bankIndex = 0 - - uniqueBanks.forEach { bankName, bankInfo -> - log.info("[${++bankIndex}] Getting details for $bankName ...") - - getAndSaveBankDetails(bankInfo, responsesFolder, csvPrinter) - } - - printStatistics() - - csvPrinter.close() - csvFile.close() - } - - - private fun getAnonymousBankInfo(bank: BankData): BankResponse { - val context = JobContext(JobContextType.AnonymousBankInfo, SimpleFinTsClientCallback(), product, bank) - context.startNewDialog() - - val requestBody = messageBuilder.createAnonymousDialogInitMessage(context) - - val anonymousBankInfoResponse = AtomicReference() - val countDownLatch = CountDownLatch(1) - - jobExecutor.getAndHandleResponseForMessagePublic(context, requestBody) { - anonymousBankInfoResponse.set(it) - countDownLatch.countDown() - } - - countDownLatch.await(30, TimeUnit.SECONDS) - - modelMapper.updateBankData(bank, anonymousBankInfoResponse.get()) - - return anonymousBankInfoResponse.get() - } - - private fun getAndSaveBankDetails(bankInfo: BankInfo, responsesFolder: File, csvPrinter: CSVPrinter) = runBlocking { - val bank = BankData.anonymous(bankInfo.bankCode, bankInfo.pinTanAddress ?: "", bankInfo.bic) - bank.bankName = bankInfo.name - - val anonymousBankInfoResponse = getAnonymousBankInfo(bank) - - File(responsesFolder, "${bankInfo.bankCode}_${bankInfo.name.replace('/', '-')}").writeText( - anonymousBankInfoResponse.receivedSegments.joinToString(System.lineSeparator()) { it.segmentString + Separators.SegmentSeparator }) - - if (anonymousBankInfoResponse.successful == false) { - requestNotSuccessful.add(bankInfo) - log.warn("Did not receive response from bank $bankInfo: ${anonymousBankInfoResponse.receivedSegments.joinToString(System.lineSeparator()) { it.segmentString + Separators.SegmentSeparator }}") - - return@runBlocking - } - - - val supportsHKTAN6 = supportsJobInVersion(bank, "HKTAN", 6) - val supportsHKSAL5or7 = supportsJobInVersion(bank, "HKSAL", listOf(5, 7)) - val supportsHKKAZ5to7 = supportsJobInVersion(bank, "HKKAZ", listOf(5, 6, 7)) - val supportsHKCCS1 = supportsJobInVersion(bank, "HKCCS", 1) - - val tanInfo = anonymousBankInfoResponse.receivedSegments.filterIsInstance(TanInfo::class.java) - val tanMethodParameters = tanInfo.flatMap { it.tanProcedureParameters.methodParameters } - val supportedTanMethods = tanMethodParameters.map { it.technicalTanMethodIdentification } - val hhd13Supported = supportedTanMethods.firstOrNull { it.startsWith("hhd1.3", true) } != null - val hhd14Supported = supportedTanMethods.firstOrNull { it.startsWith("hhd1.4", true) } != null - - val supportedHKTANVersions = tanInfo.map { it.segmentVersion } - val supportedHKSALVersions = getSupportedVersions(bank, "HKSAL") - val supportedHKKAZVersions = getSupportedVersions(bank, "HKKAZ") - val supportedHKCAZVersions = getSupportedVersions(bank, "HKCAZ") - val supportedHKCCSVersions = getSupportedVersions(bank, "HKCCS") - - val sepaAccountInfoParameters = anonymousBankInfoResponse.receivedSegments.filterIsInstance() - val supportedSepaFormats = sepaAccountInfoParameters.flatMap { it.supportedSepaFormats }.map { it.substring(it.indexOf(":xsd:") + ":xsd:".length) } - val supportsPain_001_001_or_003_03 = supportedSepaFormats.firstOrNull { it.contains("pain.001.001.03") or it.contains("pain.001.003.03") } != null - - csvPrinter.printRecord(bankInfo.bankCode, bankInfo.name, bankInfo.city, - bank.bpdVersion, - bank.tanMethodsSupportedByBank.joinToString(", ") { it.securityFunction.code + ": " + it.displayName + " (" + it.type + ")" }, - supportedTanMethods.joinToString(", "), - hhd13Supported, - hhd14Supported, - supportsHKTAN6, - supportedHKTANVersions.joinToString(", "), - supportsHKSAL5or7, - supportedHKSALVersions.joinToString(", "), - supportsHKKAZ5to7, - supportedHKKAZVersions.joinToString(", "), - supportedHKCAZVersions.joinToString(", "), - supportsHKCCS1, - supportedHKCCSVersions.joinToString(", "), - supportsPain_001_001_or_003_03, - supportedSepaFormats.joinToString(", "), - bank.supportedLanguages.filter { it != Dialogsprache.German }.joinToString(", ") { it.name }, - bank.supportedJobs.joinToString(", ") { it.jobName + " " + it.segmentVersion } - ) - - tanMethodParameters.forEach { methodParameter -> - if (tanMethodParameter.containsKey(methodParameter.methodName) == false) { - tanMethodParameter.put(methodParameter.methodName, mutableSetOf(methodParameter)) - } - else { - tanMethodParameter[methodParameter.methodName]?.add(methodParameter) - } - - val tanMethodType = modelMapper.mapToTanMethodTypePublic(methodParameter) - if (tanMethodTypes.containsKey(tanMethodType) == false) { - tanMethodTypes.put(tanMethodType, mutableSetOf(methodParameter)) - } - else { - tanMethodTypes[tanMethodType]?.add(methodParameter) - } - - tanMethodParameterTechnicalIdentification.add(methodParameter.technicalTanMethodIdentification) - tanMethodParameterVersionDkTanMethod.add(methodParameter.versionDkTanMethod) - - if (methodParameter.smsDebitAccountRequired == SmsAbbuchungskontoErforderlich.SmsAbbuchungskontoMussAngegebenWerden) { - requiresSmsAbbuchungskonto.add(bankInfo) - } - if (methodParameter.initiatorAccountRequired == AuftraggeberkontoErforderlich.AuftraggeberkontoMussAngegebenWerdenWennImGeschaeftsvorfallEnthalten) { - requiresAuftraggeberkonto.add(bankInfo) - } - if (methodParameter.challengeClassRequired) { - requiresChallengeClass.add(bankInfo) - } - if (methodParameter.signatureStructured) { - signatureStructured.add(bankInfo) - } - if (methodParameter.nameOfTanMediumRequired == BezeichnungDesTanMediumsErforderlich.BezeichnungDesTanMediumsMussAngegebenWerden) { - requiresNameOfTanMedia.add(bankInfo) - } - if (methodParameter.hhdUcResponseRequired) { - requiresHhdUcResponse.add(bankInfo) - } - } - - if (supportsHKTAN6 == false) { - doesNotSupportHKTAN6.add(bankInfo) - } - if (supportsHKSAL5or7 == false) { - doesNotSupportHKSAL5or7.add(bankInfo) - } - if (supportsHKKAZ5to7 == false) { - doesNotSupportHKKAZ5to7.add(bankInfo) - } - if (supportsHKCCS1 == false) { - doesNotSupportHKCCS1.add(bankInfo) - } - - if (hhd13Supported) { - supportsHhd13.add(bankInfo) - } - if (hhd14Supported) { - supportsHhd14.add(bankInfo) - } - - if (supportsPain_001_001_or_003_03 == false) { - doesNotSupportPain_001_001_or_003_03.add(bankInfo) - } - } - - private fun getSupportedVersions(bank: BankData, jobName: String): List { - return bank.supportedJobs.filter { it.jobName == jobName }.map { it.segmentVersion } - } - - private fun supportsJobInVersion(bank: BankData, jobName: String, version: Int): Boolean { - return supportsJobInVersion(bank, jobName, listOf(version)) - } - - private fun supportsJobInVersion(bank: BankData, jobName: String, versions: List): Boolean { - return bank.supportedJobs.firstOrNull { it.jobName == jobName && versions.contains(it.segmentVersion) } != null - } - - - private fun printStatistics() { - log.info("Did not receive response from Banks ${printBanks(requestNotSuccessful)}") - - log.info("Mapped tanMethodTypes: ${tanMethodTypes.map { System.lineSeparator() + it.key + ": " + it.value.map { it.methodName + " " + it.dkTanMethod + " " + it.technicalTanMethodIdentification + " (" + it.descriptionToShowToUser + ")" }.toSet().joinToString(", ") }}\n\n") - log.info("TanMethodParameters:${tanMethodParameter.map { System.lineSeparator() + it.key + ": " + it.value.map { it.securityFunction.code + " " + it.dkTanMethod + " " + it.technicalTanMethodIdentification + " (" + it.descriptionToShowToUser + ")" }.toSet().joinToString(", ") } }\n\n") - - log.info("TanMethodParameters TechnicalIdentification:${tanMethodParameterTechnicalIdentification.joinToString(", ") } \n\n") - log.info("TanMethodParameters VersionDkTanMethod:${tanMethodParameterVersionDkTanMethod.joinToString(", ") } \n\n") - - log.info("Requires SmsAbbuchungskonto ${printBanks(requiresSmsAbbuchungskonto)}") // no (only 2) - log.info("Requires Auftraggeberkonto ${printBanks(requiresAuftraggeberkonto)}") // yes, a lot of (12631) - log.info("Requires ChallengeClass ${printBanks(requiresChallengeClass)}") // no - log.info("Has structured signature ${printBanks(signatureStructured)}") // yes, a lot of (12651) - log.info("Requires NameOfTanMedia ${printBanks(requiresNameOfTanMedia)}") // yes, a lot of (912) - log.info("Requires HhdUcResponse ${printBanks(requiresHhdUcResponse)}") // no (only 2) - - log.info("Banks supporting HHD 1.3 (${supportsHhd13.size}):${printBanks(supportsHhd13)}") - log.info("Banks supporting HHD 1.4 (${supportsHhd14.size}):${printBanks(supportsHhd14)}") - - log.info("Banks not supporting HKTAN 6 ${printBanks(doesNotSupportHKTAN6)}") - log.info("Banks not supporting HKSAL 5 or 7 ${printBanks(doesNotSupportHKSAL5or7)}") - log.info("Banks not supporting HKKAZ 5-7 ${printBanks(doesNotSupportHKKAZ5to7)}") - log.info("Banks not supporting HKCCS 1 ${printBanks(doesNotSupportHKCCS1)}") - - log.info("Banks not supporting pain.001.001.03 or pain.001.003.03 ${printBanks(doesNotSupportPain_001_001_or_003_03)}") - } - - private fun printBanks(banks: List): String { - return "(${banks.size}):${ banks.joinToString { System.lineSeparator() + it } }\n\n\n" - } - -} \ No newline at end of file diff --git a/fints4k/src/jvm6Main/kotlin/net/dankito/banking/fints/util/JavaThreadPool.kt b/fints4k/src/jvmMain/kotlin/net/dankito/banking/fints/util/JavaThreadPool.kt similarity index 100% rename from fints4k/src/jvm6Main/kotlin/net/dankito/banking/fints/util/JavaThreadPool.kt rename to fints4k/src/jvmMain/kotlin/net/dankito/banking/fints/util/JavaThreadPool.kt diff --git a/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt new file mode 100644 index 00000000..90b08afd --- /dev/null +++ b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/FinTsClientTestBase.kt @@ -0,0 +1,270 @@ +//package net.dankito.banking.fints +// +//import ch.tutteli.atrium.api.fluent.en_GB.* +//import ch.tutteli.atrium.api.verbs.expect +//import jdk.nashorn.internal.ir.annotations.Ignore +//import net.dankito.banking.bankfinder.InMemoryBankFinder +//import net.dankito.banking.fints.callback.FinTsClientCallback +//import net.dankito.banking.fints.extensions.isTrue +//import net.dankito.banking.fints.extensions.isFalse +//import net.dankito.banking.fints.messages.datenelemente.implementierte.Dialogsprache +//import net.dankito.banking.fints.messages.datenelemente.implementierte.KundensystemStatus +//import net.dankito.banking.fints.messages.datenelemente.implementierte.KundensystemStatusWerte +//import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanEinsatzOption +//import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanGeneratorTanMedium +//import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMedienArtVersion +//import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMediumKlasse +//import net.dankito.banking.fints.messages.segmente.id.CustomerSegmentId +//import net.dankito.banking.fints.model.* +//import net.dankito.banking.fints.response.client.* +//import net.dankito.utils.multiplatform.Date +//import net.dankito.utils.multiplatform.DateFormatter +//import net.dankito.utils.multiplatform.UUID +//import org.assertj.core.api.Assertions.assertThat +//import org.junit.jupiter.api.Test +//import org.junit.jupiter.api.fail +//import java.util.concurrent.CountDownLatch +//import java.util.concurrent.TimeUnit +//import java.util.concurrent.atomic.AtomicReference +// +// +//@Ignore // not an automatic test, supply your settings below +//open class FinTsClientTestBase { +// +// companion object { +// +// // TODO: add your settings here: +// val BankCode = "" +// +// val CustomerId = "" +// +// val Password = "" +// +// +// val DateTimeFormatForUniqueBankTransferReference = DateFormatter("yyyy-MM-dd'T'HH:mm:ss.SSS") +// } +// +// +// private var didAskUserForTanMethod = false +// +// private var didAskUserToEnterTan = false +// +// +// private val callback = object : FinTsClientCallback { +// +// override fun askUserForTanMethod(supportedTanMethods: List, suggestedTanMethod: TanMethod?, callback: (TanMethod?) -> Unit) { +// didAskUserForTanMethod = true +// callback(suggestedTanMethod) // simply return suggestedTanMethod as in most cases it's the best fitting one +// } +// +// override fun enterTan(bank: BankData, tanChallenge: TanChallenge, callback: (EnterTanResult) -> Unit) { +// didAskUserToEnterTan = true +// +// callback(EnterTanResult.userDidNotEnterTan()) +// } +// +// override fun enterTanGeneratorAtc(bank: BankData, tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { +// fail("Bank asks you to synchronize your TAN generator for card ${tanMedium.cardNumber} " + +// "(card sequence number ${tanMedium.cardSequenceNumber}). Please do this via your online banking portal or Banking UI.") +// } +// +// } +// +// +// private val underTest = FinTsClient(callback) +// +// +// private val BankDataAnonymous = BankData.anonymous("10070000", "https://fints.deutsche-bank.de/", "DEUTDEBBXXX") +// +// private val bankInfo = InMemoryBankFinder().findBankByBankCode(BankCode).first() +// private val Bank = BankData(bankInfo.bankCode, CustomerId, Password, bankInfo.pinTanAddress ?: "", bankInfo.bic, bankInfo.name) +// +// +// +// @Test +// fun getAnonymousBankInfo() { +// +// // when +// underTest.getAnonymousBankInfo(BankDataAnonymous) { result -> +// +// // then +// expect(result.successful).isTrue() +// expect(BankDataAnonymous.supportedHbciVersions).isNotEmpty() +// expect(BankDataAnonymous.tanMethodsSupportedByBank).isNotEmpty() +// expect(BankDataAnonymous.supportedJobs).isNotEmpty() +// expect(BankDataAnonymous.supportedLanguages).isNotEmpty() +// expect(BankDataAnonymous.bankName).isNotEmpty() +// } +// } +// +// +// @Test +// fun addAccount() { +// +// // given +// val response = AtomicReference() +// val countDownLatch = CountDownLatch(1) +// +// +// // when +// underTest.addAccountAsync(Bank.toAddAccountParameter()) { +// response.set(it) +// countDownLatch.countDown() +// } +// +// +// // then +// countDownLatch.await(30, TimeUnit.SECONDS) +// val result = response.get() +// +// expect(result.successful).isTrue() +// +// expect(didAskUserForTanMethod).isFalse() +// +// expect(Bank.bankName).isNotEmpty() +// expect(Bank.supportedJobs).isNotEmpty() // supported jobs are now known +// expect(Bank.tanMethodsSupportedByBank).isNotEmpty() // supported tan methods are now known +// expect(Bank.supportedHbciVersions).isNotEmpty() // supported HBIC versions are now known +// expect(Bank.supportedLanguages).isNotEmpty() // supported languages are now known +// +// expect(Bank.customerName).isNotEmpty() +// expect(Bank.tanMethodsAvailableForUser).isNotEmpty() +// expect(Bank.selectedLanguage).notToBe(Dialogsprache.Default) // language is set now +// expect(Bank.customerSystemId).notToBe(KundensystemStatus.SynchronizingCustomerSystemId.code) // customer system id is now set +// expect(Bank.customerSystemStatus).toBe(KundensystemStatusWerte.Benoetigt) // customerSystemStatus is set now +// expect(Bank.accounts).isNotEmpty() // accounts are now known +// expect(Bank.accounts.first().allowedJobs).isNotEmpty() // allowed jobs are now known +// } +// +// +// @ExperimentalWithOptions +// @Test +// fun getTransactions() { +// +// // given +// val response = AtomicReference() +// val countDownLatch = CountDownLatch(1) +// +// underTest.addAccountAsync(Bank.toAddAccountParameter(false)) { // retrieve basic data, e.g. accounts +// val account = Bank.accounts.firstOrNull { it.supportsFeature(AccountFeature.RetrieveAccountTransactions) } +// expect(account).withRepresentation("We need at least one account that supports retrieving account transactions (${CustomerSegmentId.AccountTransactionsMt940.id})").notToBeNull() +// +// // when +// +// // some banks support retrieving account transactions of last 90 days without TAN +// underTest.tryGetAccountTransactionsOfLast90DaysWithoutTan(Bank, account!!) { +// response.set(it) +// countDownLatch.countDown() +// } +// } +// +// +// // then +// countDownLatch.await(30, TimeUnit.SECONDS) +// val result = response.get() +// +// assertThat(result.successful).isTrue() +// assertThat(result.retrievedData).isNotNull() +// } +// +// +// @Test +// fun getTanMediaList() { +// +// // this test is only senseful for accounts using chipTAN / TAN generator as TAN method +// +// // given +// val response = AtomicReference() +// val countDownLatch = CountDownLatch(1) +// val anonymousBankInfoCountDownLatch = CountDownLatch(1) +// +// +// underTest.getAnonymousBankInfo(Bank) { +// anonymousBankInfoCountDownLatch.countDown() +// } +// anonymousBankInfoCountDownLatch.await(30, TimeUnit.SECONDS) +// +// +// val supportsRetrievingTanMedia = Bank.supportedJobs.firstOrNull { it.jobName == "HKTAB" } != null +// +// if (supportsRetrievingTanMedia == false) { // accounts with appTAN, pushTAN, smsTAN, ... would fail here -> simply return +// println("Bank ${Bank.bankName} does not support retrieving TAN media. Therefore cannot execute test getTanMediaList()") +// return +// } +// +// expect(Bank.tanMedia).isEmpty() +// +// +// // when +// underTest.getTanMediaList(Bank, TanMedienArtVersion.Alle, TanMediumKlasse.AlleMedien) { result -> +// response.set(result) +// countDownLatch.countDown() +// } +// +// // then +// countDownLatch.await(30, TimeUnit.SECONDS) +// val result = response.get() +// +// expect(result.successful).isTrue() +// +// expect(result.tanMediaList).notToBeNull() +// expect(result.tanMediaList!!.usageOption).toBe(TanEinsatzOption.KundeKannGenauEinMediumZuEinerZeitNutzen) // TODO: may adjust to your value +// expect(result.tanMediaList!!.tanMedia).isNotEmpty() +// +// expect(Bank.tanMedia).isNotEmpty() +// } +// +// @Ignore // only works with banks that don't support HKTAB version 5 +// @Test +// fun getTanMediaList_UnsupportedTanMediumClass() { +// +// // when +// expect { +// underTest.getTanMediaList(Bank, TanMedienArtVersion.Alle, TanMediumKlasse.BilateralVereinbart) { } +// }.toThrow() +// +// +// // then +// // exception gets thrown +// } +// +// +// @ExperimentalWithOptions +// @Test +// fun testBankTransfer() { +// +// // given +// val response = AtomicReference() +// val countDownLatch = CountDownLatch(1) +// +// underTest.addAccountAsync(Bank.toAddAccountParameter(false)) { // retrieve basic data, e.g. accounts +// // we need at least one account that supports cash transfer +// val account = Bank.accounts.firstOrNull { it.supportsFeature(AccountFeature.TransferMoney) } +// expect(account).withRepresentation("We need at least one account that supports cash transfer (${CustomerSegmentId.SepaBankTransfer.id})").notToBeNull() +// +// // IBAN should be set +// expect(account?.iban).withRepresentation("Account IBAN must be set").notToBeNull() +// +// // transfer 1 cent to yourself. Transferring money to oneself also doesn't require to enter a TAN according to PSD2 +// val BankTransferData = BankTransferData(Bank.customerName, account?.iban!!, Bank.bic, Money(Amount("0,01"), "EUR"), +// "${DateTimeFormatForUniqueBankTransferReference.format(Date())} Test transaction ${UUID.random()}") +// +// +// // when +// underTest.doBankTransferAsync(BankTransferData, Bank, account) { result -> +// response.set(result) +// countDownLatch.countDown() +// } +// +// } +// +// +// // then +// countDownLatch.await(30, TimeUnit.SECONDS) +// val result = response.get() +// +// expect(result.successful).isTrue() +// +// } +// +//} \ No newline at end of file diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsTestBaseJvm.kt b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/FinTsTestBaseJvm.kt similarity index 100% rename from fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/FinTsTestBaseJvm.kt rename to fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/FinTsTestBaseJvm.kt diff --git a/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt new file mode 100644 index 00000000..3f226962 --- /dev/null +++ b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/bankdetails/BanksFinTsDetailsRetriever.kt @@ -0,0 +1,317 @@ +//package net.dankito.banking.fints.bankdetails +// +//import kotlinx.coroutines.runBlocking +//import net.dankito.banking.bankfinder.InMemoryBankFinder +//import net.dankito.banking.fints.callback.NoOpFinTsClientCallback +//import net.dankito.banking.fints.messages.MessageBuilder +//import net.dankito.banking.fints.messages.MessageBuilderResult +//import net.dankito.banking.fints.messages.Separators +//import net.dankito.banking.fints.messages.datenelemente.implementierte.Dialogsprache +//import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AuftraggeberkontoErforderlich +//import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.BezeichnungDesTanMediumsErforderlich +//import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.SmsAbbuchungskontoErforderlich +//import net.dankito.banking.fints.model.* +//import net.dankito.banking.bankfinder.BankInfo +//import net.dankito.banking.fints.FinTsJobExecutor +//import net.dankito.banking.fints.callback.SimpleFinTsClientCallback +//import net.dankito.banking.fints.model.mapper.ModelMapper +//import net.dankito.banking.fints.response.BankResponse +//import net.dankito.banking.fints.response.segments.SepaAccountInfoParameters +//import net.dankito.banking.fints.response.segments.TanInfo +//import net.dankito.banking.fints.response.segments.TanMethodParameters +//import net.dankito.banking.fints.util.* +//import org.apache.commons.csv.CSVFormat +//import org.apache.commons.csv.CSVPrinter +//import org.junit.Ignore +//import kotlin.test.Test +//import org.slf4j.LoggerFactory +//import java.io.File +//import java.io.FileWriter +//import java.text.SimpleDateFormat +//import java.util.* +//import java.util.concurrent.CountDownLatch +//import java.util.concurrent.TimeUnit +//import java.util.concurrent.atomic.AtomicReference +// +// +//@Ignore // not a real test, run manually to retrieve FinTS information from all banks +//class BanksFinTsDetailsRetriever { +// +// companion object { +// private val OutputFolderDateFormat = SimpleDateFormat("yyyy_MM_dd_HH_mm_ss") +// +// private val log = LoggerFactory.getLogger(BanksFinTsDetailsRetriever::class.java) +// } +// +// +// private val bankFinder = InMemoryBankFinder() +// +// private val product: ProductData = ProductData("15E53C26816138699C7B6A3E8", "1.0.0") // TODO: get version dynamically +// +// private val messageBuilder = MessageBuilder() +// +// private val modelMapper = object : ModelMapper(messageBuilder) { +// +// fun mapToTanMethodTypePublic(parameters: TanMethodParameters): TanMethodType? { +// return super.mapToTanMethodType(parameters) +// } +// +// } +// +// private val jobExecutor = object : FinTsJobExecutor(modelMapper = modelMapper) { +// +// fun getAndHandleResponseForMessagePublic(context: JobContext, message: MessageBuilderResult, callback: (BankResponse) -> Unit) { +// getAndHandleResponseForMessage(context, message, callback) +// } +// } +// +// +// private val requestNotSuccessful = mutableListOf() +// +// private val tanMethodParameter = mutableMapOf>() +// private val tanMethodTypes = mutableMapOf>() +// +// private val tanMethodParameterTechnicalIdentification = mutableSetOf() +// private val tanMethodParameterVersionDkTanMethod = mutableSetOf() +// +// private val requiresSmsAbbuchungskonto = mutableListOf() +// private val requiresAuftraggeberkonto = mutableListOf() +// private val requiresChallengeClass = mutableListOf() +// private val signatureStructured = mutableListOf() +// private val requiresNameOfTanMedia = mutableListOf() +// private val requiresHhdUcResponse = mutableListOf() +// +// private val doesNotSupportHKTAN6 = mutableListOf() +// private val doesNotSupportHKSAL5or7 = mutableListOf() +// private val doesNotSupportHKKAZ5to7 = mutableListOf() +// private val doesNotSupportHKCCS1 = mutableListOf() +// +// private val supportsHhd13 = mutableListOf() +// private val supportsHhd14 = mutableListOf() +// +// private val doesNotSupportPain_001_001_or_003_03 = mutableListOf() +// +// +// @Test +// fun retrieveAllBanksFinTsDetails() { +// +// val allBanks = bankFinder.getBankList() +// val banksSupportingFinTs = allBanks.filter { it.supportsFinTs3_0 } +// +// val outputFolder = File("bankData", OutputFolderDateFormat.format(Date())) +// val responsesFolder = File(outputFolder, "responses") +// responsesFolder.mkdirs() +// +// val csvFile = FileWriter(File(outputFolder, "bank_details.csv")) +// val csvPrinter = CSVPrinter(csvFile, CSVFormat.DEFAULT.withHeader( +// "BLZ", "Name", "Ort", "BPD", "Tanverfahren", "Technische Tanverfahrennamen", "HHD 1.3?", "HHD 1.4?", +// "HKTAN 6?", "HKTAN", "HKSAL 5?", "HKSAL", "HKKAZ 5-7?", "HKKAZ", "HKCAZ", "HKCCS 1?", "HKCCS", +// "pain.001.001.03?", "SEPA Formate", "Sprachen", "Untersstützte Geschäftsvorfälle" +// )) +// +// +// val uniqueBanks = banksSupportingFinTs.associateBy { "${it.bankCode}_${it.name}" } +// var bankIndex = 0 +// +// uniqueBanks.forEach { bankName, bankInfo -> +// log.info("[${++bankIndex}] Getting details for $bankName ...") +// +// getAndSaveBankDetails(bankInfo, responsesFolder, csvPrinter) +// } +// +// printStatistics() +// +// csvPrinter.close() +// csvFile.close() +// } +// +// +// private fun getAnonymousBankInfo(bank: BankData): BankResponse { +// val context = JobContext(JobContextType.AnonymousBankInfo, SimpleFinTsClientCallback(), product, bank) +// context.startNewDialog() +// +// val requestBody = messageBuilder.createAnonymousDialogInitMessage(context) +// +// val anonymousBankInfoResponse = AtomicReference() +// val countDownLatch = CountDownLatch(1) +// +// jobExecutor.getAndHandleResponseForMessagePublic(context, requestBody) { +// anonymousBankInfoResponse.set(it) +// countDownLatch.countDown() +// } +// +// countDownLatch.await(30, TimeUnit.SECONDS) +// +// modelMapper.updateBankData(bank, anonymousBankInfoResponse.get()) +// +// return anonymousBankInfoResponse.get() +// } +// +// private fun getAndSaveBankDetails(bankInfo: BankInfo, responsesFolder: File, csvPrinter: CSVPrinter) = runBlocking { +// val bank = BankData.anonymous(bankInfo.bankCode, bankInfo.pinTanAddress ?: "", bankInfo.bic) +// bank.bankName = bankInfo.name +// +// val anonymousBankInfoResponse = getAnonymousBankInfo(bank) +// +// File(responsesFolder, "${bankInfo.bankCode}_${bankInfo.name.replace('/', '-')}").writeText( +// anonymousBankInfoResponse.receivedSegments.joinToString(System.lineSeparator()) { it.segmentString + Separators.SegmentSeparator }) +// +// if (anonymousBankInfoResponse.successful == false) { +// requestNotSuccessful.add(bankInfo) +// log.warn("Did not receive response from bank $bankInfo: ${anonymousBankInfoResponse.receivedSegments.joinToString(System.lineSeparator()) { it.segmentString + Separators.SegmentSeparator }}") +// +// return@runBlocking +// } +// +// +// val supportsHKTAN6 = supportsJobInVersion(bank, "HKTAN", 6) +// val supportsHKSAL5or7 = supportsJobInVersion(bank, "HKSAL", listOf(5, 7)) +// val supportsHKKAZ5to7 = supportsJobInVersion(bank, "HKKAZ", listOf(5, 6, 7)) +// val supportsHKCCS1 = supportsJobInVersion(bank, "HKCCS", 1) +// +// val tanInfo = anonymousBankInfoResponse.receivedSegments.filterIsInstance(TanInfo::class.java) +// val tanMethodParameters = tanInfo.flatMap { it.tanProcedureParameters.methodParameters } +// val supportedTanMethods = tanMethodParameters.map { it.technicalTanMethodIdentification } +// val hhd13Supported = supportedTanMethods.firstOrNull { it.startsWith("hhd1.3", true) } != null +// val hhd14Supported = supportedTanMethods.firstOrNull { it.startsWith("hhd1.4", true) } != null +// +// val supportedHKTANVersions = tanInfo.map { it.segmentVersion } +// val supportedHKSALVersions = getSupportedVersions(bank, "HKSAL") +// val supportedHKKAZVersions = getSupportedVersions(bank, "HKKAZ") +// val supportedHKCAZVersions = getSupportedVersions(bank, "HKCAZ") +// val supportedHKCCSVersions = getSupportedVersions(bank, "HKCCS") +// +// val sepaAccountInfoParameters = anonymousBankInfoResponse.receivedSegments.filterIsInstance() +// val supportedSepaFormats = sepaAccountInfoParameters.flatMap { it.supportedSepaFormats }.map { it.substring(it.indexOf(":xsd:") + ":xsd:".length) } +// val supportsPain_001_001_or_003_03 = supportedSepaFormats.firstOrNull { it.contains("pain.001.001.03") or it.contains("pain.001.003.03") } != null +// +// csvPrinter.printRecord(bankInfo.bankCode, bankInfo.name, bankInfo.city, +// bank.bpdVersion, +// bank.tanMethodsSupportedByBank.joinToString(", ") { it.securityFunction.code + ": " + it.displayName + " (" + it.type + ")" }, +// supportedTanMethods.joinToString(", "), +// hhd13Supported, +// hhd14Supported, +// supportsHKTAN6, +// supportedHKTANVersions.joinToString(", "), +// supportsHKSAL5or7, +// supportedHKSALVersions.joinToString(", "), +// supportsHKKAZ5to7, +// supportedHKKAZVersions.joinToString(", "), +// supportedHKCAZVersions.joinToString(", "), +// supportsHKCCS1, +// supportedHKCCSVersions.joinToString(", "), +// supportsPain_001_001_or_003_03, +// supportedSepaFormats.joinToString(", "), +// bank.supportedLanguages.filter { it != Dialogsprache.German }.joinToString(", ") { it.name }, +// bank.supportedJobs.joinToString(", ") { it.jobName + " " + it.segmentVersion } +// ) +// +// tanMethodParameters.forEach { methodParameter -> +// if (tanMethodParameter.containsKey(methodParameter.methodName) == false) { +// tanMethodParameter.put(methodParameter.methodName, mutableSetOf(methodParameter)) +// } +// else { +// tanMethodParameter[methodParameter.methodName]?.add(methodParameter) +// } +// +// val tanMethodType = modelMapper.mapToTanMethodTypePublic(methodParameter) +// if (tanMethodTypes.containsKey(tanMethodType) == false) { +// tanMethodTypes.put(tanMethodType, mutableSetOf(methodParameter)) +// } +// else { +// tanMethodTypes[tanMethodType]?.add(methodParameter) +// } +// +// tanMethodParameterTechnicalIdentification.add(methodParameter.technicalTanMethodIdentification) +// tanMethodParameterVersionDkTanMethod.add(methodParameter.versionDkTanMethod) +// +// if (methodParameter.smsDebitAccountRequired == SmsAbbuchungskontoErforderlich.SmsAbbuchungskontoMussAngegebenWerden) { +// requiresSmsAbbuchungskonto.add(bankInfo) +// } +// if (methodParameter.initiatorAccountRequired == AuftraggeberkontoErforderlich.AuftraggeberkontoMussAngegebenWerdenWennImGeschaeftsvorfallEnthalten) { +// requiresAuftraggeberkonto.add(bankInfo) +// } +// if (methodParameter.challengeClassRequired) { +// requiresChallengeClass.add(bankInfo) +// } +// if (methodParameter.signatureStructured) { +// signatureStructured.add(bankInfo) +// } +// if (methodParameter.nameOfTanMediumRequired == BezeichnungDesTanMediumsErforderlich.BezeichnungDesTanMediumsMussAngegebenWerden) { +// requiresNameOfTanMedia.add(bankInfo) +// } +// if (methodParameter.hhdUcResponseRequired) { +// requiresHhdUcResponse.add(bankInfo) +// } +// } +// +// if (supportsHKTAN6 == false) { +// doesNotSupportHKTAN6.add(bankInfo) +// } +// if (supportsHKSAL5or7 == false) { +// doesNotSupportHKSAL5or7.add(bankInfo) +// } +// if (supportsHKKAZ5to7 == false) { +// doesNotSupportHKKAZ5to7.add(bankInfo) +// } +// if (supportsHKCCS1 == false) { +// doesNotSupportHKCCS1.add(bankInfo) +// } +// +// if (hhd13Supported) { +// supportsHhd13.add(bankInfo) +// } +// if (hhd14Supported) { +// supportsHhd14.add(bankInfo) +// } +// +// if (supportsPain_001_001_or_003_03 == false) { +// doesNotSupportPain_001_001_or_003_03.add(bankInfo) +// } +// } +// +// private fun getSupportedVersions(bank: BankData, jobName: String): List { +// return bank.supportedJobs.filter { it.jobName == jobName }.map { it.segmentVersion } +// } +// +// private fun supportsJobInVersion(bank: BankData, jobName: String, version: Int): Boolean { +// return supportsJobInVersion(bank, jobName, listOf(version)) +// } +// +// private fun supportsJobInVersion(bank: BankData, jobName: String, versions: List): Boolean { +// return bank.supportedJobs.firstOrNull { it.jobName == jobName && versions.contains(it.segmentVersion) } != null +// } +// +// +// private fun printStatistics() { +// log.info("Did not receive response from Banks ${printBanks(requestNotSuccessful)}") +// +// log.info("Mapped tanMethodTypes: ${tanMethodTypes.map { System.lineSeparator() + it.key + ": " + it.value.map { it.methodName + " " + it.dkTanMethod + " " + it.technicalTanMethodIdentification + " (" + it.descriptionToShowToUser + ")" }.toSet().joinToString(", ") }}\n\n") +// log.info("TanMethodParameters:${tanMethodParameter.map { System.lineSeparator() + it.key + ": " + it.value.map { it.securityFunction.code + " " + it.dkTanMethod + " " + it.technicalTanMethodIdentification + " (" + it.descriptionToShowToUser + ")" }.toSet().joinToString(", ") } }\n\n") +// +// log.info("TanMethodParameters TechnicalIdentification:${tanMethodParameterTechnicalIdentification.joinToString(", ") } \n\n") +// log.info("TanMethodParameters VersionDkTanMethod:${tanMethodParameterVersionDkTanMethod.joinToString(", ") } \n\n") +// +// log.info("Requires SmsAbbuchungskonto ${printBanks(requiresSmsAbbuchungskonto)}") // no (only 2) +// log.info("Requires Auftraggeberkonto ${printBanks(requiresAuftraggeberkonto)}") // yes, a lot of (12631) +// log.info("Requires ChallengeClass ${printBanks(requiresChallengeClass)}") // no +// log.info("Has structured signature ${printBanks(signatureStructured)}") // yes, a lot of (12651) +// log.info("Requires NameOfTanMedia ${printBanks(requiresNameOfTanMedia)}") // yes, a lot of (912) +// log.info("Requires HhdUcResponse ${printBanks(requiresHhdUcResponse)}") // no (only 2) +// +// log.info("Banks supporting HHD 1.3 (${supportsHhd13.size}):${printBanks(supportsHhd13)}") +// log.info("Banks supporting HHD 1.4 (${supportsHhd14.size}):${printBanks(supportsHhd14)}") +// +// log.info("Banks not supporting HKTAN 6 ${printBanks(doesNotSupportHKTAN6)}") +// log.info("Banks not supporting HKSAL 5 or 7 ${printBanks(doesNotSupportHKSAL5or7)}") +// log.info("Banks not supporting HKKAZ 5-7 ${printBanks(doesNotSupportHKKAZ5to7)}") +// log.info("Banks not supporting HKCCS 1 ${printBanks(doesNotSupportHKCCS1)}") +// +// log.info("Banks not supporting pain.001.001.03 or pain.001.003.03 ${printBanks(doesNotSupportPain_001_001_or_003_03)}") +// } +// +// private fun printBanks(banks: List): String { +// return "(${banks.size}):${ banks.joinToString { System.lineSeparator() + it } }\n\n\n" +// } +// +//} \ No newline at end of file diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/response/ResponseParserTestJvm.kt b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/response/ResponseParserTestJvm.kt similarity index 96% rename from fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/response/ResponseParserTestJvm.kt rename to fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/response/ResponseParserTestJvm.kt index e4a191be..0eaeb0bd 100644 --- a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/response/ResponseParserTestJvm.kt +++ b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/response/ResponseParserTestJvm.kt @@ -4,7 +4,7 @@ import net.dankito.banking.fints.FinTsTestBaseJvm import net.dankito.banking.fints.messages.HbciCharset import net.dankito.banking.fints.tan.TanImageDecoder import org.assertj.core.api.Assertions.assertThat -import org.junit.Test +import org.junit.jupiter.api.Test import java.nio.charset.Charset diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt similarity index 95% rename from fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt rename to fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt index 5586cbe0..22cd68c1 100644 --- a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt +++ b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/transactions/Mt940AccountTransactionsParserTest.kt @@ -4,7 +4,7 @@ import net.dankito.banking.fints.FinTsTestBaseJvm import net.dankito.banking.fints.model.AccountData import net.dankito.banking.fints.model.BankData import org.assertj.core.api.Assertions.assertThat -import org.junit.Test +import org.junit.jupiter.api.Test class Mt940AccountTransactionsParserTest : FinTsTestBaseJvm() { diff --git a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940ParserTestJvm.kt b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/transactions/Mt940ParserTestJvm.kt similarity index 94% rename from fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940ParserTestJvm.kt rename to fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/transactions/Mt940ParserTestJvm.kt index 38b1b399..dbec106f 100644 --- a/fints4k/src/jvm6Test/kotlin/net/dankito/banking/fints/transactions/Mt940ParserTestJvm.kt +++ b/fints4k/src/jvmTest/kotlin/net/dankito/banking/fints/transactions/Mt940ParserTestJvm.kt @@ -3,7 +3,7 @@ package net.dankito.banking.fints.transactions import net.dankito.banking.fints.FinTsTestBaseJvm import net.dankito.banking.fints.transactions.mt940.Mt940Parser import org.assertj.core.api.Assertions.assertThat -import org.junit.Test +import org.junit.jupiter.api.Test class Mt940ParserTestJvm : FinTsTestBaseJvm() { diff --git a/fints4k/src/jvm6Test/resources/logback-test.xml b/fints4k/src/jvmTest/resources/logback-test.xml similarity index 100% rename from fints4k/src/jvm6Test/resources/logback-test.xml rename to fints4k/src/jvmTest/resources/logback-test.xml diff --git a/fints4k/src/jvm6Test/resources/test_files/Decode_TanChallengeHhdUc_WithMaskedCharacter.txt b/fints4k/src/jvmTest/resources/test_files/Decode_TanChallengeHhdUc_WithMaskedCharacter.txt similarity index 100% rename from fints4k/src/jvm6Test/resources/test_files/Decode_TanChallengeHhdUc_WithMaskedCharacter.txt rename to fints4k/src/jvmTest/resources/test_files/Decode_TanChallengeHhdUc_WithMaskedCharacter.txt diff --git a/fints4k/src/jvm6Test/resources/test_files/TransactionsMt940.txt b/fints4k/src/jvmTest/resources/test_files/TransactionsMt940.txt similarity index 100% rename from fints4k/src/jvm6Test/resources/test_files/TransactionsMt940.txt rename to fints4k/src/jvmTest/resources/test_files/TransactionsMt940.txt diff --git a/fints4k/src/jvm6Test/resources/test_files/TransactionsMt940_2.txt b/fints4k/src/jvmTest/resources/test_files/TransactionsMt940_2.txt similarity index 100% rename from fints4k/src/jvm6Test/resources/test_files/TransactionsMt940_2.txt rename to fints4k/src/jvmTest/resources/test_files/TransactionsMt940_2.txt diff --git a/fints4k/src/main/AndroidManifest.xml b/fints4k/src/main/AndroidManifest.xml deleted file mode 100644 index aa7335e3..00000000 --- a/fints4k/src/main/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 763395f0..155302ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,3 @@ -android.enableJetifier=true -android.useAndroidX=true kotlin.code.style=official # Specifies the JVM arguments used for the daemon process. @@ -7,6 +5,7 @@ kotlin.code.style=official org.gradle.jvmargs=-Xmx3072m -quarkusVersion=1.11.0.Final +kotlinVersion=1.6.0 -#kotlin.js.compiler=ir \ No newline at end of file +coroutinesVersion=1.6.0 +ktorVersion=2.0.0-beta-1 \ No newline at end of file diff --git a/persistence/LuceneBankingPersistence/build.gradle b/persistence/LuceneBankingPersistence/build.gradle deleted file mode 100644 index fe208776..00000000 --- a/persistence/LuceneBankingPersistence/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -apply plugin: 'java-library' -apply plugin: 'kotlin' - - -sourceCompatibility = "1.7" -targetCompatibility = "1.7" - -compileKotlin { - kotlinOptions.jvmTarget = "1.6" -} -compileTestKotlin { - kotlinOptions.jvmTarget = "1.6" -} - - -dependencies { - implementation project(":BankingUiCommon") - - api project(":BankingPersistenceJson") - - implementation "net.dankito.search:lucene-4-utils:$luceneUtilsVersion" - - - testImplementation "junit:junit:$junitVersion" - testImplementation "org.assertj:assertj-core:$assertJVersion" - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - - testImplementation "org.slf4j:slf4j-simple:$slf4jVersion" -} \ No newline at end of file diff --git a/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/LuceneConfig.kt b/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/LuceneConfig.kt deleted file mode 100644 index d97f0f8f..00000000 --- a/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/LuceneConfig.kt +++ /dev/null @@ -1,39 +0,0 @@ -package net.dankito.banking - -import java.io.File - - -class LuceneConfig { - - companion object { - const val BankAccountIdFieldName = "bank_account_id" - - const val IdFieldName = "id" - - const val OtherPartyNameFieldName = "other_party_name" - - const val OtherPartyBankCodeFieldName = "other_party_bank_code" - - const val OtherPartyAccountIdFieldName = "other_party_account_id" - - const val BookingDateFieldName = "booking_date" - const val DateSortFieldName = "value_date_sort" - - const val ReferenceFieldName = "reference" - - const val BookingTextFieldName = "booking_text" - - const val AmountFieldName = "amount" - - const val CurrencyFieldName = "currency" - - const val BalanceFieldName = "balance" - - - fun getAccountTransactionsIndexFolder(indexFolder: File): File { - return File(indexFolder, "account_transactions") - } - - } - -} \ No newline at end of file diff --git a/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/persistence/LuceneBankingPersistence.kt b/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/persistence/LuceneBankingPersistence.kt deleted file mode 100644 index 3063331b..00000000 --- a/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/persistence/LuceneBankingPersistence.kt +++ /dev/null @@ -1,109 +0,0 @@ -package net.dankito.banking.persistence - -import net.dankito.utils.multiplatform.File -import net.dankito.banking.LuceneConfig -import net.dankito.banking.LuceneConfig.Companion.AmountFieldName -import net.dankito.banking.LuceneConfig.Companion.BalanceFieldName -import net.dankito.banking.LuceneConfig.Companion.BankAccountIdFieldName -import net.dankito.banking.LuceneConfig.Companion.BookingDateFieldName -import net.dankito.banking.LuceneConfig.Companion.DateSortFieldName -import net.dankito.banking.LuceneConfig.Companion.BookingTextFieldName -import net.dankito.banking.LuceneConfig.Companion.CurrencyFieldName -import net.dankito.banking.LuceneConfig.Companion.IdFieldName -import net.dankito.banking.LuceneConfig.Companion.OtherPartyAccountIdFieldName -import net.dankito.banking.LuceneConfig.Companion.OtherPartyBankCodeFieldName -import net.dankito.banking.LuceneConfig.Companion.OtherPartyNameFieldName -import net.dankito.banking.LuceneConfig.Companion.ReferenceFieldName -import net.dankito.banking.ui.model.* -import net.dankito.banking.util.ISerializer -import net.dankito.banking.util.JacksonJsonSerializer -import net.dankito.utils.lucene.index.DocumentsWriter -import net.dankito.utils.lucene.index.FieldBuilder -import org.apache.lucene.index.IndexableField -import org.slf4j.LoggerFactory - - -open class LuceneBankingPersistence( - protected val indexFolder: File, - databaseFolder: File, - serializer: ISerializer = JacksonJsonSerializer() -) : BankingPersistenceJson(databaseFolder, serializer), IBankingPersistence { - - companion object { - - // i really hate this solution, but could find no other way to avoid app crashes when - // Android app gets restored as previous IndexWriter is not not destroyed yet and holds - // write lock and a new IndexWriter instance in DocumentsWriter gets instantiated - protected var documentsWriter: DocumentsWriter? = null - - - private val log = LoggerFactory.getLogger(LuceneBankingPersistence::class.java) - - } - - - protected val fields = FieldBuilder() - - - override fun saveOrUpdateAccountTransactions(account: TypedBankAccount, transactions: List) { - val writer = getWriter() - - transactions.forEach { transaction -> - writer.updateDocumentForNonNullFields( - IdFieldName, transaction.technicalId, - *createFieldsForAccountTransaction(account, transaction).toTypedArray() - ) - } - - writer.flushChangesToDisk() - } - - protected open fun createFieldsForAccountTransaction(account: TypedBankAccount, transaction: IAccountTransaction): List { - return listOf( - fields.keywordField(BankAccountIdFieldName, account.technicalId), - fields.nullableFullTextSearchField(OtherPartyNameFieldName, transaction.otherPartyName, true), - fields.fullTextSearchField(ReferenceFieldName, transaction.reference, true), - fields.nullableFullTextSearchField(BookingTextFieldName, transaction.bookingText, true), - - fields.nullableStoredField(OtherPartyBankCodeFieldName, transaction.otherPartyBankCode), - fields.nullableStoredField(OtherPartyAccountIdFieldName, transaction.otherPartyAccountId), - fields.storedField(BookingDateFieldName, transaction.bookingDate), - fields.storedField(AmountFieldName, transaction.amount), - fields.storedField(CurrencyFieldName, transaction.currency), - fields.nullableStoredField(BalanceFieldName, transaction.closingBalance), // TODO: remove - - fields.sortField(DateSortFieldName, transaction.valueDate) - ) - } - - - override fun deleteBank(bank: TypedBankData, allBanks: List) { - try { - deleteAccountTransactions(bank.accounts) - } catch (e: Exception) { - log.error("Could not delete account transactions of account $bank", e) - } - - super.deleteBank(bank, allBanks) - } - - protected open fun deleteAccountTransactions(accounts: List) { - val writer = getWriter() - - val accountIds = accounts.map { it.technicalId } - writer.deleteDocumentsAndFlushChangesToDisk(BankAccountIdFieldName, *accountIds.toTypedArray()) - } - - - @Synchronized - protected open fun getWriter(): DocumentsWriter { - documentsWriter?.let { return it } - - val writer = DocumentsWriter(LuceneConfig.getAccountTransactionsIndexFolder(indexFolder)) - - documentsWriter = writer - - return writer - } - -} \ No newline at end of file diff --git a/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/search/LuceneTransactionPartySearcher.kt b/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/search/LuceneTransactionPartySearcher.kt deleted file mode 100644 index 6b5105a1..00000000 --- a/persistence/LuceneBankingPersistence/src/main/kotlin/net/dankito/banking/search/LuceneTransactionPartySearcher.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.dankito.banking.search - -import net.dankito.banking.LuceneConfig -import net.dankito.banking.LuceneConfig.Companion.OtherPartyAccountIdFieldName -import net.dankito.banking.LuceneConfig.Companion.OtherPartyBankCodeFieldName -import net.dankito.banking.LuceneConfig.Companion.OtherPartyNameFieldName -import net.dankito.utils.lucene.mapper.PropertyDescription -import net.dankito.utils.lucene.mapper.PropertyType -import net.dankito.utils.lucene.search.MappedSearchConfig -import net.dankito.utils.lucene.search.QueryBuilder -import net.dankito.utils.lucene.search.Searcher -import java.io.File - - -open class LuceneTransactionPartySearcher(indexFolder: File) : ITransactionPartySearcher { - - companion object { - - private val properties = listOf( - PropertyDescription(PropertyType.NullableString, OtherPartyNameFieldName, TransactionParty::name), - PropertyDescription(PropertyType.NullableString, OtherPartyBankCodeFieldName, TransactionParty::bic), - PropertyDescription(PropertyType.NullableString, OtherPartyAccountIdFieldName, TransactionParty::iban) - ) - - } - - - protected val queries = QueryBuilder() - - protected val searcher = Searcher(LuceneConfig.getAccountTransactionsIndexFolder(indexFolder)) - - - override fun findTransactionParty(query: String): List { - val luceneQuery = queries.createQueriesForSingleTerms(query.toLowerCase()) { singleTerm -> - listOf( - queries.fulltextQuery(OtherPartyNameFieldName, singleTerm) - ) - } - - return searcher.searchAndMap(MappedSearchConfig(luceneQuery, TransactionParty::class.java, properties)) - .toSet() // don't display same transaction party multiple times - .filterNot { it.iban.isNullOrBlank() || it.bic.isNullOrBlank() } // e.g. comdirect doesn't supply other party's IBAN and BIC -> filter these as they have no value for auto-entering a transaction party's IBAN and BIC - } - -} \ No newline at end of file diff --git a/persistence/LuceneBankingPersistence/src/test/kotlin/net/dankito/banking/search/LuceneTransactionPartySearcherTest.kt b/persistence/LuceneBankingPersistence/src/test/kotlin/net/dankito/banking/search/LuceneTransactionPartySearcherTest.kt deleted file mode 100644 index 1c714b98..00000000 --- a/persistence/LuceneBankingPersistence/src/test/kotlin/net/dankito/banking/search/LuceneTransactionPartySearcherTest.kt +++ /dev/null @@ -1,235 +0,0 @@ -package net.dankito.banking.search - -import net.dankito.banking.persistence.LuceneBankingPersistence -import net.dankito.banking.ui.model.BankData -import net.dankito.banking.ui.model.AccountTransaction -import net.dankito.banking.ui.model.BankAccount -import net.dankito.utils.io.FileUtils -import net.dankito.utils.multiplatform.File -import net.dankito.utils.multiplatform.toBigDecimal -import net.dankito.utils.multiplatform.toDate -import org.assertj.core.api.Assertions.assertThat -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.mockito.Mockito.mock -import java.math.BigDecimal -import java.text.SimpleDateFormat -import java.util.* -import java.util.concurrent.ThreadLocalRandom - - -class LuceneTransactionPartySearcherTest { - - companion object { - - private val dataFolder = File("testData") - - private val databaseFolder = File(dataFolder, "db") - - private val indexFolder = File(dataFolder, "index") - - - private val BookingDate = "27.03.2020" - private val OtherPartyName = "Mahatma Gandhi" - private val OtherPartyBankCode = "12345678" - private val OtherPartyAccountId = "0987654321" - private val Amount = BigDecimal.valueOf(123.45) - - - private val bankAccountMock = BankAccount(mock(BankData::class.java), "", "", null, null, "") - - - private val dateFormat = SimpleDateFormat("dd.MM.yyyy") - - } - - - private val fileUtils = FileUtils() - - private val bankingPersistence = LuceneBankingPersistence(indexFolder, databaseFolder) - - private val underTest = LuceneTransactionPartySearcher(indexFolder) - - - @Before - fun setUp() { - clearDataFolder() - } - - @After - fun tearDown() { - clearDataFolder() - } - - private fun clearDataFolder() { - fileUtils.deleteFolderRecursively(dataFolder) - } - - - @Test - fun findTransactionParty_ByFullName() { - - // given - val query = OtherPartyName - - val before = underTest.findTransactionParty(query) - assertThat(before).isEmpty() - - bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf( - createTransaction(bankAccountMock, BookingDate, Amount, OtherPartyName, OtherPartyBankCode, OtherPartyAccountId), - createTransaction(), - createTransaction() - )) - - - // when - val result = underTest.findTransactionParty(query) - - - // then - assertThat(result).hasSize(1) - assertThat(result.first().name).isEqualTo(OtherPartyName) - assertThat(result.first().bic).isEqualTo(OtherPartyBankCode) - assertThat(result.first().iban).isEqualTo(OtherPartyAccountId) - } - - @Test - fun findTransactionParty_ByPartialName() { - - // given - val query = "gand" - - val before = underTest.findTransactionParty(query) - assertThat(before).isEmpty() - - bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf( - createTransaction(bankAccountMock, BookingDate, Amount, OtherPartyName, OtherPartyBankCode, OtherPartyAccountId), - createTransaction(), - createTransaction() - )) - - - // when - val result = underTest.findTransactionParty(query) - - - // then - assertThat(result).hasSize(1) - assertThat(result.first().name).isEqualTo(OtherPartyName) - assertThat(result.first().bic).isEqualTo(OtherPartyBankCode) - assertThat(result.first().iban).isEqualTo(OtherPartyAccountId) - } - - @Test - fun findTransactionParty_SimilarNames() { - - // given - val query = "gand" - val secondOtherPartyName = "Gandalf" - - val before = underTest.findTransactionParty(query) - assertThat(before).isEmpty() - - bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf( - createTransaction(bankAccountMock, BookingDate, Amount, OtherPartyName, OtherPartyBankCode, OtherPartyAccountId), - createTransaction(otherPartyName = secondOtherPartyName), - createTransaction() - )) - - - // when - val result = underTest.findTransactionParty(query) - - - // then - assertThat(result).hasSize(2) - assertThat(result.map { it.name }).containsExactlyInAnyOrder(OtherPartyName, secondOtherPartyName) - } - - @Test - fun findTransactionParty_DuplicateEntries() { - - // given - val query = OtherPartyName - - val before = underTest.findTransactionParty(query) - assertThat(before).isEmpty() - - bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf( - createTransaction(bankAccountMock, BookingDate, Amount, OtherPartyName, OtherPartyBankCode, OtherPartyAccountId), - createTransaction(bankAccountMock, "01.02.2020", Amount, OtherPartyName, OtherPartyBankCode, OtherPartyAccountId), - createTransaction(bankAccountMock, "03.04.2020", Amount, OtherPartyName, OtherPartyBankCode, OtherPartyAccountId), - createTransaction(), - createTransaction() - )) - - - // when - val result = underTest.findTransactionParty(query) - - - // then - assertThat(result).hasSize(1) - assertThat(result.first().name).isEqualTo(OtherPartyName) - assertThat(result.first().bic).isEqualTo(OtherPartyBankCode) - assertThat(result.first().iban).isEqualTo(OtherPartyAccountId) - } - - @Test - fun findTransactionParty_OtherName() { - - // given - val query = "Mandela" - - val before = underTest.findTransactionParty(query) - assertThat(before).isEmpty() - - bankingPersistence.saveOrUpdateAccountTransactions(bankAccountMock, listOf( - createTransaction(bankAccountMock, BookingDate, Amount, OtherPartyName, OtherPartyBankCode, OtherPartyAccountId), - createTransaction(), - createTransaction() - )) - - - // when - val result = underTest.findTransactionParty(query) - - - // then - assertThat(result).isEmpty() - } - - - private fun createTransaction(bankAccount: BankAccount = bankAccountMock, bookingDate: String, amount: BigDecimal = randomBigDecimal(), - otherPartyName: String = randomString(), otherPartyBankCode: String = randomString(), - otherPartyAccountId: String = randomString(), reference: String = randomString()): AccountTransaction { - - return createTransaction(bankAccount, dateFormat.parse(bookingDate), amount, otherPartyName, - otherPartyBankCode, otherPartyAccountId, reference) - } - - private fun createTransaction(bankAccount: BankAccount = bankAccountMock, bookingDate: Date = randomDate(), amount: BigDecimal = randomBigDecimal(), - otherPartyName: String = randomString(), otherPartyBankCode: String = randomString(), - otherPartyAccountId: String = randomString(), reference: String = randomString()): AccountTransaction { - - return AccountTransaction(bankAccount, amount.toBigDecimal(), "EUR", reference, bookingDate.toDate(), otherPartyName, otherPartyBankCode, otherPartyAccountId, null, bookingDate.toDate()) - } - - private fun randomString(): String { - return UUID.randomUUID().toString() - } - - private fun randomDate(): Date { - val pseudoRandomLong = ThreadLocalRandom.current().nextLong(0, Date().time) - - return Date(pseudoRandomLong) - } - - private fun randomBigDecimal(): BigDecimal { - val pseudoRandomDouble = ThreadLocalRandom.current().nextDouble(-5-000.0, 12_000.0) - - return BigDecimal.valueOf(pseudoRandomDouble) - } - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/build.gradle b/persistence/database/RoomBankingPersistence/build.gradle deleted file mode 100644 index a4c9db2b..00000000 --- a/persistence/database/RoomBankingPersistence/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'kotlin-kapt' - -android { - compileSdkVersion androidCompileSdkVersion - buildToolsVersion androidBuildToolsVersion - - defaultConfig { - - minSdkVersion androidMinSdkVersion - targetSdkVersion androidTargetSdkVersion - - versionName version - versionCode appVersionCode - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - implementation project(':BankingUiCommon') - - implementation "androidx.room:room-runtime:$roomVersion" - kapt "androidx.room:room-compiler:$roomVersion" - implementation "androidx.room:room-ktx:$roomVersion" - - implementation "net.zetetic:android-database-sqlcipher:$sqlCipherVersion" - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/consumer-rules.pro b/persistence/database/RoomBankingPersistence/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/persistence/database/RoomBankingPersistence/proguard-rules.pro b/persistence/database/RoomBankingPersistence/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/persistence/database/RoomBankingPersistence/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/AndroidManifest.xml b/persistence/database/RoomBankingPersistence/src/main/AndroidManifest.xml deleted file mode 100644 index 622eda74..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - / - \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/BankingDatabase.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/BankingDatabase.kt deleted file mode 100644 index 6045d5f5..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/BankingDatabase.kt +++ /dev/null @@ -1,33 +0,0 @@ -package net.dankito.banking.persistence - -import androidx.room.Database -import androidx.room.RoomDatabase -import androidx.room.TypeConverters -import net.dankito.banking.persistence.dao.* -import net.dankito.banking.persistence.model.* - - -@Database(entities = [ - Bank::class, BankAccount::class, AccountTransaction::class, - TanMethod::class, TanMedium::class, - AppSettings::class, TanMethodSettings::class -], version = 1, exportSchema = false) -@TypeConverters(net.dankito.banking.persistence.TypeConverters::class) -abstract class BankingDatabase : RoomDatabase() { - - abstract fun bankDao(): BankDao - - abstract fun bankAccountDao(): BankAccountDao - - abstract fun accountTransactionDao(): AccountTransactionDao - - abstract fun tanMethodDao(): TanMethodDao - - abstract fun tanMediumDao(): TanMediumDao - - - abstract fun appSettingsDao(): AppSettingsDao - - abstract fun tanMethodSettingsDao(): TanMethodSettingsDao - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/RoomBankingPersistence.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/RoomBankingPersistence.kt deleted file mode 100644 index e061c6e1..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/RoomBankingPersistence.kt +++ /dev/null @@ -1,286 +0,0 @@ -package net.dankito.banking.persistence - -import android.content.Context -import androidx.room.Room -import net.dankito.banking.persistence.dao.BaseDao -import net.dankito.banking.persistence.dao.saveOrUpdate -import net.dankito.banking.persistence.model.* -import net.dankito.banking.search.ITransactionPartySearcher -import net.dankito.banking.search.TransactionParty -import net.dankito.banking.ui.model.IAccountTransaction -import net.dankito.banking.ui.model.TypedBankAccount -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.model.settings.AppSettings -import net.dankito.banking.ui.model.tan.MobilePhoneTanMedium -import net.dankito.banking.ui.model.tan.TanGeneratorTanMedium -import net.dankito.banking.util.persistence.downloadIcon -import net.dankito.utils.multiplatform.asString -import net.sqlcipher.database.SQLiteDatabase -import net.sqlcipher.database.SupportFactory -import org.slf4j.LoggerFactory -import java.util.concurrent.CopyOnWriteArraySet - - -open class RoomBankingPersistence(protected open val applicationContext: Context) : IBankingPersistence, ITransactionPartySearcher { - - companion object { - const val DatabaseName = "banking-database" - - const val AppSettingsId = 1 - - const val FlickerCodeTanMethodSettingsId = 1 - const val QrCodeTanMethodSettingsId = 2 - const val PhotoTanTanMethodSettingsId = 3 - - private val log = LoggerFactory.getLogger(RoomBankingPersistence::class.java) - } - - - protected lateinit var database: BankingDatabase - - protected open var isInitialized = false - - protected open val initializedListeners = CopyOnWriteArraySet<() -> Unit>() - - - override fun decryptData(password: CharArray): Boolean { - val result = openDatabase(password) - - if (result) { - callInitializedListeners() - } - - return result - } - - override fun changePassword(newPassword: CharArray): Boolean { - if (this::database.isInitialized) { - val cursor = database.query("PRAGMA rekey = '${newPassword.asString()}';", emptyArray()) - - return cursor.count == 1 // TODO: also check if first column content is 'ok' ? - } - else { // database hasn't been opened yet, that means we're on the first app run - return openDatabase(newPassword) - } - } - - protected open fun openDatabase(password: CharArray): Boolean { - try { - val passphrase = SQLiteDatabase.getBytes(password) - val factory = SupportFactory(passphrase) - - database = Room.databaseBuilder(applicationContext, BankingDatabase::class.java, DatabaseName) - .openHelperFactory(factory) - .build() - - return true - } catch (e: Exception) { - log.error("Could not open database", e) - } - - return false - } - - - override fun saveOrUpdateBank(bank: TypedBankData, allBanks: List) { - (bank as? Bank)?.let { bank -> - bank.selectedTanMethodId = bank.selectedTanMethod?.technicalId - - database.bankDao().saveOrUpdate(bank) - - // TODO: in this way removed accounts won't be deleted from DB and therefore still be visible to user - val accounts = bank.accounts.filterIsInstance() - accounts.forEach { it.bankId = bank.id } - database.bankAccountDao().saveOrUpdate(accounts) - - // TODO: in this way removed TAN methods won't be deleted from DB and therefore still be visible to user - val tanMethods = bank.supportedTanMethods.filterIsInstance() - tanMethods.forEach { tantanMethod -> - if (tantanMethod.bankId == BaseDao.ObjectNotInsertedId) { - tantanMethod.bankId = bank.id - database.tanMethodDao().insert(tantanMethod) - } - else { - database.tanMethodDao().update(tantanMethod) - } - } - - // TODO: in this way removed TAN media won't be deleted from DB and therefore still be visible to user - val tanMedia = bank.tanMedia.map { tanMedium -> - bank.tanMediumEntities.firstOrNull { it.id == tanMedium.technicalId } ?: map(bank, tanMedium) - } - database.tanMediumDao().saveOrUpdate(tanMedia) - bank.tanMediumEntities = tanMedia - } - } - - override fun deleteBank(bank: TypedBankData, allBanks: List) { - (bank as? Bank)?.let { bank -> - database.accountTransactionDao().delete(bank.accounts.flatMap { it.bookedTransactions }.filterIsInstance()) - - database.bankAccountDao().delete(bank.accounts.filterIsInstance()) - - database.tanMethodDao().delete(bank.supportedTanMethods.filterIsInstance()) - database.tanMediumDao().delete(bank.tanMedia.filterIsInstance()) - - database.bankDao().delete(bank) - } - } - - override fun readPersistedBanks(): List { - val banks = database.bankDao().getAll() - - val accounts = database.bankAccountDao().getAll() - - val transactions = database.accountTransactionDao().getAll() - - val tanMethods = database.tanMethodDao().getAll() - - val tanMedia = database.tanMediumDao().getAll() - - banks.forEach { bank -> - bank.accounts = accounts.filter { it.bankId == bank.id } - - bank.accounts.filterIsInstance().forEach { account -> - account.bank = bank - - account.bookedTransactions = transactions.filter { it.accountId == account.id } - - account.bookedTransactions.filterIsInstance().forEach { transaction -> - transaction.account = account - } - } - - bank.supportedTanMethods = tanMethods.filter { it.bankId == bank.id } - bank.selectedTanMethod = bank.supportedTanMethods.firstOrNull { it.technicalId == bank.selectedTanMethodId } - - bank.tanMediumEntities = tanMedia.filter { it.bankId == bank.id } - bank.tanMedia = bank.tanMediumEntities.map { map(it) } - } - - return banks - } - - override fun saveOrUpdateAccountTransactions(account: TypedBankAccount, transactions: List) { - val accountId = (account as? BankAccount)?.id ?: account.technicalId.toLong() - - val mappedTransactions = transactions.filterIsInstance() - - mappedTransactions.forEach { it.accountId = accountId } - - database.accountTransactionDao().saveOrUpdate(mappedTransactions) - } - - - protected open fun map(bank: Bank, tanMedium: net.dankito.banking.ui.model.tan.TanMedium): TanMedium { - val type = when (tanMedium) { - is TanGeneratorTanMedium -> TanMediumType.TanGeneratorTanMedium - is MobilePhoneTanMedium -> TanMediumType.MobilePhoneTanMedium - else -> TanMediumType.OtherTanMedium - } - - return TanMedium(tanMedium.technicalId, bank.id, type, tanMedium.displayName, tanMedium.status, - (tanMedium as? TanGeneratorTanMedium)?.cardNumber, (tanMedium as? MobilePhoneTanMedium)?.phoneNumber) - } - - protected open fun map(tanMedium: TanMedium): net.dankito.banking.ui.model.tan.TanMedium { - val displayName = tanMedium.displayName - val status = tanMedium.status - - val mapped = when (tanMedium.type) { - TanMediumType.TanGeneratorTanMedium -> TanGeneratorTanMedium(displayName, status, tanMedium.cardNumber ?: "") - TanMediumType.MobilePhoneTanMedium -> MobilePhoneTanMedium(displayName, status, tanMedium.phoneNumber) - else -> net.dankito.banking.ui.model.tan.TanMedium(displayName, status) - } - - mapped.technicalId = tanMedium.id - - return mapped - } - - - override fun saveOrUpdateAppSettings(appSettings: AppSettings) { - val mapped = net.dankito.banking.persistence.model.AppSettings(appSettings.automaticallyUpdateAccountsAfterMinutes, - appSettings.lockAppAfterMinutes, appSettings.screenshotsAllowed, appSettings.lastSelectedOpenPdfFolder, appSettings.lastSelectedImportFolder, appSettings.lastSelectedExportFolder) - database.appSettingsDao().saveOrUpdate(mapped) - - saveOrUpdateTanMethodSettings(appSettings.flickerCodeSettings, FlickerCodeTanMethodSettingsId) - saveOrUpdateTanMethodSettings(appSettings.qrCodeSettings, QrCodeTanMethodSettingsId) - saveOrUpdateTanMethodSettings(appSettings.photoTanSettings, PhotoTanTanMethodSettingsId) - } - - protected open fun saveOrUpdateTanMethodSettings(settings: net.dankito.banking.ui.model.settings.TanMethodSettings?, id: Int) { - settings?.let { - val settingsEntity = TanMethodSettings(id, it.width, it.height, it.space, it.frequency) - - database.tanMethodSettingsDao().saveOrUpdate(settingsEntity) - } - } - - override fun readPersistedAppSettings(): AppSettings? { - val tanMethodSettings = database.tanMethodSettingsDao().getAll() - - val settings = AppSettings() - - database.appSettingsDao().getAll().firstOrNull { it.id == AppSettingsId }?.let { persistedSettings -> - settings.automaticallyUpdateAccountsAfterMinutes = persistedSettings.automaticallyUpdateAccountsAfterMinutes - settings.lockAppAfterMinutes = persistedSettings.lockAppAfterMinutes - settings.screenshotsAllowed = persistedSettings.screenshotsAllowed - settings.lastSelectedOpenPdfFolder = persistedSettings.lastSelectedOpenPdfFolder - settings.lastSelectedImportFolder = persistedSettings.lastSelectedImportFolder - settings.lastSelectedExportFolder = persistedSettings.lastSelectedExportFolder - } - - settings.flickerCodeSettings = findTanMethodSettings(FlickerCodeTanMethodSettingsId, tanMethodSettings) - settings.qrCodeSettings = findTanMethodSettings(QrCodeTanMethodSettingsId, tanMethodSettings) - settings.photoTanSettings = findTanMethodSettings(PhotoTanTanMethodSettingsId, tanMethodSettings) - - return settings - } - - protected open fun findTanMethodSettings(id: Int, settings: List): TanMethodSettings? { - return settings.firstOrNull { it.id == id } - } - - - override fun saveBankIcon(bank: TypedBankData, iconUrl: String, fileExtension: String?) { - val iconData = downloadIcon(iconUrl) - bank.iconData = iconData - - (bank as? Bank)?.let { - database.bankDao().saveOrUpdate(it) - } - } - - - override fun findTransactionParty(query: String): List { - return database.accountTransactionDao().findTransactionParty(query) - .toSet() // don't display same transaction party multiple times - .filterNot { it.bankCode.isNullOrBlank() || it.accountId.isNullOrBlank() } - .map { TransactionParty(it.name, it.accountId, it.bankCode) } - } - - - override fun addInitializedListener(listener: () -> Unit) { - if (isInitialized) { - listener() - } else { - initializedListeners.add(listener) - } - } - - protected open fun callInitializedListeners() { - isInitialized = true - val copy = ArrayList(initializedListeners) - initializedListeners.clear() - - copy.forEach { listener -> { - try { - listener() - } catch (e: Exception) { - log.error("Could not call listener $listener", e) - } - } } - } - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/TypeConverters.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/TypeConverters.kt deleted file mode 100644 index b067a05c..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/TypeConverters.kt +++ /dev/null @@ -1,91 +0,0 @@ -package net.dankito.banking.persistence - -import androidx.room.TypeConverter -import net.dankito.banking.persistence.model.TanMediumType -import net.dankito.banking.ui.model.BankAccountType -import net.dankito.banking.ui.model.tan.AllowedTanFormat -import net.dankito.banking.ui.model.tan.TanMediumStatus -import net.dankito.banking.ui.model.tan.TanMethodType -import net.dankito.utils.multiplatform.BigDecimal -import net.dankito.utils.multiplatform.Date - - -open class TypeConverters { - - @TypeConverter - fun fromMultiplatformBigDecimal(value: BigDecimal?): String? { - return value?.toPlainString() - } - - @TypeConverter - fun toMultiplatformBigDecimal(value: String?): BigDecimal? { - return value?.let { BigDecimal(value) } - } - - - @TypeConverter - fun fromMultiplatformDate(value: Date?): Long? { - return value?.millisSinceEpoch - } - - @TypeConverter - fun toMultiplatformDate(value: Long?): Date? { - return value?.let { Date(value) } - } - - - @TypeConverter - fun fromBankAccountType(value: BankAccountType): Int { - return value.ordinal - } - - @TypeConverter - fun toBankAccountType(value: Int): BankAccountType { - return BankAccountType.values().first { it.ordinal == value } - } - - - @TypeConverter - fun fromTanMethodType(value: TanMethodType): Int { - return value.ordinal - } - - @TypeConverter - fun toTanMethodType(value: Int): TanMethodType { - return TanMethodType.values().first { it.ordinal == value } - } - - - @TypeConverter - fun fromAllowedTanFormat(value: AllowedTanFormat): Int { - return value.ordinal - } - - @TypeConverter - fun toAllowedTanFormat(value: Int): AllowedTanFormat { - return AllowedTanFormat.values().first { it.ordinal == value } - } - - - @TypeConverter - fun fromTanMediumStatus(value: TanMediumStatus): Int { - return value.ordinal - } - - @TypeConverter - fun toTanMediumStatus(value: Int): TanMediumStatus { - return TanMediumStatus.values().first { it.ordinal == value } - } - - - @TypeConverter - fun fromTanMediumTypes(value: TanMediumType): Int { - return value.ordinal - } - - @TypeConverter - fun toTanMediumType(value: Int): TanMediumType { - return TanMediumType.values().first { it.ordinal == value } - } - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/AccountTransactionDao.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/AccountTransactionDao.kt deleted file mode 100644 index bbb39265..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/AccountTransactionDao.kt +++ /dev/null @@ -1,18 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.Dao -import androidx.room.Query -import net.dankito.banking.persistence.model.AccountTransaction -import net.dankito.banking.persistence.model.TransactionParty - - -@Dao -interface AccountTransactionDao : BaseDao { - - @Query("SELECT * FROM AccountTransaction") - fun getAll(): List - - @Query("SELECT otherPartyName, otherPartyBankCode, otherPartyAccountId FROM AccountTransaction WHERE otherPartyName LIKE '%' || :query || '%'") - fun findTransactionParty(query: String): List - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/AppSettingsDao.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/AppSettingsDao.kt deleted file mode 100644 index 200db798..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/AppSettingsDao.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.* -import net.dankito.banking.persistence.model.AppSettings - - -@Dao -interface AppSettingsDao : BaseDao { - - @Query("SELECT * FROM AppSettings") - fun getAll(): List - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BankAccountDao.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BankAccountDao.kt deleted file mode 100644 index 3a4e2af6..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BankAccountDao.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.Dao -import androidx.room.Query -import net.dankito.banking.persistence.model.BankAccount - - -@Dao -interface BankAccountDao : BaseDao { - - @Query("SELECT * FROM BankAccount") - fun getAll(): List - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BankDao.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BankDao.kt deleted file mode 100644 index ed23ede9..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BankDao.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.* -import net.dankito.banking.persistence.model.Bank - - -@Dao -interface BankDao : BaseDao { - - @Query("SELECT * FROM Bank") - fun getAll(): List - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BaseDao.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BaseDao.kt deleted file mode 100644 index 794362cb..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BaseDao.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.* - - -interface BaseDao { - - companion object { - const val ObjectNotInsertedId = -1L - - const val IdNotSet = 0L - } - - - @Insert(onConflict = OnConflictStrategy.IGNORE) - fun insert(obj: T): Long - - @Insert(onConflict = OnConflictStrategy.IGNORE) - fun insert(obj: List): List - - - @Update(onConflict = OnConflictStrategy.IGNORE) - fun update(obj: T) - - @Update(onConflict = OnConflictStrategy.IGNORE) - fun update(obj: List) - - - @Delete - fun delete(obj: T) - - @Delete - fun delete(obj: List) - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BaseDaoExtensions.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BaseDaoExtensions.kt deleted file mode 100644 index 28dc3c97..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/BaseDaoExtensions.kt +++ /dev/null @@ -1,58 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.Transaction -import net.dankito.banking.persistence.model.* - - -/* Room didn't allow me to add these methods to BaseDao directly (Kapt error), so i defined them as extension methods */ - -@Transaction -fun BaseDao.saveOrUpdate(obj: T) { - val id = insert(obj) - - if (wasNotInserted(id)) { - update(obj) - } - else { - setId(obj, id) - } -} - -@Transaction -fun BaseDao.saveOrUpdate(objList: List) { - val ids = insert(objList) - - // i was not allowed to use mapIndexedNotNull() - val notInsertedObjects = mutableListOf() - ids.forEachIndexed { index, id -> - val obj = objList[index] - - if (wasNotInserted(id)) { - notInsertedObjects.add(obj) - } - else { - setId(obj, id) - } - } - - update(notInsertedObjects) -} - -private fun wasNotInserted(id: Long): Boolean { - return id == BaseDao.ObjectNotInsertedId -} - -private fun setId(obj: T, id: Long) { - if (obj is Bank) { - obj.id = id // why doesn't Room set this on itself? - obj.technicalId = obj.id.toString() - } - else if (obj is BankAccount) { - obj.id = id // why doesn't Room set this on itself? - obj.technicalId = obj.id.toString() - } - else if (obj is AccountTransaction) { - obj.id = id // why doesn't Room set this on itself? - obj.technicalId = obj.id.toString() - } -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMediumDao.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMediumDao.kt deleted file mode 100644 index 676c48b0..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMediumDao.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.Dao -import androidx.room.Query -import net.dankito.banking.persistence.model.TanMedium - - -@Dao -interface TanMediumDao : BaseDao { - - @Query("SELECT * FROM TanMedium") - fun getAll(): List - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMethodDao.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMethodDao.kt deleted file mode 100644 index cae83b1a..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMethodDao.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.Dao -import androidx.room.Query -import net.dankito.banking.persistence.model.TanMethod - - -@Dao -interface TanMethodDao : BaseDao { - - @Query("SELECT * FROM TanMethod") - fun getAll(): List - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMethodSettingsDao.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMethodSettingsDao.kt deleted file mode 100644 index 1aaca077..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/dao/TanMethodSettingsDao.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.dankito.banking.persistence.dao - -import androidx.room.* -import net.dankito.banking.persistence.model.TanMethodSettings - - -@Dao -interface TanMethodSettingsDao : BaseDao { - - @Query("SELECT * FROM TanMethodSettings") - fun getAll(): List - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/AccountTransaction.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/AccountTransaction.kt deleted file mode 100644 index 261df062..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/AccountTransaction.kt +++ /dev/null @@ -1,94 +0,0 @@ -package net.dankito.banking.persistence.model - -import androidx.room.Entity -import androidx.room.Ignore -import androidx.room.PrimaryKey -import net.dankito.banking.persistence.dao.BaseDao -import net.dankito.banking.ui.model.IAccountTransaction -import net.dankito.utils.multiplatform.* - - -@Entity -open class AccountTransaction( - @Ignore - override var account: BankAccount, - - override var amount: BigDecimal, - override var currency: String, - override var unparsedReference: String, - override var bookingDate: Date, - override var otherPartyName: String?, - override var otherPartyBankCode: String?, - override var otherPartyAccountId: String?, - override var bookingText: String?, - override var valueDate: Date, - override var statementNumber: Int, - override var sequenceNumber: Int?, - override var openingBalance: BigDecimal?, - override var closingBalance: BigDecimal?, - - override var endToEndReference: String?, - override var customerReference: String?, - override var mandateReference: String?, - override var creditorIdentifier: String?, - override var originatorsIdentificationCode: String?, - override var compensationAmount: String?, - override var originalAmount: String?, - override var sepaReference: String?, - override var deviantOriginator: String?, - override var deviantRecipient: String?, - override var referenceWithNoSpecialType: String?, - override var primaNotaNumber: String?, - override var textKeySupplement: String?, - - override var currencyType: String?, - override var bookingKey: String, - override var referenceForTheAccountOwner: String, - override var referenceOfTheAccountServicingInstitution: String?, - override var supplementaryDetails: String?, - - override var transactionReferenceNumber: String, - override var relatedReferenceNumber: String? -) : IAccountTransaction { - - // for object deserializers - internal constructor() : this(BankAccount(), null, "", BigDecimal.Zero, Date(), null) - - /* convenience constructors for languages not supporting default values */ - - constructor(account: BankAccount, otherPartyName: String?, unparsedReference: String, amount: BigDecimal, valueDate: Date, bookingText: String?) - : this(account, amount, "EUR", unparsedReference, valueDate, - otherPartyName, null, null, bookingText, valueDate) - - - constructor(account: BankAccount, amount: BigDecimal, currency: String, unparsedReference: String, bookingDate: Date, - otherPartyName: String?, otherPartyBankCode: String?, otherPartyAccountId: String?, - bookingText: String?, valueDate: Date) - : this(account, amount, currency, unparsedReference, bookingDate, - otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate, - 0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "", "", null, null, "", null) - - - @PrimaryKey(autoGenerate = true) - open var id: Long = BaseDao.IdNotSet - - override var technicalId: String = buildTransactionIdentifier() - - // Room doesn't allow me to add getters and setters -> have to map it manually - open var accountId: Long = BaseDao.ObjectNotInsertedId - - - override fun equals(other: Any?): Boolean { - return doesEqual(other) - } - - override fun hashCode(): Int { - return calculateHashCode() - } - - - override fun toString(): String { - return stringRepresentation - } - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/AppSettings.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/AppSettings.kt deleted file mode 100644 index 64fd8d0c..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/AppSettings.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.dankito.banking.persistence.model - -import androidx.room.Entity -import androidx.room.PrimaryKey -import net.dankito.banking.persistence.RoomBankingPersistence -import net.dankito.banking.ui.model.settings.AppSettings - - -@Entity -open class AppSettings( - open var automaticallyUpdateAccountsAfterMinutes: Int? = AppSettings.DefaultAutomaticallyUpdateAccountsAfterMinutes, - open var lockAppAfterMinutes: Int? = null, - open var screenshotsAllowed: Boolean = false, - open var lastSelectedOpenPdfFolder: String? = null, - open var lastSelectedImportFolder: String? = null, - open var lastSelectedExportFolder: String? = null -) { - - internal constructor() : this(AppSettings.DefaultAutomaticallyUpdateAccountsAfterMinutes, null, false) - - @PrimaryKey - open var id: Int = RoomBankingPersistence.AppSettingsId - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/Bank.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/Bank.kt deleted file mode 100644 index 468ce9e3..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/Bank.kt +++ /dev/null @@ -1,63 +0,0 @@ -package net.dankito.banking.persistence.model - -import androidx.room.Entity -import androidx.room.Ignore -import androidx.room.PrimaryKey -import net.dankito.banking.persistence.dao.BaseDao -import net.dankito.banking.ui.model.TypedBankAccount -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.model.tan.TanMedium -import net.dankito.banking.ui.model.tan.TanMethod - - -@Entity -open class Bank( - override var bankCode: String, - override var userName: String, - override var password: String, - override var finTsServerAddress: String, - override var bankName: String, - override var bic: String, - override var customerName: String, - - override var userId: String = userName, - override var iconData: ByteArray? = null, - - @Ignore - override var accounts: List = listOf(), - - @Ignore - override var supportedTanMethods: List = listOf(), - @Ignore - override var selectedTanMethod: TanMethod? = null, - @Ignore - override var tanMedia: List = listOf(), - - - @PrimaryKey(autoGenerate = true) - open var id: Long = BaseDao.IdNotSet, - - override var technicalId: String = id.toString(), - - override var wrongCredentialsEntered: Boolean = false, - - override var savePassword: Boolean = true, - - override var userSetDisplayName: String? = null, - override var displayIndex: Int = 0 -) : TypedBankData { - - internal constructor() : this("", "", "", "", "", "", "") // for object deserializers - - - open var selectedTanMethodId: String? = null - - @Ignore - open var tanMediumEntities = listOf() - - - override fun toString(): String { - return stringRepresentation - } - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/BankAccount.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/BankAccount.kt deleted file mode 100644 index fadc019c..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/BankAccount.kt +++ /dev/null @@ -1,82 +0,0 @@ -package net.dankito.banking.persistence.model - -import androidx.room.Entity -import androidx.room.Ignore -import androidx.room.PrimaryKey -import net.dankito.banking.persistence.dao.BaseDao -import net.dankito.banking.ui.model.* -import net.dankito.utils.multiplatform.BigDecimal -import net.dankito.utils.multiplatform.Date -import net.dankito.utils.multiplatform.UUID - - -@Entity -open class BankAccount( - @Ignore - override var bank: TypedBankData, - override var identifier: String, - override var accountHolderName: String, - override var iban: String?, - override var subAccountNumber: String?, - override var balance: BigDecimal = BigDecimal.Zero, - override var currency: String = "EUR", - override var type: BankAccountType = BankAccountType.CheckingAccount, - override var productName: String? = null, - override var accountLimit: String? = null, - override var retrievedTransactionsFromOn: Date? = null, - override var retrievedTransactionsUpTo: Date? = null, - - override var supportsRetrievingAccountTransactions: Boolean = false, - override var supportsRetrievingBalance: Boolean = false, - override var supportsTransferringMoney: Boolean = false, - override var supportsRealTimeTransfer: Boolean = false, - - @Ignore - override var bookedTransactions: List = listOf(), - @Ignore - override var unbookedTransactions: List = listOf() -) : TypedBankAccount { - - internal constructor() : this(Bank(), null, "") // for object deserializers - - /* convenience constructors for languages not supporting default values */ - - constructor(bank: TypedBankData, productName: String?, identifier: String) : this(bank, productName, identifier, BankAccountType.CheckingAccount) - - constructor(bank: TypedBankData, productName: String?, identifier: String, type: BankAccountType = BankAccountType.CheckingAccount, balance: BigDecimal = BigDecimal.Zero) - : this(bank, identifier, "", null, null, balance, "EUR", type, productName) - - - @PrimaryKey(autoGenerate = true) - open var id: Long = BaseDao.IdNotSet - - override var technicalId: String = UUID.random() - - // Room doesn't allow me to add getters and setters -> have to map it manually - open var bankId: Long = BaseDao.ObjectNotInsertedId - - - override var haveAllTransactionsBeenRetrieved: Boolean = false - - override var isAccountTypeSupportedByApplication: Boolean = true - - override var countDaysForWhichTransactionsAreKept: Int? = null - - - override var userSetDisplayName: String? = null - - override var displayIndex: Int = 0 - - - override var hideAccount = false - - override var includeInAutomaticAccountsUpdate = true - - override var doNotShowStrikingFetchAllTransactionsView = false - - - override fun toString(): String { - return stringRepresentation - } - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/RoomModelCreator.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/RoomModelCreator.kt deleted file mode 100644 index d61eba78..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/RoomModelCreator.kt +++ /dev/null @@ -1,75 +0,0 @@ -package net.dankito.banking.persistence.model - -import net.dankito.banking.ui.model.IAccountTransaction -import net.dankito.banking.ui.model.TypedBankAccount -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.model.mapper.IModelCreator -import net.dankito.banking.ui.model.tan.AllowedTanFormat -import net.dankito.banking.ui.model.tan.TanMethodType -import net.dankito.utils.multiplatform.BigDecimal -import net.dankito.utils.multiplatform.Date - - -open class RoomModelCreator : IModelCreator { - - override fun createBank( - bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String, - bic: String, customerName: String, userId: String, iconData: ByteArray? - ): TypedBankData { - - return Bank(bankCode, userName, password, finTsServerAddress, bankName, bic, customerName, userId, iconData) - } - - override fun createAccount(bank: TypedBankData, productName: String?, identifier: String): TypedBankAccount { - return BankAccount(bank, productName, identifier) - } - - override fun createTransaction( - account: TypedBankAccount, - amount: BigDecimal, - currency: String, - unparsedReference: String, - bookingDate: Date, - otherPartyName: String?, - otherPartyBankCode: String?, - otherPartyAccountId: String?, - bookingText: String?, - valueDate: Date, - statementNumber: Int, - sequenceNumber: Int?, - openingBalance: BigDecimal?, - closingBalance: BigDecimal?, - endToEndReference: String?, - customerReference: String?, - mandateReference: String?, - creditorIdentifier: String?, - originatorsIdentificationCode: String?, - compensationAmount: String?, - originalAmount: String?, - sepaReference: String?, - deviantOriginator: String?, - deviantRecipient: String?, - referenceWithNoSpecialType: String?, - primaNotaNumber: String?, - textKeySupplement: String?, - currencyType: String?, - bookingKey: String, - referenceForTheAccountOwner: String, - referenceOfTheAccountServicingInstitution: String?, - supplementaryDetails: String?, - transactionReferenceNumber: String, - relatedReferenceNumber: String? - ): IAccountTransaction { - return AccountTransaction(account as BankAccount, amount, currency, unparsedReference, bookingDate, otherPartyName, otherPartyBankCode, otherPartyAccountId, - bookingText, valueDate, statementNumber, sequenceNumber, openingBalance, closingBalance, endToEndReference, customerReference, mandateReference, - creditorIdentifier, originatorsIdentificationCode, compensationAmount, originalAmount, sepaReference, deviantOriginator, deviantRecipient, - referenceWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner, - referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber) - } - - - override fun createTanMethod(displayName: String, type: TanMethodType, bankInternalMethodCode: String, maxTanInputLength: Int?, allowedTanFormat: AllowedTanFormat): net.dankito.banking.ui.model.tan.TanMethod { - return TanMethod(displayName, type, bankInternalMethodCode, maxTanInputLength, allowedTanFormat) - } - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMedium.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMedium.kt deleted file mode 100644 index 9be6843b..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMedium.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.dankito.banking.persistence.model - -import androidx.room.Entity -import androidx.room.PrimaryKey -import net.dankito.banking.persistence.dao.BaseDao -import net.dankito.banking.ui.model.tan.TanMediumStatus - - -@Entity -open class TanMedium( - @PrimaryKey - open var id: String, - open var bankId: Long, - - open var type: TanMediumType, - open var displayName: String, - open var status: TanMediumStatus, - open var cardNumber: String? = null, - open var phoneNumber: String? = null -) { - - internal constructor() : this("", BaseDao.ObjectNotInsertedId, TanMediumType.OtherTanMedium, "", TanMediumStatus.Available) // for object deserializers - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMediumType.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMediumType.kt deleted file mode 100644 index 719273a4..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMediumType.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.dankito.banking.persistence.model - - -enum class TanMediumType { - - TanGeneratorTanMedium, - - MobilePhoneTanMedium, - - OtherTanMedium - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMethod.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMethod.kt deleted file mode 100644 index a8edd57f..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMethod.kt +++ /dev/null @@ -1,29 +0,0 @@ -package net.dankito.banking.persistence.model - -import androidx.room.Entity -import androidx.room.PrimaryKey -import net.dankito.banking.persistence.dao.BaseDao -import net.dankito.banking.ui.model.tan.AllowedTanFormat -import net.dankito.banking.ui.model.tan.TanMethod -import net.dankito.banking.ui.model.tan.TanMethodType - - -@Entity -open class TanMethod( - override var displayName: String, - override var type: TanMethodType, - override var bankInternalMethodCode: String, - override var maxTanInputLength: Int? = null, - override var allowedTanFormat: AllowedTanFormat = AllowedTanFormat.Alphanumeric -) : TanMethod(displayName, type, bankInternalMethodCode, maxTanInputLength, allowedTanFormat) { - - internal constructor() : this("", TanMethodType.EnterTan, "") // for object deserializers - - - @PrimaryKey - open var id: String = technicalId - - // Room doesn't allow me to add getters and setters -> have to map it manually - open var bankId: Long = BaseDao.ObjectNotInsertedId - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMethodSettings.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMethodSettings.kt deleted file mode 100644 index 40188863..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TanMethodSettings.kt +++ /dev/null @@ -1,21 +0,0 @@ -package net.dankito.banking.persistence.model - -import androidx.room.Entity -import androidx.room.PrimaryKey -import net.dankito.banking.persistence.dao.BaseDao -import net.dankito.banking.ui.model.settings.TanMethodSettings - - -@Entity -open class TanMethodSettings( - @PrimaryKey - open var id: Int, - width: Int, - height: Int, - space: Int = -1, - frequency: Int = -1 -) : TanMethodSettings(width, height, space, frequency) { - - internal constructor() : this(BaseDao.IdNotSet.toInt(), 0, 0) // for object deserializers - -} \ No newline at end of file diff --git a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TransactionParty.kt b/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TransactionParty.kt deleted file mode 100644 index 7d346bbc..00000000 --- a/persistence/database/RoomBankingPersistence/src/main/java/net/dankito/banking/persistence/model/TransactionParty.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.dankito.banking.persistence.model - -import androidx.room.ColumnInfo - - -data class TransactionParty( - @ColumnInfo(name = "otherPartyName") val name: String, - - @ColumnInfo(name = "otherPartyBankCode") val bankCode: String?, - - @ColumnInfo(name = "otherPartyAccountId") val accountId: String? -) \ No newline at end of file diff --git a/persistence/json/BankingPersistenceJson/README.md b/persistence/json/BankingPersistenceJson/README.md deleted file mode 100644 index 2e62b22f..00000000 --- a/persistence/json/BankingPersistenceJson/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# BankingPersistenceJson - -A simple IBankingPersistence implementation based on Json. - -Not meant to be a real or useful implementation. Just there to get you up and running fast. - -Preferably use another IBankingPersistence implementation, e.g. a JPA based one. \ No newline at end of file diff --git a/persistence/json/BankingPersistenceJson/build.gradle b/persistence/json/BankingPersistenceJson/build.gradle deleted file mode 100644 index 5177cf94..00000000 --- a/persistence/json/BankingPersistenceJson/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -apply plugin: 'java-library' -apply plugin: 'kotlin' -apply plugin: 'kotlin-kapt' - - -sourceCompatibility = "1.7" -targetCompatibility = "1.7" - -compileKotlin { - kotlinOptions.jvmTarget = "1.6" -} -compileTestKotlin { - kotlinOptions.jvmTarget = "1.6" -} - - -dependencies { - implementation project(':BankingUiCommon') - - - testImplementation "junit:junit:$junitVersion" - - testImplementation "org.assertj:assertj-core:$assertJVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - - testImplementation "org.slf4j:slf4j-simple:$slf4jVersion" -} \ No newline at end of file diff --git a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/BankingPersistenceJson.kt b/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/BankingPersistenceJson.kt deleted file mode 100644 index eea7e825..00000000 --- a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/BankingPersistenceJson.kt +++ /dev/null @@ -1,101 +0,0 @@ -package net.dankito.banking.persistence - -import net.dankito.banking.persistence.model.BankDataEntity -import net.dankito.banking.ui.model.* -import net.dankito.banking.ui.model.settings.AppSettings -import net.dankito.utils.multiplatform.File -import net.dankito.banking.util.ISerializer -import net.dankito.banking.util.persistence.downloadIcon - - -open class BankingPersistenceJson( - protected val databaseFolder: File, - protected val serializer: ISerializer -) : IBankingPersistence { - - companion object { - const val BanksJsonFileName = "accounts.json" - - const val AppSettingsJsonFileName = "app_settings.json" - } - - - protected val banksJsonFile: File - - protected val appSettingsJsonFile: File - - protected var allBanks: List? = null - - - init { - databaseFolder.mkdirs() - - banksJsonFile = File(databaseFolder, BanksJsonFileName) - appSettingsJsonFile = File(databaseFolder, AppSettingsJsonFileName) - } - - - override fun decryptData(password: CharArray): Boolean { - // TODO: may implement data decryption. But then we have to store password to be able to encrypt data - return true - } - - override fun changePassword(newPassword: CharArray): Boolean { - // TODO: may implement data decryption. But then we have to store newPassword to be able to encrypt data - return true - } - - - override fun saveOrUpdateBank(bank: TypedBankData, allBanks: List) { - saveAllBanks(allBanks) - } - - override fun deleteBank(bank: TypedBankData, allBanks: List) { - saveAllBanks(allBanks) - } - - override fun readPersistedBanks(): List { - val banks = serializer.deserializeListOr(banksJsonFile, BankDataEntity::class).map { it as TypedBankData } - - this.allBanks = banks - - return banks - } - - - override fun saveOrUpdateAccountTransactions(account: TypedBankAccount, transactions: List) { - // done when called saveOrUpdateAccount() - // TODO: or also call saveAllBanks()? - } - - - protected open fun saveAllBanks(allBanks: List) { - this.allBanks = allBanks - - serializer.serializeObject(allBanks, banksJsonFile) - } - - - override fun saveOrUpdateAppSettings(appSettings: AppSettings) { - serializer.serializeObject(appSettings, appSettingsJsonFile) - } - - override fun readPersistedAppSettings(): AppSettings? { - return serializer.deserializeObject(appSettingsJsonFile, AppSettings::class) - } - - - override fun saveBankIcon(bank: TypedBankData, iconUrl: String, fileExtension: String?) { - bank.iconData = downloadIcon(iconUrl) - - allBanks?.let { - saveOrUpdateBank(bank, it) - } - } - - - override fun addInitializedListener(listener: () -> Unit) { - listener() - } - -} \ No newline at end of file diff --git a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/mapper/EntitiesModelCreator.kt b/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/mapper/EntitiesModelCreator.kt deleted file mode 100644 index cc010de6..00000000 --- a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/mapper/EntitiesModelCreator.kt +++ /dev/null @@ -1,74 +0,0 @@ -package net.dankito.banking.persistence.mapper - -import net.dankito.banking.persistence.model.AccountTransactionEntity -import net.dankito.banking.persistence.model.BankAccountEntity -import net.dankito.banking.persistence.model.BankDataEntity -import net.dankito.banking.ui.model.IAccountTransaction -import net.dankito.banking.ui.model.TypedBankAccount -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.model.mapper.IModelCreator -import net.dankito.utils.multiplatform.BigDecimal -import net.dankito.utils.multiplatform.Date - - -open class EntitiesModelCreator : IModelCreator { - - override fun createBank( - bankCode: String, userName: String, password: String, finTsServerAddress: String, bankName: String, bic: String, - customerName: String, userId: String, iconData: ByteArray? - ): TypedBankData { - - return BankDataEntity(bankCode, userName, password, finTsServerAddress, bankName, bic, customerName, userId, iconData) as TypedBankData - } - - - override fun createAccount(bank: TypedBankData, productName: String?, identifier: String): TypedBankAccount { - return BankAccountEntity(bank as BankDataEntity, identifier, "", null, null, productName = productName) as TypedBankAccount - } - - override fun createTransaction( - account: TypedBankAccount, - amount: BigDecimal, - currency: String, - unparsedReference: String, - bookingDate: Date, - otherPartyName: String?, - otherPartyBankCode: String?, - otherPartyAccountId: String?, - bookingText: String?, - valueDate: Date, - statementNumber: Int, - sequenceNumber: Int?, - openingBalance: BigDecimal?, - closingBalance: BigDecimal?, - endToEndReference: String?, - customerReference: String?, - mandateReference: String?, - creditorIdentifier: String?, - originatorsIdentificationCode: String?, - compensationAmount: String?, - originalAmount: String?, - sepaReference: String?, - deviantOriginator: String?, - deviantRecipient: String?, - referenceWithNoSpecialType: String?, - primaNotaNumber: String?, - textKeySupplement: String?, - currencyType: String?, - bookingKey: String, - referenceForTheAccountOwner: String, - referenceOfTheAccountServicingInstitution: String?, - supplementaryDetails: String?, - transactionReferenceNumber: String, - relatedReferenceNumber: String? - ) : IAccountTransaction { - - return AccountTransactionEntity(account as BankAccountEntity, amount, currency, unparsedReference, bookingDate, - otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, valueDate, statementNumber, sequenceNumber, - openingBalance, closingBalance, endToEndReference, customerReference, mandateReference, creditorIdentifier, - originatorsIdentificationCode, compensationAmount, originalAmount, sepaReference, deviantOriginator, deviantRecipient, - referenceWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner, - referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber) - } - -} \ No newline at end of file diff --git a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/AccountTransactionEntity.kt b/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/AccountTransactionEntity.kt deleted file mode 100644 index f51ca477..00000000 --- a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/AccountTransactionEntity.kt +++ /dev/null @@ -1,77 +0,0 @@ -package net.dankito.banking.persistence.model - -import com.fasterxml.jackson.annotation.JsonIdentityInfo -import com.fasterxml.jackson.annotation.ObjectIdGenerators -import net.dankito.banking.ui.model.IAccountTransaction -import net.dankito.utils.multiplatform.BigDecimal -import net.dankito.utils.multiplatform.Date -import net.dankito.utils.multiplatform.UUID - - -@JsonIdentityInfo(property = "technicalId", generator = ObjectIdGenerators.PropertyGenerator::class) // to avoid stack overflow due to circular references -// had to define all properties as 'var' 'cause MapStruct cannot handle vals -open class AccountTransactionEntity( - override var account: BankAccountEntity, - override var amount: BigDecimal, - override var currency: String, - override var unparsedReference: String, - override var bookingDate: Date, - override var otherPartyName: String?, - override var otherPartyBankCode: String?, - override var otherPartyAccountId: String?, - override var bookingText: String?, - override var valueDate: Date, - override var statementNumber: Int, - override var sequenceNumber: Int?, - override var openingBalance: BigDecimal?, - override var closingBalance: BigDecimal?, - - override var endToEndReference: String?, - override var customerReference: String?, - override var mandateReference: String?, - override var creditorIdentifier: String?, - override var originatorsIdentificationCode: String?, - override var compensationAmount: String?, - override var originalAmount: String?, - override var sepaReference: String?, - override var deviantOriginator: String?, - override var deviantRecipient: String?, - override var referenceWithNoSpecialType: String?, - override var primaNotaNumber: String?, - override var textKeySupplement: String?, - - override var currencyType: String?, - override var bookingKey: String, - override var referenceForTheAccountOwner: String, - override var referenceOfTheAccountServicingInstitution: String?, - override var supplementaryDetails: String?, - - override var transactionReferenceNumber: String, - override var relatedReferenceNumber: String?, - override var technicalId: String = UUID.random() -) : IAccountTransaction { - - // for object deserializers - internal constructor() : this(BankAccountEntity(), BigDecimal.Zero, "", "", Date(), null, null, null, null, Date(), - -1, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "", "", null, - null, "", null) - - constructor(account: BankAccountEntity, otherPartyName: String?, unparsedReference: String, amount: BigDecimal, valueDate: Date, bookingText: String?) - : this(account, amount, "EUR", unparsedReference, valueDate, otherPartyName, null, null, bookingText, valueDate, 0, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, null, - null, "", "", null, null, "", null) - - - override fun equals(other: Any?): Boolean { - return doesEqual(other) - } - - override fun hashCode(): Int { - return calculateHashCode() - } - - override fun toString(): String { - return stringRepresentation - } - -} \ No newline at end of file diff --git a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/BankAccountEntity.kt b/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/BankAccountEntity.kt deleted file mode 100644 index 582bf17c..00000000 --- a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/BankAccountEntity.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.dankito.banking.persistence.model - -import com.fasterxml.jackson.annotation.JsonIdentityInfo -import com.fasterxml.jackson.annotation.ObjectIdGenerators -import net.dankito.banking.ui.model.* -import net.dankito.utils.multiplatform.BigDecimal -import net.dankito.utils.multiplatform.Date -import net.dankito.utils.multiplatform.UUID - - -@JsonIdentityInfo(property = "technicalId", generator = ObjectIdGenerators.PropertyGenerator::class) // to avoid stack overflow due to circular references -// had to define all properties as 'var' 'cause MapStruct cannot handle vals (and cannot use Pozo's mapstruct-kotlin as SerializableBankAccountBuilder would fail with @Context) -open class BankAccountEntity( - override var bank: BankDataEntity, - override var identifier: String, - override var accountHolderName: String, - override var iban: String?, - override var subAccountNumber: String?, - override var balance: BigDecimal = BigDecimal.Zero, - override var currency: String = "EUR", - override var type: BankAccountType = BankAccountType.CheckingAccount, - override var productName: String? = null, - override var accountLimit: String? = null, - override var retrievedTransactionsFromOn: Date? = null, - override var retrievedTransactionsUpTo: Date? = null, - override var supportsRetrievingAccountTransactions: Boolean = false, - override var supportsRetrievingBalance: Boolean = false, - override var supportsTransferringMoney: Boolean = false, - override var supportsRealTimeTransfer: Boolean = false, - override var bookedTransactions: List = listOf(), - override var unbookedTransactions: List = listOf(), - override var technicalId: String = UUID.random(), - override var userSetDisplayName: String? = null, - override var haveAllTransactionsBeenRetrieved: Boolean = false, - override var isAccountTypeSupportedByApplication: Boolean = true, - override var countDaysForWhichTransactionsAreKept: Int? = null, - override var displayIndex: Int = 0, - override var hideAccount: Boolean = false, - override var includeInAutomaticAccountsUpdate: Boolean = true, - override var doNotShowStrikingFetchAllTransactionsView: Boolean = false - -) : IBankAccount { - - internal constructor() : this(BankDataEntity(), "", "", null, null) // for object deserializers - - - override fun toString(): String { - return stringRepresentation - } - -} \ No newline at end of file diff --git a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/BankDataEntity.kt b/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/BankDataEntity.kt deleted file mode 100644 index 224add0b..00000000 --- a/persistence/json/BankingPersistenceJson/src/main/kotlin/net/dankito/banking/persistence/model/BankDataEntity.kt +++ /dev/null @@ -1,40 +0,0 @@ -package net.dankito.banking.persistence.model - -import com.fasterxml.jackson.annotation.* -import net.dankito.banking.ui.model.IBankData -import net.dankito.banking.ui.model.tan.TanMedium -import net.dankito.banking.ui.model.tan.TanMethod -import java.util.* - - -@JsonIdentityInfo(property = "technicalId", generator = ObjectIdGenerators.PropertyGenerator::class) // to avoid stack overflow due to circular references -// had to define all properties as 'var' 'cause MapStruct cannot handle vals (and cannot use Pozo's mapstruct-kotlin as SerializableCustomerBuilder would fail with @Context) -open class BankDataEntity( - override var bankCode: String, - override var userName: String, - override var password: String, - override var finTsServerAddress: String, - override var bankName: String, - override var bic: String, - override var customerName: String, - override var userId: String = userName, - override var iconData: ByteArray? = null, - override var accounts: List = listOf(), - override var supportedTanMethods: List = listOf(), - override var selectedTanMethod: TanMethod? = null, - override var tanMedia: List = listOf(), - override var technicalId: String = UUID.randomUUID().toString(), - override var wrongCredentialsEntered: Boolean = false, - override var savePassword: Boolean = true, - override var userSetDisplayName: String? = null, - override var displayIndex: Int = 0 -) : IBankData { - - internal constructor() : this("", "", "", "", "", "", "") // for object deserializers - - - override fun toString(): String { - return stringRepresentation - } - -} \ No newline at end of file diff --git a/persistence/json/BankingPersistenceJson/src/test/kotlin/net/dankito/banking/persistence/BankingPersistenceJsonTest.kt b/persistence/json/BankingPersistenceJson/src/test/kotlin/net/dankito/banking/persistence/BankingPersistenceJsonTest.kt deleted file mode 100644 index dcb92631..00000000 --- a/persistence/json/BankingPersistenceJson/src/test/kotlin/net/dankito/banking/persistence/BankingPersistenceJsonTest.kt +++ /dev/null @@ -1,238 +0,0 @@ -package net.dankito.banking.persistence - -import net.dankito.banking.persistence.model.AccountTransactionEntity -import net.dankito.banking.persistence.model.BankAccountEntity -import net.dankito.banking.persistence.model.BankDataEntity -import net.dankito.banking.ui.model.* -import net.dankito.banking.util.JacksonJsonSerializer -import net.dankito.utils.multiplatform.BigDecimal -import net.dankito.utils.multiplatform.Date -import net.dankito.utils.multiplatform.File -import org.assertj.core.api.Assertions.assertThat -import org.junit.Assert -import org.junit.Test -import kotlin.random.Random - - -class BankingPersistenceJsonTest { - - companion object { - - const val BankCode = "12345678" - - const val CustomerId = "0987654321" - - const val Password = "12345" - - const val FinTsServerAddress = "http://i-do-not-exist.fail/givemeyourmoney" - - const val BankName = "Abzock GmbH" - - const val Bic = "ABCDDEBB123" - - const val CustomerName = "Hans Dampf" - - const val UserId = CustomerId - - val NowMillis = System.currentTimeMillis() - - val TwoYearsAgoMillis = NowMillis - (2 * 365 * 24 * 60 * 60 * 1000L) - - - val TestDataFolder = File("testData") - - init { - TestDataFolder.mkdirs() - } - } - - - private val file = File(TestDataFolder, BankingPersistenceJson.BanksJsonFileName) - - private val serializer = JacksonJsonSerializer() - - private val underTest = BankingPersistenceJson(TestDataFolder, serializer) - - - @Test - fun saveOrUpdateBank() { - - // given - val banks = listOf( - createBank(2), - createBank(3) - ) - - - // when - underTest.saveOrUpdateBank(banks.first() as TypedBankData, banks.map { it as TypedBankData }) - - - // then - val result = serializer.deserializeListOr(file, BankDataEntity::class) - - assertBanksEqual(result, banks) - } - - @Test - fun saveOrUpdateBankWithAccountsAndTransactions() { - - // given - val bank = createBank(2) - - - // when - underTest.saveOrUpdateBank(bank as TypedBankData, listOf(bank).map { it as TypedBankData }) - - - // then - val result = serializer.deserializeListOr(file, BankDataEntity::class) - - assertBanksEqual(result, listOf(bank) as List) - } - - - @Test - fun readPersistedBanks() { - - // given - val banks = listOf( - createBank(2), - createBank(3) - ) - - serializer.serializeObject(banks, file) - - - // when - val result = underTest.readPersistedBanks() - - - // then - assertBanksEqual(banks, result as List) - } - - - private fun createBank(countAccounts: Int = 0, customerId: String = CustomerId): BankDataEntity { - val result = BankDataEntity(BankCode, customerId, Password, FinTsServerAddress, BankName, Bic, CustomerName, UserId, null) - - result.accounts = createAccounts(countAccounts, result) - - return result - } - - private fun createAccounts(count: Int, customer: BankDataEntity): List { - val random = Random(System.nanoTime()) - - return IntRange(1, count).map { accountIndex -> - createAccount("Account_$accountIndex", customer, random.nextInt(2, 50)) - } - } - - private fun createAccount(productName: String, customer: BankDataEntity, countTransactions: Int = 0): BankAccountEntity { - val result = BankAccountEntity(customer, customer.userName, "AccountHolder", "DE00" + customer.bankCode + customer.userName, null, - BigDecimal(84.25), productName = productName) - - result.bookedTransactions = createTransactions(countTransactions, result) - - return result - } - - private fun createTransactions(countTransactions: Int, account: BankAccountEntity): List { - return IntRange(1, countTransactions).map { transactionIndex -> - createTransaction(transactionIndex, account) - } - } - - private fun createTransaction(transactionIndex: Int, account: BankAccountEntity): AccountTransactionEntity { - return AccountTransactionEntity(account, "OtherParty_$transactionIndex", "Reference_$transactionIndex", BigDecimal(transactionIndex.toDouble()), createDate(), null) - } - - private fun createDate(): Date { - return Date(Random(System.nanoTime()).nextLong(TwoYearsAgoMillis, NowMillis)) - } - - - private fun assertBanksEqual(deserializedBanks: List, banks: List) { - assertThat(deserializedBanks.size).isEqualTo(banks.size) - - deserializedBanks.forEach { deserializedBanks -> - val bank = banks.firstOrNull { it.technicalId == deserializedBanks.technicalId } - - if (bank == null) { - Assert.fail("Could not find matching bank for deserialized bank $deserializedBanks. banks = $banks") - } - else { - assertBanksEqual(deserializedBanks, bank) - } - } - } - - private fun assertBanksEqual(deserializedBank: BankDataEntity, bank: BankDataEntity) { - assertThat(deserializedBank.bankCode).isEqualTo(bank.bankCode) - assertThat(deserializedBank.userName).isEqualTo(bank.userName) - assertThat(deserializedBank.password).isEqualTo(bank.password) - assertThat(deserializedBank.finTsServerAddress).isEqualTo(bank.finTsServerAddress) - - assertThat(deserializedBank.bankName).isEqualTo(bank.bankName) - assertThat(deserializedBank.bic).isEqualTo(bank.bic) - assertThat(deserializedBank.customerName).isEqualTo(bank.customerName) - assertThat(deserializedBank.userId).isEqualTo(bank.userId) - assertThat(deserializedBank.iconData).isEqualTo(bank.iconData) - - assertAccountsEqual(deserializedBank.accounts, bank.accounts) - } - - private fun assertAccountsEqual(deserializedAccounts: List, accounts: List) { - assertThat(deserializedAccounts.size).isEqualTo(accounts.size) - - deserializedAccounts.forEach { deserializedAccount -> - val account = accounts.firstOrNull { it.technicalId == deserializedAccount.technicalId } - - if (account == null) { - Assert.fail("Could not find matching account for deserialized account $deserializedAccount. accounts = $accounts") - } - else { - assertAccountsEqual(deserializedAccount, account) - } - } - } - - private fun assertAccountsEqual(deserializedAccount: BankAccountEntity, account: BankAccountEntity) { - // to check if MapStruct created reference correctly - assertThat(deserializedAccount.bank.technicalId).isEqualTo(account.bank.technicalId) - - assertThat(deserializedAccount.identifier).isEqualTo(account.identifier) - assertThat(deserializedAccount.iban).isEqualTo(account.iban) - assertThat(deserializedAccount.balance).isEqualTo(account.balance) - assertThat(deserializedAccount.productName).isEqualTo(account.productName) - - assertTransactionsEqual(deserializedAccount.bookedTransactions, account.bookedTransactions) - } - - private fun assertTransactionsEqual(deserializedTransactions: List, transactions: List) { - assertThat(deserializedTransactions.size).isEqualTo(transactions.size) - - deserializedTransactions.forEach { deserializedTransaction -> - val transaction = transactions.firstOrNull { it.technicalId == deserializedTransaction.technicalId } - - if (transaction == null) { - Assert.fail("Could not find matching transaction for deserialized transaction $deserializedTransaction. transactions = $transactions") - } - else { - assertTransactionsEqual(deserializedTransaction, transaction) - } - } - } - - private fun assertTransactionsEqual(deserializedTransaction: AccountTransactionEntity, transaction: AccountTransactionEntity) { - // to check if MapStruct created reference correctly - assertThat(deserializedTransaction.account.technicalId).isEqualTo(transaction.account.technicalId) - - assertThat(deserializedTransaction.otherPartyName).isEqualTo(transaction.otherPartyName) - assertThat(deserializedTransaction.unparsedReference).isEqualTo(transaction.unparsedReference) - assertThat(deserializedTransaction.amount).isEqualTo(transaction.amount) - assertThat(deserializedTransaction.valueDate).isEqualTo(transaction.valueDate) - } - -} \ No newline at end of file diff --git a/rest/BankFinderRest/.dockerignore b/rest/BankFinderRest/.dockerignore deleted file mode 100644 index 4361d2fb..00000000 --- a/rest/BankFinderRest/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -* -!build/*-runner -!build/*-runner.jar -!build/lib/* -!build/quarkus-app/* \ No newline at end of file diff --git a/rest/BankFinderRest/build.gradle b/rest/BankFinderRest/build.gradle deleted file mode 100644 index 6c9b04fc..00000000 --- a/rest/BankFinderRest/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -plugins { - id 'org.jetbrains.kotlin.jvm' - id "org.jetbrains.kotlin.plugin.allopen" version "1.3.72" - id 'io.quarkus' -} - -apply plugin: 'java-library' -apply plugin: 'kotlin' - - - -dependencies { - implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' - - // TODO: why can't Gradle find BankFinder project? .jars have temporarily to be copied to libs folder - which are not committed to repo of course - till this issue is fixed -// implementation project(path: ":common", configuration: 'jvmDefault') -// implementation project(path: ":BankFinder", configuration: 'jvmDefault') -// implementation "net.dankito.banking:BankFinder-jvm:$version" - - implementation fileTree(dir: 'libs', include: ['*.jar']) - - implementation "net.dankito.utils:java-utils:$javaUtilsVersion" - - implementation enforcedPlatform("io.quarkus:quarkus-bom:$quarkusVersion") - implementation 'io.quarkus:quarkus-kotlin' - implementation 'io.quarkus:quarkus-resteasy' - implementation 'io.quarkus:quarkus-resteasy-jackson' - - testImplementation 'io.quarkus:quarkus-junit5' - testImplementation 'io.rest-assured:kotlin-extensions' -} - - -quarkus { - setOutputDirectory("$projectDir/build/classes/kotlin/main") -} - -quarkusDev { - setSourceDir("$projectDir/src/main/kotlin") -} - -allOpen { - annotation("javax.ws.rs.Path") - annotation("javax.enterprise.context.ApplicationScoped") - annotation("io.quarkus.test.junit.QuarkusTest") -} - - -def javaVersion = JavaVersion.VERSION_11 - -java { - sourceCompatibility = javaVersion - targetCompatibility = javaVersion -} - -compileKotlin { - kotlinOptions.jvmTarget = javaVersion - kotlinOptions.javaParameters = true -} - -compileTestKotlin { - kotlinOptions.jvmTarget = javaVersion -} -test { - systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager" -} \ No newline at end of file diff --git a/rest/BankFinderRest/src/main/docker/Dockerfile.fast-jar b/rest/BankFinderRest/src/main/docker/Dockerfile.fast-jar deleted file mode 100644 index 2793e081..00000000 --- a/rest/BankFinderRest/src/main/docker/Dockerfile.fast-jar +++ /dev/null @@ -1,57 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode -# -# Before building the container image run: -# -# mvn package -Dquarkus.package.type=fast-jar -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.fast-jar -t codinux/bank-finder-fast-jar . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 codinux/bank-finder-fast-jar -# -# If you want to include the debug port into your docker image -# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 -# -# Then run the container using : -# -# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" codinux/bank-finder-fast-jar -# -### -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 - -ARG JAVA_PACKAGE=java-11-openjdk-headless -ARG RUN_JAVA_VERSION=1.3.8 - -ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' - -# Install java and the run-java script -# Also set up permissions for user `1001` -RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ - && microdnf update \ - && microdnf clean all \ - && mkdir /deployments \ - && chown 1001 /deployments \ - && chmod "g+rwX" /deployments \ - && chown 1001:root /deployments \ - && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ - && chown 1001 /deployments/run-java.sh \ - && chmod 540 /deployments/run-java.sh \ - && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security - -# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. -ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" - -# We make four distinct layers so if there are application changes the library layers can be re-used -COPY --chown=1001 build/quarkus-app/lib/ /deployments/lib/ -COPY --chown=1001 build/quarkus-app/*.jar /deployments/ -COPY --chown=1001 build/quarkus-app/app/ /deployments/app/ -COPY --chown=1001 build/quarkus-app/quarkus/ /deployments/quarkus/ - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT [ "/deployments/run-java.sh" ] \ No newline at end of file diff --git a/rest/BankFinderRest/src/main/docker/Dockerfile.jvm b/rest/BankFinderRest/src/main/docker/Dockerfile.jvm deleted file mode 100644 index 771a9ae2..00000000 --- a/rest/BankFinderRest/src/main/docker/Dockerfile.jvm +++ /dev/null @@ -1,54 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode -# -# Before building the container image run: -# -# mvn package -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.jvm -t codinux/bank-finder-jvm . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 codinux/bank-finder-jvm -# -# If you want to include the debug port into your docker image -# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 -# -# Then run the container using : -# -# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" codinux/bank-finder-jvm -# -### -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 - -ARG JAVA_PACKAGE=java-11-openjdk-headless -ARG RUN_JAVA_VERSION=1.3.8 - -ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' - -# Install java and the run-java script -# Also set up permissions for user `1001` -RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ - && microdnf update \ - && microdnf clean all \ - && mkdir /deployments \ - && chown 1001 /deployments \ - && chmod "g+rwX" /deployments \ - && chown 1001:root /deployments \ - && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ - && chown 1001 /deployments/run-java.sh \ - && chmod 540 /deployments/run-java.sh \ - && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security - -# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. -ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" - -COPY build/lib/* /deployments/lib/ -COPY build/*-runner.jar /deployments/app.jar - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT [ "/deployments/run-java.sh" ] \ No newline at end of file diff --git a/rest/BankFinderRest/src/main/docker/Dockerfile.native b/rest/BankFinderRest/src/main/docker/Dockerfile.native deleted file mode 100644 index 39ba04c6..00000000 --- a/rest/BankFinderRest/src/main/docker/Dockerfile.native +++ /dev/null @@ -1,27 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode -# -# Before building the container image run: -# -# mvn package -Pnative -Dquarkus.native.container-build=true -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.native -t codinux/bank-finder . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 codinux/bank-finder -# -### -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 -WORKDIR /work/ -RUN chown 1001 /work \ - && chmod "g+rwX" /work \ - && chown 1001:root /work -COPY --chown=1001:root build/*-runner /work/application - -EXPOSE 8080 -USER 1001 - -CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] \ No newline at end of file diff --git a/rest/BankFinderRest/src/main/kotlin/net/dankito/banking/bankfinder/rest/BankFinderResource.kt b/rest/BankFinderRest/src/main/kotlin/net/dankito/banking/bankfinder/rest/BankFinderResource.kt deleted file mode 100644 index 36df7493..00000000 --- a/rest/BankFinderRest/src/main/kotlin/net/dankito/banking/bankfinder/rest/BankFinderResource.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.dankito.banking.bankfinder.rest - -import net.dankito.banking.bankfinder.BankInfo -import net.dankito.banking.bankfinder.InMemoryBankFinder -import org.jboss.resteasy.annotations.jaxrs.PathParam -import javax.ws.rs.GET -import javax.ws.rs.Path -import javax.ws.rs.Produces -import javax.ws.rs.core.MediaType - - -@Path("/bankfinder") -class BankFinderResource { - - protected var bankFinder = InMemoryBankFinder() - - - @GET - @Produces(MediaType.APPLICATION_JSON) - @Path("{query}") - fun findBank(@PathParam query: String): List { - return bankFinder.findBankByNameBankCodeOrCity(query) - } - -} \ No newline at end of file diff --git a/rest/BankFinderRest/src/main/resources/application.properties b/rest/BankFinderRest/src/main/resources/application.properties deleted file mode 100644 index 4c6d1e55..00000000 --- a/rest/BankFinderRest/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -quarkus.http.port=5666 \ No newline at end of file diff --git a/rest/BankFinderRest/src/native-test/kotlin/net/dankito/banking/bankfinder/rest/NativeBankFinderResourceIT.kt b/rest/BankFinderRest/src/native-test/kotlin/net/dankito/banking/bankfinder/rest/NativeBankFinderResourceIT.kt deleted file mode 100644 index c3437278..00000000 --- a/rest/BankFinderRest/src/native-test/kotlin/net/dankito/banking/bankfinder/rest/NativeBankFinderResourceIT.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.dankito.banking.bankfinder.rest - -import io.quarkus.test.junit.NativeImageTest - -@NativeImageTest -class NativeBankFinderResourceIT : ExampleResourceTest() \ No newline at end of file diff --git a/rest/BankFinderRest/src/test/kotlin/net/dankito/banking/bankfinder/rest/BankFinderResourceTest.kt b/rest/BankFinderRest/src/test/kotlin/net/dankito/banking/bankfinder/rest/BankFinderResourceTest.kt deleted file mode 100644 index 4bb0ce8a..00000000 --- a/rest/BankFinderRest/src/test/kotlin/net/dankito/banking/bankfinder/rest/BankFinderResourceTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package net.dankito.banking.bankfinder.rest - -import io.quarkus.test.junit.QuarkusTest -import io.restassured.RestAssured.given -import org.hamcrest.CoreMatchers.containsString -import org.junit.jupiter.api.Test - - -@QuarkusTest -class BankFinderResourceTest { - - @Test - fun testSparkasse() { - given() - .`when`().get("/bankfinder/Sparkasse") - .then() - .statusCode(200) - .body(containsString("Berliner Sparkasse")) - .body(containsString("\"bankCode\":\"10050000\"")) - } - -} \ No newline at end of file diff --git a/rest/fints4kRest/.dockerignore b/rest/fints4kRest/.dockerignore deleted file mode 100644 index 4361d2fb..00000000 --- a/rest/fints4kRest/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -* -!build/*-runner -!build/*-runner.jar -!build/lib/* -!build/quarkus-app/* \ No newline at end of file diff --git a/rest/fints4kRest/build.gradle b/rest/fints4kRest/build.gradle deleted file mode 100644 index bbdd6852..00000000 --- a/rest/fints4kRest/build.gradle +++ /dev/null @@ -1,65 +0,0 @@ -plugins { - id 'org.jetbrains.kotlin.jvm' - id "org.jetbrains.kotlin.plugin.allopen" version "1.3.72" - id 'io.quarkus' -} - - -dependencies { - implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' - - // TODO: why can't Gradle find fints4k project? .jars have temporarily to be copied to libs folder - which are not committed to repo of course - till this issue is fixed - implementation fileTree(dir: 'libs', include: ['*.jar']) - - implementation "net.dankito.utils:java-utils:$javaUtilsVersion" - - implementation "io.ktor:ktor-client-okhttp:$ktorVersion" - - implementation "org.slf4j:slf4j-api:$slf4jVersion" - - implementation enforcedPlatform("io.quarkus:quarkus-bom:$quarkusVersion") - implementation 'io.quarkus:quarkus-kotlin' - implementation 'io.quarkus:quarkus-resteasy' - implementation 'io.quarkus:quarkus-resteasy-jackson' - - implementation "ch.qos.logback:logback-classic:$logbackVersion" - - - testImplementation 'io.quarkus:quarkus-junit5' - testImplementation 'io.rest-assured:kotlin-extensions' -} - - -quarkus { - setOutputDirectory("$projectDir/build/classes/kotlin/main") -} - -quarkusDev { - setSourceDir("$projectDir/src/main/kotlin") -} - -allOpen { - annotation("javax.ws.rs.Path") - annotation("javax.enterprise.context.ApplicationScoped") - annotation("io.quarkus.test.junit.QuarkusTest") -} - - -def javaVersion = JavaVersion.VERSION_11 - -java { - sourceCompatibility = javaVersion - targetCompatibility = javaVersion -} - -compileKotlin { - kotlinOptions.jvmTarget = javaVersion - kotlinOptions.javaParameters = true -} - -compileTestKotlin { - kotlinOptions.jvmTarget = javaVersion -} -test { - systemProperty "java.util.logging.manager", "org.jboss.logmanager.LogManager" -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/docker/Dockerfile.fast-jar b/rest/fints4kRest/src/main/docker/Dockerfile.fast-jar deleted file mode 100644 index ed4e2dd9..00000000 --- a/rest/fints4kRest/src/main/docker/Dockerfile.fast-jar +++ /dev/null @@ -1,57 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode -# -# Before building the container image run: -# -# mvn package -Dquarkus.package.type=fast-jar -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.fast-jar -t codinux/fints4k-fast-jar . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 codinux/fints4k-fast-jar -# -# If you want to include the debug port into your docker image -# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 -# -# Then run the container using : -# -# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" codinux/fints4k-fast-jar -# -### -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 - -ARG JAVA_PACKAGE=java-11-openjdk-headless -ARG RUN_JAVA_VERSION=1.3.8 - -ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' - -# Install java and the run-java script -# Also set up permissions for user `1001` -RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ - && microdnf update \ - && microdnf clean all \ - && mkdir /deployments \ - && chown 1001 /deployments \ - && chmod "g+rwX" /deployments \ - && chown 1001:root /deployments \ - && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ - && chown 1001 /deployments/run-java.sh \ - && chmod 540 /deployments/run-java.sh \ - && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security - -# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. -ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" - -# We make four distinct layers so if there are application changes the library layers can be re-used -COPY --chown=1001 build/quarkus-app/lib/ /deployments/lib/ -COPY --chown=1001 build/quarkus-app/*.jar /deployments/ -COPY --chown=1001 build/quarkus-app/app/ /deployments/app/ -COPY --chown=1001 build/quarkus-app/quarkus/ /deployments/quarkus/ - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT [ "/deployments/run-java.sh" ] \ No newline at end of file diff --git a/rest/fints4kRest/src/main/docker/Dockerfile.jvm b/rest/fints4kRest/src/main/docker/Dockerfile.jvm deleted file mode 100644 index 0e76ac92..00000000 --- a/rest/fints4kRest/src/main/docker/Dockerfile.jvm +++ /dev/null @@ -1,54 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode -# -# Before building the container image run: -# -# mvn package -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.jvm -t codinux/fints4k-jvm . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 codinux/fints4k-jvm -# -# If you want to include the debug port into your docker image -# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 -# -# Then run the container using : -# -# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" codinux/fints4k-jvm -# -### -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 - -ARG JAVA_PACKAGE=java-11-openjdk-headless -ARG RUN_JAVA_VERSION=1.3.8 - -ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' - -# Install java and the run-java script -# Also set up permissions for user `1001` -RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ - && microdnf update \ - && microdnf clean all \ - && mkdir /deployments \ - && chown 1001 /deployments \ - && chmod "g+rwX" /deployments \ - && chown 1001:root /deployments \ - && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ - && chown 1001 /deployments/run-java.sh \ - && chmod 540 /deployments/run-java.sh \ - && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security - -# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. -ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" - -COPY build/lib/* /deployments/lib/ -COPY build/*-runner.jar /deployments/app.jar - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT [ "/deployments/run-java.sh" ] \ No newline at end of file diff --git a/rest/fints4kRest/src/main/docker/Dockerfile.native b/rest/fints4kRest/src/main/docker/Dockerfile.native deleted file mode 100644 index c1522ea4..00000000 --- a/rest/fints4kRest/src/main/docker/Dockerfile.native +++ /dev/null @@ -1,27 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode -# -# Before building the container image run: -# -# mvn package -Pnative -Dquarkus.native.container-build=true -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.native -t codinux/fints4k . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 codinux/fints4k -# -### -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 -WORKDIR /work/ -RUN chown 1001 /work \ - && chmod "g+rwX" /work \ - && chown 1001:root /work -COPY --chown=1001:root build/*-runner /work/application - -EXPOSE 8080 -USER 1001 - -CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/AccessControlResponseFilter.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/AccessControlResponseFilter.kt deleted file mode 100644 index 0a450ffd..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/AccessControlResponseFilter.kt +++ /dev/null @@ -1,26 +0,0 @@ -package net.dankito.banking.fints.rest - -import javax.annotation.Priority -import javax.ws.rs.Priorities -import javax.ws.rs.container.ContainerRequestContext -import javax.ws.rs.container.ContainerResponseContext -import javax.ws.rs.container.ContainerResponseFilter -import javax.ws.rs.core.MultivaluedMap -import javax.ws.rs.ext.Provider - - -@Provider -@Priority(Priorities.HEADER_DECORATOR) -open class AccessControlResponseFilter : ContainerResponseFilter { - - - override fun filter(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) { - val headers: MultivaluedMap = responseContext.headers - - headers.add("Access-Control-Allow-Origin", "*") - headers.add("Access-Control-Allow-Headers", "Authorization, Origin, X-Requested-With, Content-Type") - headers.add("Access-Control-Expose-Headers", "Location, Content-Disposition") - headers.add("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, HEAD, OPTIONS") - } - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/LoggingFilter.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/LoggingFilter.kt deleted file mode 100644 index 7e84f18f..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/LoggingFilter.kt +++ /dev/null @@ -1,58 +0,0 @@ -package net.dankito.banking.fints.rest - -import com.fasterxml.jackson.databind.ObjectMapper -import org.slf4j.LoggerFactory -import javax.inject.Inject -import javax.ws.rs.container.ContainerRequestContext -import javax.ws.rs.container.ContainerResponseContext -import javax.ws.rs.container.ContainerResponseFilter -import javax.ws.rs.core.Response -import javax.ws.rs.ext.Provider - - -@Provider -class LoggingFilter : ContainerResponseFilter { - - companion object { - private val log = LoggerFactory.getLogger(LoggingFilter::class.java) - } - - - @Inject - internal lateinit var mapper: ObjectMapper - - - override fun filter(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) { - if (responseContext.statusInfo.family != Response.Status.Family.SUCCESSFUL) { - log.warn("Request ${geRequestUrl(requestContext)} failed: ${getResponseStatus(responseContext)}" - + System.lineSeparator() + getHeadersAsString(responseContext) - + System.lineSeparator() + getBodyAsString(responseContext)) - } - else if (log.isInfoEnabled) { - log.info("Result of request ${geRequestUrl(requestContext)}: ${getResponseStatus(responseContext)}" - + System.lineSeparator() + getHeadersAsString(responseContext) - + System.lineSeparator() + getBodyAsString(responseContext)) - } - } - - private fun geRequestUrl(requestContext: ContainerRequestContext): String { - return "${requestContext.request.method} ${requestContext.uriInfo.requestUri}" - } - - private fun getResponseStatus(responseContext: ContainerResponseContext): String { - return "${responseContext.status} ${responseContext.statusInfo.reasonPhrase}" - } - - private fun getHeadersAsString(responseContext: ContainerResponseContext): String { - return responseContext.stringHeaders.map { header -> "${header.key}: ${header.value}" }.joinToString("\n", "Headers:\n") - } - - private fun getBodyAsString(responseContext: ContainerResponseContext): String { - if (responseContext.hasEntity()) { - return "Body ${responseContext.entityClass.name}:\n" + mapper.writeValueAsString(responseContext.entity) - } - - return "" - } - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/fints4kResource.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/fints4kResource.kt deleted file mode 100644 index 05bd958e..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/fints4kResource.kt +++ /dev/null @@ -1,72 +0,0 @@ -package net.dankito.banking.fints.rest - -import net.dankito.banking.fints.response.client.AddAccountResponse -import net.dankito.banking.fints.response.client.GetTransactionsResponse -import net.dankito.banking.fints.rest.model.dto.request.AddAccountRequestDto -import net.dankito.banking.fints.rest.mapper.DtoMapper -import net.dankito.banking.fints.rest.model.dto.request.GetAccountsTransactionsRequestDto -import net.dankito.banking.fints.rest.model.dto.request.TanResponseDto -import net.dankito.banking.fints.rest.model.dto.response.AddAccountResponseDto -import net.dankito.banking.fints.rest.model.dto.response.GetAccountsTransactionsResponseDto -import net.dankito.banking.fints.rest.model.dto.response.RestResponse -import net.dankito.banking.fints.rest.service.fints4kService -import net.dankito.banking.fints.rest.service.model.GetAccountsTransactionsResponse -import org.slf4j.LoggerFactory -import javax.inject.Inject -import javax.ws.rs.* -import javax.ws.rs.core.MediaType - - -@Path("/fints/v1") -@Consumes(MediaType.APPLICATION_JSON) -@Produces(MediaType.APPLICATION_JSON) -class fints4kResource { - - @Inject - protected val service = fints4kService() - - protected val mapper = DtoMapper() - - - @POST - @Path("addaccount") - fun addAccount(request: AddAccountRequestDto): RestResponse { - val response = service.getAddAccountResponse(request) - - return mapper.createRestResponse(response) { successResponse -> mapper.map(successResponse) } - } - - - @POST - @Path("transactions") - fun getAccountTransactions(request: GetAccountsTransactionsRequestDto): GetAccountsTransactionsResponseDto { - val response = service.getAccountTransactions(request) - - return mapper.map(response) - } - - - @POST - @Path("tanresponse") - fun tanResponse(dto: TanResponseDto): RestResponse { - val response = service.handleTanResponse(dto) - - // couldn't make it that compiler access ResponseHolder<*> for mapper.createRestResponse(), resulted in very cryptic "{"arity":0}" response -> handle it manually - response.response?.let { successResponse -> - return RestResponse.success(mapSuccessResponse(successResponse)) - } - - // all other cases map here, the responseMapper callback has no function - return mapper.createRestResponse(response) { it!! } - } - - private fun mapSuccessResponse(successResponse: Any): Any { - return when (successResponse) { - is AddAccountResponse -> mapper.map(successResponse) - is GetAccountsTransactionsResponse -> mapper.map(successResponse) - is GetTransactionsResponse -> mapper.mapTransactions(successResponse) - else -> successResponse // add others / new ones here - } - } - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/mapper/DtoMapper.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/mapper/DtoMapper.kt deleted file mode 100644 index 50187a4c..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/mapper/DtoMapper.kt +++ /dev/null @@ -1,166 +0,0 @@ -package net.dankito.banking.fints.rest.mapper - -import net.dankito.banking.fints.model.* -import net.dankito.banking.fints.response.client.AddAccountResponse -import net.dankito.banking.fints.response.client.FinTsClientResponse -import net.dankito.banking.fints.response.client.GetTransactionsResponse -import net.dankito.banking.fints.rest.model.ResponseHolder -import net.dankito.banking.fints.rest.model.dto.response.* -import net.dankito.banking.fints.rest.service.model.GetAccountsTransactionsResponse -import java.math.BigDecimal -import javax.ws.rs.InternalServerErrorException - - -open class DtoMapper { - - fun createRestResponse(responseHolder: ResponseHolder, responseMapper: (DomainType) -> DtoType): RestResponse { - responseHolder.response?.let { response -> - return RestResponse.success(responseMapper(response)) - } - - responseHolder.enterTanRequest?.let { enterTanRequest -> - return RestResponse.requiresTan(enterTanRequest) - } - - return RestResponse.error(responseHolder.error ?: "Unknown error") - } - - - open fun map(response: AddAccountResponse): AddAccountResponseDto { - return AddAccountResponseDto( - response.successful, - mapErrorMessage(response), - map(response.bank), - map(response.retrievedData) - ) - } - - - protected open fun map(bank: BankData): BankResponseDto { - return BankResponseDto( - bank.bankCode, - bank.customerId, - bank.finTs3ServerAddress, - bank.bic, - bank.bankName, - bank.userId, - bank.customerName, - mapTanMethods(bank.tanMethodsAvailableForUser), - if (bank.isTanMethodSelected) map(bank.selectedTanMethod) else null, - bank.tanMedia, - bank.supportedHbciVersions.map { it.name.replace("Hbci_", "HBCI ").replace("FinTs_", "FinTS ").replace('_', '.') } - ) - } - - - open fun map(response: GetAccountsTransactionsResponse?): GetAccountsTransactionsResponseDto { - // TODO: is this still the case? - // TODO: if a TAN is required then accountsTransactions contains null value(s) (but why?) -> application crashes - if (response == null) { - throw InternalServerErrorException("Could not fetch account transactions. Either TAN hasn't been entered or developers made a mistake.") - } - - return GetAccountsTransactionsResponseDto( - // TODO: is this correct removing accounts from result for which no transactions have been retrieved? - response.transactionsPerAccount.filter { it.response?.retrievedData?.isNotEmpty() != false } - .map { createRestResponse(it) { transactionsResponse -> mapTransactions(transactionsResponse) } } - ) - } - - open fun mapTransactions(accountTransactions: GetTransactionsResponse): GetAccountTransactionsResponseDto { - val retrievedData = accountTransactions.retrievedData.first() - val balance = mapNullable(retrievedData.balance) - val bookedTransactions = map(retrievedData.bookedTransactions) - - return GetAccountTransactionsResponseDto( - retrievedData.account.accountIdentifier, - retrievedData.account.productName, - accountTransactions.successful, - mapErrorMessage(accountTransactions), - balance, - bookedTransactions, - listOf() - ) - } - - - protected open fun map(accountData: List): List { - return accountData.map { map(it) } - } - - protected open fun map(accountData: RetrievedAccountData): BankAccountResponseDto { - val account = accountData.account - - return BankAccountResponseDto( - account.accountIdentifier, - account.subAccountAttribute, - account.iban, - account.accountType, - account.currency, - account.accountHolderName, - account.productName, - account.supportsRetrievingBalance, - account.supportsRetrievingAccountTransactions, - account.supportsTransferringMoney, - account.supportsRealTimeTransfer, - accountData.successfullyRetrievedData, - mapNullable(accountData.balance), - accountData.retrievedTransactionsFrom, - accountData.retrievedTransactionsTo, - map(accountData.bookedTransactions), - listOf() - ) - } - - - protected open fun map(transactions: Collection): Collection { - return transactions.map { map(it) } - } - - protected open fun map(transaction: AccountTransaction): AccountTransactionResponseDto { - return AccountTransactionResponseDto( - map(transaction.amount), - transaction.amount.currency.code, - transaction.reference, - transaction.bookingDate, - transaction.otherPartyName, - transaction.otherPartyBankCode, - transaction.otherPartyAccountId, - transaction.bookingText, - transaction.valueDate - ) - } - - - protected open fun mapTanMethods(tanMethods: List): List { - return tanMethods.map { map(it) } - } - - protected open fun map(tanMethod: TanMethod): TanMethodResponseDto { - return TanMethodResponseDto( - tanMethod.displayName, - tanMethod.securityFunction.code, - tanMethod.type, - tanMethod.hhdVersion?.name?.replace("HHD_", "")?.replace('_', '.'), - tanMethod.maxTanInputLength, - tanMethod.allowedTanFormat - ) - } - - - protected open fun map(money: Money): BigDecimal { - return money.bigDecimal - } - - protected open fun mapNullable(money: Money?): BigDecimal? { - return money?.let { map(it) } - } - - - protected open fun mapErrorMessage(response: FinTsClientResponse): String? { - // TODO: evaluate fields like isJobAllowed or tanRequiredButWeWereToldToAbortIfSo and set error message accordingly - return response.errorMessage - ?: if (response.errorsToShowToUser.isNotEmpty()) response.errorsToShowToUser.joinToString("\n") else null - } - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/BankAccessData.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/BankAccessData.kt deleted file mode 100644 index c0506723..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/BankAccessData.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.dankito.banking.fints.rest.model - - -open class BankAccessData( - open val bankCode: String, - open val loginName: String, - open val password: String, - open val finTsServerAddress: String? = null -) { - - internal constructor() : this("", "", "") // for object deserializers - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/EnterTanContext.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/EnterTanContext.kt deleted file mode 100644 index 2fe11498..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/EnterTanContext.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.dankito.banking.fints.rest.model - -import net.dankito.banking.fints.model.EnterTanResult -import java.util.* -import java.util.concurrent.CountDownLatch -import java.util.concurrent.atomic.AtomicReference - - -class EnterTanContext( - val enterTanResult: AtomicReference, - val responseHolder: ResponseHolder<*>, - val countDownLatch: CountDownLatch, - val tanRequestedTimeStamp: Date = Date() -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/EnteringTanRequested.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/EnteringTanRequested.kt deleted file mode 100644 index 7adcfdd2..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/EnteringTanRequested.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.dankito.banking.fints.rest.model - -import net.dankito.banking.fints.model.TanChallenge - - -class EnteringTanRequested( - val tanRequestId: String, - val tanChallenge: TanChallenge -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/ResponseHolder.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/ResponseHolder.kt deleted file mode 100644 index 02264988..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/ResponseHolder.kt +++ /dev/null @@ -1,63 +0,0 @@ -package net.dankito.banking.fints.rest.model - -import java.util.concurrent.CountDownLatch - - -class ResponseHolder() { - - private var responseReceivedLatch = CountDownLatch(1) - - constructor(error: String) : this() { - setError(error) - } - - - var response: T? = null - private set - - var error: String? = null - private set - - var enterTanRequest: EnteringTanRequested? = null - private set - - - fun setResponse(response: T) { - this.response = response - - signalResponseReceived() - } - - fun setError(error: String) { - this.error = error - - signalResponseReceived() - } - - fun setEnterTanRequest(enterTanRequest: EnteringTanRequested) { - this.enterTanRequest = enterTanRequest - - signalResponseReceived() - } - - - fun waitForResponse() { - responseReceivedLatch.await() - } - - fun resetAfterEnteringTan() { - this.enterTanRequest = null - - responseReceivedLatch = CountDownLatch(1) - } - - private fun signalResponseReceived() { - responseReceivedLatch.countDown() - } - - - override fun toString(): String { - return "Error: $error, TAN requested: $enterTanRequest, success: $response" - } - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/AccountRequestDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/AccountRequestDto.kt deleted file mode 100644 index 413695a3..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/AccountRequestDto.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.request - - -open class AccountRequestDto( - open val identifier: String -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/AddAccountRequestDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/AddAccountRequestDto.kt deleted file mode 100644 index 0eeb34d7..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/AddAccountRequestDto.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.request - - -open class AddAccountRequestDto : BankAccessDataRequestDto() \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/BankAccessDataRequestDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/BankAccessDataRequestDto.kt deleted file mode 100644 index 1533e2dc..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/BankAccessDataRequestDto.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.request - -import net.dankito.banking.fints.rest.model.BankAccessData - - -open class BankAccessDataRequestDto : BankAccessData() \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/GetAccountsTransactionsRequestDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/GetAccountsTransactionsRequestDto.kt deleted file mode 100644 index fdad36af..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/GetAccountsTransactionsRequestDto.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.request - -import net.dankito.banking.fints.rest.model.BankAccessData -import net.dankito.utils.multiplatform.Date - - -open class GetAccountsTransactionsRequestDto( - open val credentials: BankAccessData, - open val accounts: List, - open val alsoRetrieveBalance: Boolean = true, - open val fromDate: Date? = null, - open val toDate: Date? = null, - open val abortIfTanIsRequired: Boolean = false -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/TanResponseDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/TanResponseDto.kt deleted file mode 100644 index d41f383a..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/request/TanResponseDto.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.request - -import net.dankito.banking.fints.model.EnterTanResult - - -class TanResponseDto( - val tanRequestId: String, - val enterTanResult: EnterTanResult -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/AccountTransactionResponseDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/AccountTransactionResponseDto.kt deleted file mode 100644 index 867b923b..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/AccountTransactionResponseDto.kt +++ /dev/null @@ -1,17 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - -import net.dankito.utils.multiplatform.Date -import java.math.BigDecimal - - -open class AccountTransactionResponseDto( - open val amount: BigDecimal, - open val currency: String, - open val reference: String, - open val bookingDate: Date, - open val otherPartyName: String?, - open val otherPartyBankCode: String?, - open val otherPartyAccountId: String?, - open val bookingText: String?, - open val valueDate: Date -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/AddAccountResponseDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/AddAccountResponseDto.kt deleted file mode 100644 index fab0a71c..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/AddAccountResponseDto.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - - -open class AddAccountResponseDto( - successful: Boolean, - errorMessage: String?, - open val bank: BankResponseDto, - open val accounts: List -) : ResponseDtoBase(successful, errorMessage) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/BankAccountResponseDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/BankAccountResponseDto.kt deleted file mode 100644 index d49b216e..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/BankAccountResponseDto.kt +++ /dev/null @@ -1,26 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - -import net.dankito.banking.fints.response.segments.AccountType -import net.dankito.utils.multiplatform.Date -import java.math.BigDecimal - - -open class BankAccountResponseDto( - open val accountIdentifier: String, - open val subAccountAttribute: String?, - open val iban: String?, - open val accountType: AccountType?, - open val currency: String?, - open val accountHolderName: String, - open val productName: String?, - open val supportsRetrievingBalance: Boolean, - open val supportsRetrievingAccountTransactions: Boolean, - open val supportsTransferringMoney: Boolean, - open val supportsInstantPaymentMoneyTransfer: Boolean, - open val successfullyRetrievedData: Boolean, - open val balance: BigDecimal?, - open val retrievedTransactionsFrom: Date?, - open val retrievedTransactionsTo: Date?, - open var bookedTransactions: Collection, - open var unbookedTransactions: Collection -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/BankResponseDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/BankResponseDto.kt deleted file mode 100644 index 2d1b5492..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/BankResponseDto.kt +++ /dev/null @@ -1,22 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.TanMedium - - -open class BankResponseDto( - open val bankCode: String, - open val userName: String, - open val finTs3ServerAddress: String, - open val bic: String, - - open val bankName: String, - - open val userId: String, - open val customerName: String, - - open val usersTanMethods: List, - open val selectedTanMethod: TanMethodResponseDto?, - open val tanMedia: List, - - open val supportedHbciVersions: List -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/GetAccountTransactionsResponseDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/GetAccountTransactionsResponseDto.kt deleted file mode 100644 index fa4005d9..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/GetAccountTransactionsResponseDto.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - -import java.math.BigDecimal - - -open class GetAccountTransactionsResponseDto( - open val identifier: String, - open val productName: String?, - successful: Boolean, - errorMessage: String?, - open val balance: BigDecimal?, - open var bookedTransactions: Collection, - open var unbookedTransactions: Collection -) : ResponseDtoBase(successful, errorMessage) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/GetAccountsTransactionsResponseDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/GetAccountsTransactionsResponseDto.kt deleted file mode 100644 index dbda2749..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/GetAccountsTransactionsResponseDto.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - - -open class GetAccountsTransactionsResponseDto( - open val transactionsPerAccount: List> -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/ResponseDtoBase.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/ResponseDtoBase.kt deleted file mode 100644 index e0747d1a..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/ResponseDtoBase.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - - -open class ResponseDtoBase( - open val successful: Boolean, - open val errorMessage: String? -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/ResponseType.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/ResponseType.kt deleted file mode 100644 index bed09865..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/ResponseType.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - - -enum class ResponseType { - - Success, - - Error, - - TanRequired - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/RestResponse.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/RestResponse.kt deleted file mode 100644 index 291b5b5c..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/RestResponse.kt +++ /dev/null @@ -1,29 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - -import net.dankito.banking.fints.rest.model.EnteringTanRequested - - -class RestResponse( - val status: ResponseType, - val errorMessage: String?, - val successResponse: T?, - val enteringTanRequested: EnteringTanRequested? = null -) { - - companion object { - - fun success(result: T): RestResponse { - return RestResponse(ResponseType.Success, null, result, null) - } - - fun error(errorMessage: String): RestResponse { - return RestResponse(ResponseType.Error, errorMessage, null, null) - } - - fun requiresTan(enteringTanRequested: EnteringTanRequested): RestResponse { - return RestResponse(ResponseType.TanRequired, null, null, enteringTanRequested) - } - - } - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/TanMethodResponseDto.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/TanMethodResponseDto.kt deleted file mode 100644 index c08f110b..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/model/dto/response/TanMethodResponseDto.kt +++ /dev/null @@ -1,15 +0,0 @@ -package net.dankito.banking.fints.rest.model.dto.response - -import net.dankito.banking.fints.messages.datenelemente.implementierte.tan.AllowedTanFormat -import net.dankito.banking.fints.model.TanMethodType - - -open class TanMethodResponseDto( - open val displayName: String, - open val bankInternalMethodCode: String, - open val type: TanMethodType, - open val hhdVersion: String? = null, - open val maxTanInputLength: Int? = null, - open val allowedTanFormat: AllowedTanFormat? = null, - open val nameOfTanMediumRequired: Boolean = false -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/service/fints4kService.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/service/fints4kService.kt deleted file mode 100644 index db759449..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/service/fints4kService.kt +++ /dev/null @@ -1,202 +0,0 @@ -package net.dankito.banking.fints.rest.service - -import net.dankito.banking.bankfinder.InMemoryBankFinder -import net.dankito.banking.fints.FinTsClientForCustomer -import net.dankito.banking.fints.callback.FinTsClientCallback -import net.dankito.banking.fints.callback.SimpleFinTsClientCallback -import net.dankito.banking.fints.model.* -import net.dankito.banking.fints.response.client.AddAccountResponse -import net.dankito.banking.fints.response.client.GetTransactionsResponse -import net.dankito.banking.fints.rest.model.BankAccessData -import net.dankito.banking.fints.rest.model.EnterTanContext -import net.dankito.banking.fints.rest.model.EnteringTanRequested -import net.dankito.banking.fints.rest.model.ResponseHolder -import net.dankito.banking.fints.rest.model.dto.request.GetAccountsTransactionsRequestDto -import net.dankito.banking.fints.rest.model.dto.request.TanResponseDto -import net.dankito.banking.fints.rest.service.model.GetAccountsTransactionsResponse -import java.util.* -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.CountDownLatch -import java.util.concurrent.atomic.AtomicReference -import javax.enterprise.context.ApplicationScoped - - -@ApplicationScoped -class fints4kService { - - protected val bankFinder = InMemoryBankFinder() - - protected val clientCache = ConcurrentHashMap() - - // TODO: create clean up job for timed out TAN requests - protected val tanRequests = ConcurrentHashMap() - - - fun getAddAccountResponse(accessData: BankAccessData): ResponseHolder { - val (bank, errorMessage) = mapToBankData(accessData) - - if (errorMessage != null) { - return ResponseHolder(errorMessage) - } - - return getAccountData(bank) - } - - protected fun getAccountData(bank: BankData): ResponseHolder { - return getAsyncResponse(bank) { client, responseRetrieved -> - client.addAccountAsync(AddAccountParameter(bank)) { response -> - responseRetrieved(response) - } - } - } - - - fun getAccountTransactions(dto: GetAccountsTransactionsRequestDto): GetAccountsTransactionsResponse { - val (bank, errorMessage) = mapToBankData(dto.credentials) - - if (errorMessage != null) { - return GetAccountsTransactionsResponse(listOf(ResponseHolder(errorMessage))) - } - - val retrievedAccounts = getAccounts(bank) - - val transactionsPerAccount = dto.accounts.map { accountDto -> - val account = retrievedAccounts?.firstOrNull { it.accountIdentifier == accountDto.identifier } - - return@map if (account != null) { - val parameter = GetTransactionsParameter(account, dto.alsoRetrieveBalance, dto.fromDate, dto.toDate, abortIfTanIsRequired = dto.abortIfTanIsRequired) - getAccountTransactions(bank, parameter) - } - else { - ResponseHolder("Account with identifier '${accountDto.identifier}' not found. Available accounts: " + - "${retrievedAccounts?.joinToString(", ") { it.accountIdentifier }}") - } - } - - return GetAccountsTransactionsResponse(transactionsPerAccount) - } - - fun getAccountTransactions(bank: BankData, parameter: GetTransactionsParameter): ResponseHolder { - return getAsyncResponse(bank) { client, responseRetrieved -> - client.getTransactionsAsync(parameter) { response -> - responseRetrieved(response) - } - } - } - - - fun handleTanResponse(dto: TanResponseDto): ResponseHolder<*> { - tanRequests.remove(dto.tanRequestId)?.let { enterTanContext -> - val responseHolder = enterTanContext.responseHolder - responseHolder.resetAfterEnteringTan() - - enterTanContext.enterTanResult.set(dto.enterTanResult) - enterTanContext.countDownLatch.countDown() - - responseHolder.waitForResponse() - - return responseHolder - } - - return ResponseHolder("No TAN request found for TAN Request ID '${dto.tanRequestId}'") - } - - - protected fun getAsyncResponse(bank: BankData, executeRequest: (FinTsClientForCustomer, ((T) -> Unit)) -> Unit): ResponseHolder { - val responseHolder = ResponseHolder() - - val client = getClient(bank, responseHolder) - - executeRequest(client) { response -> - responseHolder.setResponse(response) - } - - responseHolder.waitForResponse() - - return responseHolder - } - - private fun getClient(bank: BankData, responseHolder: ResponseHolder): FinTsClientForCustomer { - val cacheKey = getCacheKey(bank.bankCode, bank.customerId) - - clientCache[cacheKey]?.let { - // TODO: this will not work for two parallel calls for the same account if both calls require entering a TAN as second one overwrites callback and ResponseHolder of first one -> first one blocks forever - it.setCallback(createFinTsClientCallback(responseHolder)) // we have to newly create callback otherwise ResponseHolder instance of when client was created is used -> its CountDownLatch would never signal - return it - } - - val client = FinTsClientForCustomer(bank, createFinTsClientCallback(responseHolder)) - - clientCache[cacheKey] = client - - return client - } - - private fun createFinTsClientCallback(responseHolder: ResponseHolder): FinTsClientCallback { - return SimpleFinTsClientCallback({ bank, tanChallenge -> handleEnterTan(bank, tanChallenge, responseHolder) }) { supportedTanMethods, suggestedTanMethod -> - suggestedTanMethod - } - } - - protected fun handleEnterTan(bank: BankData, tanChallenge: TanChallenge, responseHolder: ResponseHolder): EnterTanResult { - val enterTanResult = AtomicReference() - val enterTanLatch = CountDownLatch(1) - - val tanRequestId = UUID.randomUUID().toString() - - tanRequests.put(tanRequestId, EnterTanContext(enterTanResult, responseHolder, enterTanLatch)) - - responseHolder.setEnterTanRequest(EnteringTanRequested(tanRequestId, tanChallenge)) - - enterTanLatch.await() - - return enterTanResult.get() - } - - - protected fun mapToBankData(accessData: BankAccessData): Pair { - val bankSearchResult = bankFinder.findBankByBankCode(accessData.bankCode) - val fintsServerAddress = accessData.finTsServerAddress ?: bankSearchResult.firstOrNull { it.pinTanAddress != null }?.pinTanAddress - val potentialBankInfo = bankSearchResult.firstOrNull() - - val bank = BankData(accessData.bankCode, accessData.loginName, accessData.password, fintsServerAddress ?: "", - potentialBankInfo?.bic ?: "", potentialBankInfo?.name ?: "") - - if (fintsServerAddress == null) { - val errorMessage = if (bankSearchResult.isEmpty()) "No bank found for bank code '${accessData.bankCode}'" else "Bank '${bankSearchResult.firstOrNull()?.name} does not support FinTS 3.0" - - return Pair(bank, errorMessage) - } - - return Pair(bank, null) - } - - - protected fun getAccounts(bank: BankData): List? { - getCachedClient(bank)?.bank?.accounts?.let { - return it - } - - val addAccountResponse = getAccountData(bank) - - return addAccountResponse.response?.bank?.accounts - } - - - private fun getCachedClient(bank: BankData): FinTsClientForCustomer? { - val cacheKey = getCacheKey(bank.bankCode, bank.customerId) - - return clientCache[cacheKey] - } - - private fun getCachedClient(credentials: BankAccessData): FinTsClientForCustomer? { - val cacheKey = getCacheKey(credentials.bankCode, credentials.loginName) - - return clientCache[cacheKey] - } - - private fun getCacheKey(bankCode: String, loginName: String): String { - return bankCode + "_" + loginName - } - -} \ No newline at end of file diff --git a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/service/model/GetAccountsTransactionsResponse.kt b/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/service/model/GetAccountsTransactionsResponse.kt deleted file mode 100644 index c686e3e1..00000000 --- a/rest/fints4kRest/src/main/kotlin/net/dankito/banking/fints/rest/service/model/GetAccountsTransactionsResponse.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.dankito.banking.fints.rest.service.model - -import net.dankito.banking.fints.response.client.GetTransactionsResponse -import net.dankito.banking.fints.rest.model.ResponseHolder - - -class GetAccountsTransactionsResponse( - val transactionsPerAccount: List> -) \ No newline at end of file diff --git a/rest/fints4kRest/src/main/resources/application.properties b/rest/fints4kRest/src/main/resources/application.properties deleted file mode 100644 index 0793aed7..00000000 --- a/rest/fints4kRest/src/main/resources/application.properties +++ /dev/null @@ -1,11 +0,0 @@ -quarkus.http.port=5555 - -# enable https support in native builds -quarkus.native.enable-https-url-handler=true -quarkus.native.enable-all-security-services=true - -quarkus.log.level=WARN -# FinTS messages are logged on DEBUG -quarkus.log.category."net.dankito.banking.fints.log.MessageLogCollector".level=INFO -# REST responses are logged on INFO -quarkus.log.category."net.dankito.banking.fints.rest.LoggingFilter".level=WARN \ No newline at end of file diff --git a/rest/fints4kRest/src/main/resources/logback.xml b/rest/fints4kRest/src/main/resources/logback.xml deleted file mode 100755 index 828c47b6..00000000 --- a/rest/fints4kRest/src/main/resources/logback.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - DEBUG - - - - - - - - - data/logs/fints4kRest-${bySecond}.log - - - %-4relative [%thread] %-5level %logger{35} - %msg%n - - - - DEBUG - - - - - - - - \ No newline at end of file diff --git a/rest/fints4kRest/src/native-test/kotlin/net/dankito/banking/fints/rest/NativeFints4kIT.kt b/rest/fints4kRest/src/native-test/kotlin/net/dankito/banking/fints/rest/NativeFints4kIT.kt deleted file mode 100644 index 8f497ac9..00000000 --- a/rest/fints4kRest/src/native-test/kotlin/net/dankito/banking/fints/rest/NativeFints4kIT.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.dankito.banking.fints.rest - -import io.quarkus.test.junit.NativeImageTest - -@NativeImageTest -class NativeFints4kIT : ExampleResourceTest() \ No newline at end of file diff --git a/rest/fints4kRest/src/test/kotlin/net/dankito/banking/fints/rest/fints4kResourceTest.kt b/rest/fints4kRest/src/test/kotlin/net/dankito/banking/fints/rest/fints4kResourceTest.kt deleted file mode 100644 index 338e8f8a..00000000 --- a/rest/fints4kRest/src/test/kotlin/net/dankito/banking/fints/rest/fints4kResourceTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package net.dankito.banking.fints.rest - -import io.quarkus.test.junit.QuarkusTest -import io.restassured.RestAssured.given -import org.hamcrest.CoreMatchers.`is` -import org.junit.jupiter.api.Test - -@QuarkusTest -class fints4kResourceTest { - - @Test - fun testHelloEndpoint() { - given() - .`when`().get("/hello") - .then() - .statusCode(200) - .body(`is`("hello")) - } - -} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 540066df..1f0c14cc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,82 +1,13 @@ pluginManagement { repositories { - mavenLocal() mavenCentral() gradlePluginPortal() } - plugins { - id 'io.quarkus' version "$quarkusVersion" - } } rootProject.name = 'fints4kProject' -enableFeaturePreview('GRADLE_METADATA') - include ':fints4k' -include ':fints4k-jvm' include ':common' - - -/* UI */ - -include ':BankingUiCommon' - -include ':fints4kBankingClient' -include ':hbci4jBankingClient' - -include ':BankingPersistenceJson' -include ':LuceneBankingPersistence' -include ':RoomBankingPersistence' - -include ':BankingAndroidApp' - -include ':BankingJavaFxControls' -include ':BankingJavaFxApp' - -include ':BankingUiNativeIntegration' - - -project(':BankingUiCommon').projectDir = "$rootDir/ui/BankingUiCommon/" as File - -project(':fints4kBankingClient').projectDir = "$rootDir/ui/fints4kBankingClient/" as File -project(':hbci4jBankingClient').projectDir = "$rootDir/ui/hbci4jBankingClient/" as File - -project(':BankingAndroidApp').projectDir = "$rootDir/ui/BankingAndroidApp/" as File - -project(':BankingJavaFxControls').projectDir = "$rootDir/ui/BankingJavaFxControls/" as File -project(':BankingJavaFxApp').projectDir = "$rootDir/ui/BankingJavaFxApp/" as File - -project(':BankingUiNativeIntegration').projectDir = "$rootDir/ui/BankingUiNativeIntegration/" as File - -project(':BankingPersistenceJson').projectDir = "$rootDir/persistence/json/BankingPersistenceJson/" as File -project(':LuceneBankingPersistence').projectDir = "$rootDir/persistence/LuceneBankingPersistence/" as File -project(':RoomBankingPersistence').projectDir = "$rootDir/persistence/database/RoomBankingPersistence/" as File - - -/* REST APIs */ - -include ':BankFinderRest' -include ':fints4kRest' - -project(':BankFinderRest').projectDir = "$rootDir/rest/BankFinderRest/" as File -project(':fints4kRest').projectDir = "$rootDir/rest/fints4kRest/" as File - - - -/* Tools */ - -include ':BankFinder' -include ':LuceneBankFinder' -include ':BankListCreator' -include ':CsvAccountTransactionsImporterAndExporter' -include ':EpcQrCodeParser' - - -project(':BankFinder').projectDir = "$rootDir/tools/BankFinder/" as File -project(':LuceneBankFinder').projectDir = "$rootDir/tools/LuceneBankFinder/" as File -project(':BankListCreator').projectDir = "$rootDir/tools/BankListCreator/" as File -project(':CsvAccountTransactionsImporterAndExporter').projectDir = "$rootDir/tools/CsvAccountTransactionsImporterAndExporter/" as File -project(':EpcQrCodeParser').projectDir = "$rootDir/tools/EpcQrCodeParser/" as File diff --git a/tools/BankFinder/build.gradle b/tools/BankFinder/build.gradle index 1dcdba63..1795e4dd 100644 --- a/tools/BankFinder/build.gradle +++ b/tools/BankFinder/build.gradle @@ -1,6 +1,5 @@ plugins { id "org.jetbrains.kotlin.multiplatform" - id "com.android.library" id "maven-publish" } @@ -10,31 +9,43 @@ ext.artifactName = "bank-finder" kotlin { jvm { - compilations.main.kotlinOptions { - jvmTarget = "1.6" + compilations.all { + kotlinOptions.jvmTarget = '1.8' + } + withJava() + testRuns["test"].executionTask.configure { + useJUnitPlatform() } } - targets { - final def iOSTarget = iOSIsRealDevice ? presets.iosArm64 : presets.iosX64 +// js(BOTH) { +// browser { +// commonWebpackConfig { +// cssSupport.enabled = true +// } +// } +// } - fromPreset(iOSTarget, 'ios') { - binaries { - framework { - baseName = "BankFinder" - - embedBitcode(embedBitcodeValue) - } + ios { + binaries { + framework { + baseName = "BankFinder" } } } +// def hostOs = System.getProperty("os.name") +// def isMingwX64 = hostOs.startsWith("Windows") +// def nativeTarget +// if (hostOs == "Mac OS X") nativeTarget = macosX64('native') { binaries.executable() } +// else if (hostOs == "Linux") nativeTarget = linuxX64("native") { binaries.executable() } +// else if (isMingwX64) nativeTarget = mingwX64("native") { binaries.executable() } +// else throw new GradleException("Host OS is not supported in Kotlin/Native.") + sourceSets { commonMain { dependencies { - api kotlin("stdlib-common") - api project(":common") } } @@ -55,10 +66,7 @@ kotlin { jvmTest { dependencies { - implementation kotlin("test-junit") - implementation "org.junit.jupiter:junit-jupiter:$junit5Version" - runtimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" } } @@ -66,97 +74,14 @@ kotlin { iosMain { dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion" + } } iosTest { dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation "org.jetbrains.kotlin:kotlin-test" + } } } -} - - -// Task to generate iOS framework for xcode projects. -task packForXcode(type: Sync) { - - final File frameworkDir = new File(buildDir, "xcode-frameworks") - final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG' - - final def framework = kotlin.targets.ios.binaries.getFramework("", mode) - - inputs.property "mode", mode - dependsOn framework.linkTask - - from { framework.outputFile.parentFile } - into frameworkDir - - doLast { - new File(frameworkDir, 'gradlew').with { - text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n" - setExecutable(true) - } - } -} - -// Run packForXcode when building. -tasks.build.dependsOn packForXcode - - -android { - compileSdkVersion androidCompileSdkVersion - - - defaultConfig { - minSdkVersion androidMinSdkVersion - targetSdkVersion androidTargetSdkVersion - - versionName version - versionCode appVersionCode - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - packagingOptions { - pickFirst 'META-INF/ktor-http.kotlin_module' - pickFirst 'META-INF/kotlinx-io.kotlin_module' - pickFirst 'META-INF/atomicfu.kotlin_module' - pickFirst 'META-INF/ktor-utils.kotlin_module' - pickFirst 'META-INF/kotlinx-coroutines-io.kotlin_module' - pickFirst 'META-INF/ktor-client-core.kotlin_module' - pickFirst 'META-INF/DEPENDENCIES' - pickFirst 'META-INF/NOTICE' - pickFirst 'META-INF/LICENSE' - pickFirst 'META-INF/LICENSE.txt' - pickFirst 'META-INF/NOTICE.txt' - } - - lintOptions { - abortOnError false - } - -} - - -//task jarTest (type: Jar) { -// from sourceSets.jvmTest.output -// classifier = 'test' -//} -// -//configurations { -// testOutput -//} -// -//artifacts { -// testOutput jarTest -//} \ No newline at end of file +} \ No newline at end of file diff --git a/tools/EpcQrCodeParser/build.gradle b/tools/EpcQrCodeParser/build.gradle index c9b48918..25899cfb 100644 --- a/tools/EpcQrCodeParser/build.gradle +++ b/tools/EpcQrCodeParser/build.gradle @@ -1,55 +1,52 @@ plugins { id 'org.jetbrains.kotlin.multiplatform' -// id 'java-library' - id "com.android.library" // TODO: get rid off, use java-library instead id "maven-publish" } ext.artifactName = "epc-qr-code-parser" -def frameworkName = "EpcQrCodeParser" - kotlin { + jvm { + compilations.all { + kotlinOptions.jvmTarget = '1.8' + } + withJava() + testRuns["test"].executionTask.configure { + useJUnitPlatform() + } + } - targets { - final def iOSTarget = iOSIsRealDevice ? presets.iosArm64 : presets.iosX64 +// js(BOTH) { +// browser { +// commonWebpackConfig { +// cssSupport.enabled = true +// } +// } +// } - fromPreset(iOSTarget, 'ios') { - binaries { - framework { - baseName = frameworkName - - embedBitcode(embedBitcodeValue) - } + ios { + binaries { + framework { + baseName = "EpcQrCodeParser" } } } - jvm() +// def hostOs = System.getProperty("os.name") +// def isMingwX64 = hostOs.startsWith("Windows") +// def nativeTarget +// if (hostOs == "Mac OS X") nativeTarget = macosX64('native') { binaries.executable() } +// else if (hostOs == "Linux") nativeTarget = linuxX64("native") { binaries.executable() } +// else if (isMingwX64) nativeTarget = mingwX64("native") { binaries.executable() } +// else throw new GradleException("Host OS is not supported in Kotlin/Native.") - js { - - nodejs { - testTask { - enabled = false - } - } - - browser { - testTask { - enabled = false - } - - } - - } sourceSets { commonMain { dependencies { - implementation kotlin('stdlib-common') + } } commonTest { @@ -61,25 +58,24 @@ kotlin { jvmMain { dependencies { - implementation kotlin('stdlib-jdk8') + } } jvmTest { dependencies { - implementation kotlin('test') - implementation kotlin('test-junit') + } } jsMain { dependencies { - implementation kotlin('stdlib-js') + } } jsTest { dependencies { - implementation kotlin('test-js') + } } @@ -89,73 +85,4 @@ kotlin { } } -} - - -// Task to generate iOS framework for xcode projects. -task packForXcode(type: Sync) { - - final File frameworkDir = new File(buildDir, "xcode-frameworks") - final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG' - - final def framework = kotlin.targets.ios.binaries.getFramework("", mode) - - inputs.property "mode", mode - dependsOn framework.linkTask - - from { framework.outputFile.parentFile } - into frameworkDir - - doLast { - new File(frameworkDir, 'gradlew').with { - text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n" - setExecutable(true) - } - } -} - -// Run packForXcode when building. -tasks.build.dependsOn packForXcode - - -// TODO: get rid of this -android { - compileSdkVersion androidCompileSdkVersion - - - defaultConfig { - minSdkVersion androidMinSdkVersion - targetSdkVersion androidTargetSdkVersion - - versionName version - versionCode appVersionCode - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - packagingOptions { - pickFirst 'META-INF/ktor-http.kotlin_module' - pickFirst 'META-INF/kotlinx-io.kotlin_module' - pickFirst 'META-INF/atomicfu.kotlin_module' - pickFirst 'META-INF/ktor-utils.kotlin_module' - pickFirst 'META-INF/kotlinx-coroutines-io.kotlin_module' - pickFirst 'META-INF/ktor-client-core.kotlin_module' - pickFirst 'META-INF/DEPENDENCIES' - pickFirst 'META-INF/NOTICE' - pickFirst 'META-INF/LICENSE' - pickFirst 'META-INF/LICENSE.txt' - pickFirst 'META-INF/NOTICE.txt' - } - - lintOptions { - abortOnError false - } - } \ No newline at end of file diff --git a/ui/BankingAndroidApp/build.gradle b/ui/BankingAndroidApp/build.gradle deleted file mode 100644 index 73771dde..00000000 --- a/ui/BankingAndroidApp/build.gradle +++ /dev/null @@ -1,184 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'kotlin-kapt' - - -repositories { - // for security issues fixed version of iText 2 from JasperReports - maven { - url "https://jaspersoft.jfrog.io/jaspersoft/third-party-ce-artifacts" - } -} - - -android { - compileSdkVersion androidCompileSdkVersion - buildToolsVersion androidBuildToolsVersion - - - defaultConfig { - applicationId "net.codinux.banking.android" - - minSdkVersion androidMinSdkVersion - targetSdkVersion androidTargetSdkVersion - - versionName version.replace("-", " ") - versionCode appVersionCode - - multiDexEnabled true - - // enable using vector drawables on pre Lollipop devices - vectorDrawables.useSupportLibrary = true - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - kotlinOptions { - jvmTarget = '1.8' - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - buildTypes { - debug { - applicationIdSuffix = ".develop" - } - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - signingConfigs { - debug { - // so that all machines have the same signing key, no matter if app is installed from developer's machine or from Jenkins - storeFile file('debug-keystore.jks') - storePassword 'find_my_bugs_before_releasing_me' - keyAlias 'DebugKey' - keyPassword 'find_my_bugs_before_releasing_me' - } - } - - packagingOptions { - pickFirst 'META-INF/kotlinx-coroutines-io.kotlin_module' - pickFirst 'META-INF/kotlinx-io.kotlin_module' - pickFirst 'META-INF/kotlinx-serialization-runtime.kotlin_module' - pickFirst 'META-INF/ktor-utils.kotlin_module' - pickFirst 'META-INF/ktor-client-core.kotlin_module' - pickFirst 'META-INF/ktor-http.kotlin_module' - pickFirst 'META-INF/ktor-io.kotlin_module' - pickFirst 'META-INF/ktor-http-cio.kotlin_module' - pickFirst 'META-INF/atomicfu.kotlin_module' - - pickFirst 'META-INF/common.kotlin_module' - pickFirst 'META-INF/fints4k.kotlin_module' - pickFirst 'META-INF/BankFinder.kotlin_module' - pickFirst 'META-INF/BankFinder.kotlin_module' - - pickFirst 'META-INF/DEPENDENCIES' - pickFirst 'META-INF/NOTICE' - pickFirst 'META-INF/LICENSE' - pickFirst 'META-INF/LICENSE.txt' - pickFirst 'META-INF/NOTICE.txt' - - pickFirst 'BankList.json' - exclude 'DetailedBankList.json' - } - - lintOptions { - abortOnError false - } - -} - -dependencies { - implementation project(":fints4k") - - implementation project(':BankingUiCommon') - - implementation project(':fints4kBankingClient') - - implementation project(':LuceneBankFinder') - - implementation project(':BankingPersistenceJson') - implementation project(':LuceneBankingPersistence') - implementation project(':RoomBankingPersistence') - - implementation project(':CsvAccountTransactionsImporterAndExporter') - - - implementation "net.dankito.text.extraction:itext2-text-extractor:$textExtractorVersion" - implementation "net.dankito.text.extraction:pdfbox-android-text-extractor:$textExtractorVersion" + "a" // TODO: version 0.6.0a become only necessary due to a misconfigured Maven upload task. Remove 'a' again on next version - - implementation "com.github.clans:fab:$clansFloatingActionButtonVersion" - implementation 'info.hoang8f:android-segmented:1.0.6' - - implementation "com.otaliastudios:autocomplete:$autocompleteVersion" - - implementation("com.journeyapps:zxing-android-embedded:4.1.0") { transitive = false } // transitive to use older ZXing version as ZXing 3.4.0 requires Android > 23 - implementation "com.google.zxing:core:$zxingVersion" - - implementation "com.yakivmospan:scytale:$scytaleVersion" - - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion" - - implementation "net.dankito.filechooserdialog:filechooserdialog-android:$fileChooserDialogVersion", { - exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib' - exclude group: 'com.android.support', module: 'appcompat-v7' - exclude group: 'com.android.support', module: 'design' - exclude group: 'com.android.support.constraint', module: 'constraint-layout' - exclude module: 'recyclerview-v7' - } - - implementation "net.dankito.utils:android-utils:$androidUtilsVersion", { - exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7' - exclude group: 'com.android.support', module: 'appcompat-v7' - exclude group: 'com.android.support', module: 'design' - } - - // Android 4 support has been dropped with version 3.13.0 - implementation('com.squareup.okhttp3:okhttp') { - version { strictly '3.12.12' } - } - - implementation "org.slf4j:slf4j-android:$slf4jVersion" - - - implementation "androidx.multidex:multidex:$multiDexVersion" - - implementation "androidx.appcompat:appcompat:$appCompatVersion" - implementation "androidx.recyclerview:recyclerview:$appCompatVersion" - implementation "androidx.annotation:annotation:$appCompatVersion" - implementation "com.google.android.material:material:$materialComponentsVersion" - implementation "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion" - - implementation "androidx.biometric:biometric:$androidXBiometricVersion" - implementation "at.favre.lib:bcrypt:$bcryptVersion" - - implementation "com.mikepenz:fastadapter:$fastAdapterVersion" - implementation "com.mikepenz:fastadapter-extensions-binding:$fastAdapterVersion" - implementation "com.mikepenz:fastadapter-extensions-drag:$fastAdapterVersion" - implementation "com.mikepenz:fastadapter-extensions-swipe:$fastAdapterVersion" - implementation "com.mikepenz:fastadapter-extensions-utils:$fastAdapterVersion" - - // for MaterialDrawer - implementation "com.mikepenz:materialdrawer:$materialDrawerVersion" - implementation "com.mikepenz:materialdrawer-nav:$materialDrawerVersion" - - implementation "com.mikepenz:materialdrawer-iconics:$materialDrawerVersion" - - - kapt "com.google.dagger:dagger-compiler:$daggerVersion" - implementation "com.google.dagger:dagger:$daggerVersion" - - - implementation "androidx.navigation:navigation-fragment:$androidXNavigationVersion" - implementation "androidx.navigation:navigation-ui:$androidXNavigationVersion" - implementation "androidx.navigation:navigation-fragment-ktx:$androidXNavigationVersion" - implementation "androidx.navigation:navigation-ui-ktx:$androidXNavigationVersion" -} diff --git a/ui/BankingAndroidApp/debug-keystore.jks b/ui/BankingAndroidApp/debug-keystore.jks deleted file mode 100644 index 0809a56ddf34eca6cb6ee392ecd3d8b987cdfb61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2251 zcmchYXE+;*8ppGwW~>^mS+iynTa8kxM$v>SjT*75f*dJor)KpS$5x7JP^w02RYcIC zW+_Ebd#jiy$0%3NbMJl5^W5+E!~eto_vwB9@B94U;~&RA0002!RKUN*=<0^Sdw9DA zpMtv>cufWXzyO95ASZAblvxf6gaBnhoIoH0078JQ1?JdQyq2+VE|+YK>B^p_ClwzX z%ZG8RM0SpecfSUiPwV;CZ7d}e6t|(m*@JsN%75oliPG@E*(|@B>6Jc7m>THrc$ewg zcsHx$g4OzE)JX)0uuf;y*>zDCF+osZ#qiVG2DZAdl}Fzw+m(EuY4XIXkUIqxq}F})Vr z2mK}Xoe5+)-@(h{0ZR`MnW1Vo#bOhry`xwv@tM6H>SBJCIbj&@OwHvs{T+AR4y;06 zvu@SE+;@4XYvYAxEwS7zwTZT>9sL8J^+tYbq!CCcN66ru zthv(gj$wBE`Uzn^pnfA~UZqDHAStd_~lrkzJwoDS!h>eC(f{Cu}# zi0qHKcfXp{X0s1w-Z@BFb1BF7gy1V^^^bbA8XW{b=)KXgR~v;=V!1W6W_}B=te43n z0Z9fY;ZK%FAR<+Za+;^NfqjSqI3B$G73>44T^PWLi}2-1L6XHbe(Zu-nvp^sq?7JQWp))G3J z+ak!ZaJ{zcRgzcx8hTjwh6_K3ZN~Itl)MP$Qha&Bk;<5$jrkdghInJHVEkavh6yZ! zr#_GadX1c}9LqC5Smg9}Ro!4aCeKk{2A^{Ey$`*`-fignS7ok*=vEKJJKn9SWN9$s>ax;x>^(ou9ln%`&@dYD? zB$b}F(jSYRj{*oi7E7LF0ARI6OYIB8Xz?|ba(Ap`Bq&!V(EyY*Acv)Y3RWt5$sT9? zLxl3EDXTg)yi&AXpLf@q2Nhj>Ui0FgoXx4iUCXJAO@3n7*#&JxFH3GT?epP4lFisi zE$>4!*!IQ~zCN!JGo%6g<~uLRl>C-)F9Ej!bf|~&;t=ti%LIK1<$|J=rwUz=QV>Zl z9(y}D>w4>425<9_?Rgv(^r*JOQFDrM=f!?+vl81QT^4V6?NG1vnNd4q z@koj%12tWLT`!RA>0=6AcX<5s`eL)(C*{-tajIZ9*O?9Go9t0el64CNtBR+{w5rA5 z@x|}pb$4cVB+GY+yf1^U=`&dG<~hi0=>FwYcVDVLeuFlRrOu669uVc7NZ&bJZYLsH zSB2Av2*rcwE-xH1^{q7&6eyyJY1CA9Cq%q?uW@k8lB!Qpk6b38WBx8j23ti{xF!Gq zj(`)uA#ei7r4S4Pf?3CG)THYk&9tZ^)z4G3gm0Kl;b7B~|Wd6NyCbLcp36Tl)~Z>V7$z}~AqDDq@#zZ# zX4(ZBsCU&)1FgLz&M`g3iu}%}!f6x>`FV8-BFlDFM!e|P%%5cOp3%)(bm;vfvSUayUtc)2>1EuBZ3rAEiYvmQgeT$(69I{eJhfXpZ+& zrVl8JZ-Q4x4Mhe^Rx2eL38OIQ;9Zt$M{hdLaqrcc+duogQSyt#%#~xxW%FZmO%NCe z02W_>i@=3Ww=D#N@IubU(X5!Pj8|=ajXFp~o!UDB-$Pgb8RF?(orVYmFhc=~!=3=g zdwddSMVbJ!d4DM}eN&dOi1oin=d6%X-!gg@wQbI)AXf?%+5P+;F%gFvKQPMYGfi^F ztLo(35j~;7*tf?b8?9e1vp+s z&B0Wc(|b4=zG@wTJ9%v9ZE$Ik8jgG0SwLy$ve{%SsWB2<>Yj-V=lL6ZRnz8oDSoo` zq6%n$)WzqfWLAFoL%G}%1qc*SkxgJWEJ{48IfPgxQ{`&yKeZke5Hq9>vmtS${0t^V L9m(?cR_A{K - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/ic_launcher-playstore.png b/ui/BankingAndroidApp/src/main/ic_launcher-playstore.png deleted file mode 100644 index 8e3d8299376a0c92c2be1b5e042bd3dcf3326fb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9744 zcmbVyXFyZgy7mSURKSJ;f)qtjlww2(s1(PFR12Welt{0k_hg2#K>$ajh%}|C2uLw> zf&z(v^j<@YbV3b;K=!v2Gos%)_sqTL*Iqp9U2j|MS#Nlvr*oNio6t4@0C+X7T(}MZ z>`;>(*un{Y7QI?m0pM_l#)We?y}GCSJf9o4#SI`^Cn8VWEx*g7b3vHY+V=K0Pi~8? z8dnmfcRtfQwB^tN7tUQ5>y@uux;xClGkh<$wBFUDK3?9}qr=tXtkvk(`p}NauBDkN z3}G7atY}(2yq_03Z&1*Z^P) z0H{MP$jhC;KXv^d#W#%nue5K7Z}{}@uz&Uw8np%BV*4+n+|R*Eg>BnYzl$cXU=Jm$ z@~^#Fvznl+kBXex38?d47(4yNZhC+f|xHt@`c+y^RtuZ^mPlkT#n8VYyNhnxSf2fB_ZvFVBtr z-0rzzOj?9eG`r1bcpoT@mR&bq)VgfE`nLXSsK9aA9;2p~Y7}lA^reBz%OGg7=69K2 z$g2MiMk-3*V7tyS!Y3}v6s0fJK4=|q4GmNmDmezYV(zrE>C5 zPq+7pWIO0u+3WJn2A7_xUOu#)a`_Ww-m1rdjEV(CAsATEr>gRG%^OS>Q@IFI+^SSAiTg%qIiZ+hknG&*6x)hs( z+I$nC$6kyT3v)^FT+d5BdSzEGsVlT#;BDxwb#-5lx90OH5fOpmQ6DRtTw`9BjS;tQ z0p48WC27zD)8JK7wMMUz2qP+wl1Y?YWg$t!X(2p9m@MmqJ$b;f$K=H!JNIYg%sq-d z%a6_}`!uIu+>D!TFBj#(K)kt|C9*NH>fGsg-f6nS?*N(}KT;ch?M}U_jg70;tq!5- zo_W~v>TmBm^=lksdTz#lX@21tGuE#xI##Lo{(yD6@(M1WLW@_GjdZ0_@4kUCVrq54zC1IpKpT>@>^3y z5zZCmf5utu1ZE=%V?x7^_i4{%=iV`IEzD?gIcKDWd%Y7{N0?l)OjXRIV|@O1igasR zqe>cKN28|f4sUM`c{Z*ZxR5aMID~XUi9ATT<&Khy?7xjs?jR-k+ZkyY6Jt!`sf}lm z06UsZtvZbtshaaa>QZdq?m}&cCU2Vq-}>|(@AZtz*?Lf=K2njO!FRbxF+qD?vhDZ1 zTyi%LIzqGX#%TSnRDD_6^S(coCu965UZg+Qktgz{`aSQ|hdzcT@qq@tQL0eM!_?K! z{Guk7BetH>oa7elc-)e2y>Q3P%myo~g@)A26Q{L8*A%xm-w+fQBj(#Wn@JTXJAbP; z|61~HXI1b*SE=X`tK(dCU1dBT8W#X{F`fBGu?F54SqCL~M+du+{1L=z1XXD`)m*wT zDLSqx#e#O~X&ReKpM_Ild_4YKQG-Or&XiK#W`mk>V)s6{KrKkwcI_xAydPysx`yAw z^+>1Af^0Ag4+hY(S2eT7v$Od4;e@d^nI^vg(zPPDKtm|>`mgn+xaTs%sb?x%faz~% zR^_)h&POkT89oHG3Z*Hw!X!5vb#Q*NdbZ}sv!$RY0+V-6QkGakH*d$AZDuRFl z;jwSy`qy;st{3_qiYO;ix8I!{-42rWe5=;}sf@~VMQMjjJg)i*OPA(8FU8o@ zyFZY&ZsAQswBN+)s(P5-@JOi9i`on6eQZMRc14b0jQzaMk&66^9>&Ne>`IYOYN-vp zTT~X4S(g>?A?JR=Ouu5ae4`2F4D#s={K~815sJCTKD%~>2!ddX>|aTS`Id5~SC>ED zM-Jq$v!iW$c8)$C*GBg4i_8rxEL6NdjT2i1$ zs=$>LTq#Ozq4u3wU>Z z!MhxJ^CF_S%G;-})v8e498wu83I*@Qfj50GXRr66?izI0mMLFK=-DkZns1S1ru}kw zia4Rz=NE;|SE#NScy4+#Vn}=%6CHo^ij#S)$3@j`M%}NG=j~#BJTyH%JFhHC!Vhi( z-mOc6AKn&D$+(YOmgI3n2dR}>wjJ8xrm(#kff@hvKp#1L26iQEM%4V}eKvJ>?X^d` z4OMTC8|9ptZ81ol!E*WBD0=>MM(zq6NYi{ge!n8}3p+aCREb2CNwH=v&F1pSO?zie ziH1+(FC2BKvx?$sju*q5v#FcmNSS`^3H|yBrk=KZB8hS-`gk{Q@zSejGB^vQ#euP; zYVb{$c2k***r?h#@@yiQEO0o*e@ker6gxCi)De`M_k4oO?E|s_^&>kLaf?CIZs0Ya z`70b-fc_)`t@#C*cYGVNdVy0U(Z^mY;c2pfh=}qHsMp7&J43E-DhkV?FaWekW?aQO z*#)0ZEr96(jp@GgX`{|?)o(heM4t@bJe3}wPR$?=pfqnWp`RWR|4E@7Xp>cW@m!JD zMM@oL98LjK?G4q!R@pwzKOVq9J23Niyfd5n4vcAEOsQCJIeTl+;{2;?>31-L?C6=( z1@Z#9aqF8tVz=pu<~G-mW_8k`qtbC7Qb+TBKzWy%o^Nw{Rg3WE5E6t&yWCdA&QLnV z^n9^pjr+nq_h2A6^D50wt|Y};oXyrisA7BE#7Q)esHtr^N1UsZl#cNb z6OMuBSEU{?2Dxkvg({kFS!xLYZs!=c49X#Ji(V~x%N4n8CsVnBqPzHr2c6g+fW0-- z!S^%*ukXmQ2XM2Y5ewmahH^?dcP4tIz@$Sgu$%dT{fQ4L#?rGKzzOwu4#D;r4S=nj zO{3T2RIKH0o=gda*p!*Y~m1CLPHEv93qp9FGM6Ej7OBwhG-mw zL3E9YL2Qg&ok7ev&ywaP&-f@Vx!EF5Q1j(K+=pJ=*v*S0jXz5Gun)P2F}LB zL83FWQ7+Dd4mFnE1C*<8MeDGM14`mcRmRciBvR_+ z!Yt0u$0aZpPl1)bGw#&4F9OXnwj_4uS#K-W=4-iLH<*8@P!(WspLPYVNe)f%+N;TV9%X?|o1(vN?(!J@N75*-I%VT4B+H zO=@iFSyw!p0`A{)l`csc%T`ac6{Bf7(P`G+?_EZ5Kw^~K=Gc;w!wgPPOA)e1PyB^X z&O>%dkznu2?w9Zbi$!^_@Ncd1@1v{@po>9y!K^G@P@)FW;{1{h?b|csJEr)K-x+$} z6O`=`=F5(zhvO672;dRJ$RnUmIAlNAzDJ6iRIp*4oVC~G%6WcwLPVW;`o)x~0$$TOI|Bv=}BOe^{5+)(7-7rq%-M`|R> z3mlQPdD7xBf*`4+6pVNu02a$mVUuB!Aqr3jc0>+%!_TE#U!|dG^g2%=K}ELU+b2rF z*lif#MvR;ne1?B^Dm5>P5Xs=0v>HSRVT}XOU!|k-q~R|5ntNm&Ycrc<3JL`^$ZZ3xCTU~D;PCqP>P+8e(<;7k;g{jc-9P=r0yN)U8+mAsj8Aoo}T@{3LQ zP~vN%0}k5c`%kL~T>e^L)wB>Z6iscD^2aXjYq8Q!=yEcIy-zx<>g8kQ=hu|CQd!dl zo9`{upIoVG8J6Hqt9*5%$NWma(^24!40ZlbHSg=KbqPDqM}>v0x+9Y4Yp|vd?rx{- zj~AB&O~3KOugV}^2efnw7Wo*r%7}`cx75W1*6fnM6;KhVTU(XQ{c@OZ6kGWxw^5SA zWg|D!@UXY=5d>a_8trcP>R3ucq$*o5U#v$PrAVRDcEtAYNic5N?GS~nn(En>z1UnEFa_H&l?-|`dtN0@=S?oahDsu*&g{TA z*H$69b%JdSvw~_>T^&kRlG28Hz%^=2+#<1BY<)d#C=|-1Cb>U0!+C$N6bA>ep5Llw zalKVWI3e!94x)nk5qiGQK&zmKrZR_OShcL{{#Mi44vO&bpL^??yd6{xRE&Z`&EHW^Yt3n?#!O9EIKDf+ zud}nU-`*HHysDm|`bxH5Lsdr$1~feWq)f$GDBK;3K`OXvh?{__ewH`#?45!aC_H6P zz~vdfPLrC@s=-{_(SGy}x!B$5qTRa_sB^h<6~q$7qesB?GRlHs&P&cC@6C2rnC#vO zln}zfwXIzr>2BJ7db)HRqH|gzDWIa$g+uH8YBl(H{(@mqj)PwO60XHo{j}ueR&|c# zYSe=KnV}_+^7fp{9GFR78{+ONWea)PfEg5#!P`JAIcG}ElQ@FHX@JWI2SRs6Y>7Vm z*7gWkVL9^pR{WUai#3!PHF{5$b#3UikC)1uTu+;~$VcIY)x4W3L4G2Ql-?x~I@}(& zYw2**CWr`~`Tc9G;F3`s6^G#HRXq4GQ&gBM;+-6Ov+Hb#K>q0kR8$1o4f77!fL@Mk z=RZDEEN;4>AoBzE^Yli3enOMh2JHw ziFaUAcamP;VWKMAvy;Gq0%p_{gfjQXsT{m5qX}NFa|pV)W3TosmvvKM6+_kSkw@Qj zL%GUaov^S_4SHXSUX1^G%$t1IL?H1I-wELdhVK9z7&7I6&07p-*5Ca)PiURHdM8MGfn3f9^#g#{wfz!+1rwN$AUp`rGR>2 zfr^=(fJzyU^W>KRZ=(UEl_H^AKx;td<2UMc>Me>tkZc9wX5n(tmA+#k2~#0$VaDc+ zvExGX4-h$q{V|ok^icF7rLwF~ITNO1++@#AK0JP_eQ9nO%?Fo#tTz8SL6r7QEkIG$ zpK6OJ0uqlmfN=YKs;-m6w&${GizG7qy@WtgdokOGe2j6&Ze9_8U$JtGok3N?+T!7G zFFE^dZVOS4b+T^-do}}HiyY;L8o=dm0l;yZBJdC*8wGXjiTRkG-WZXVvNc|T-lF~m zu=G&rF|X(j4sKxkEN6143t%h@_#6g2A~xM^D^MlUJ)19PNRmxY&V4RJogZi}h7+Q| z!4}C`(+`uAo>lj5EZ{vLZanq~P|A1OBtC5lw+RNuWTaA8PXm!e*WZD$3}6LsGDjcZ zj3{O@Xe$8a+-vI{BB->1u&ZOc@!C!GSQxON_vmx@Gt21>$8vZTL z{zIN+0|J<`5c6lXm@kFz<5>zJO^g=vApx}*avK0^APZ*`|65S2pDE88#ti1WI+o-w z8USb<1pKq+f9K=h*v~#Py<+*j5h*JrEZ}>L0Q>iOs5bg3liy=y`u^Q%D5)&x{@F)> z?cW5$!SwFCDMpHzPO~tkBP@)s;QNALx%$r`Fmx~%AS=Z`+}zOcleJ%C{%&f+v!4XN zJ1G9c)gK|TZMej0{omFFD^3npLK!BRo&s!4V~mg1z|TvE<45Y5^YOza77oe(old46 zW@1^MZU5t^zJHZMe~+Ivj5UU}IM{z|lwWb?(r4xv*brfj`In&^_`ld-Y5hBQOy~Z_ z{-?FU@jVl4KN7_PpwC8X%12~=`it>u|Nj>T07_8$>2yO<}+uW5uNSSg7v+02k<{q>V$Ka$7sV*#)XY`DY#pze+6S-^%MtM!kE z+KJz}zvpVhmmdzW{cw(HYXiS)FR*b|Lw!u^0Q*nT{5)U--_YnaK3w$1Qciii&ueO{q5*n=nCE*9~(T!ka!kqaXQtXDje@kd$`h)Pzn)& z&7J|%_4DKoTVnxW|I^D!lv;h8YPcXBf|y|MK*ug7sx6_Pe;ja95aPt}vVLF_DVF zaM~zm&f=l+C_2rQ&l~Pfjxxi%qU448*xKVfS5x01d(DoeSQ0keaNI4uIre(K(eM}*m_rBlgr>i zL;;XUNCzhImhik6y*t*La79$UcSFmXFWE(KUrPa#QVKXX4->xgE)@5vmuiJy0O@lp z^sKYHy~N8FTS~LP{T1v09tXxEj<8#5V;(wqaGw1T2VRN{v@yn+(!ld%PV1f~{z)|p z7ZiN5hHz9QJ@ANOLwokPDf(lWL!AewRtHvl-ib_HYZ=Ww1FB`aV6%;YM!Ueq+r!6c z>|WBdCXsZ){V+WP{qhLJ$U0PtoQZqTx$;bdKAntk^`Q!;AQTRnnV?XY>&72Xnifly z(Q#(5CR_yqrAwz)G?n?kfI$k=gF;|#RRvSu6qh%x4QivBh4-}BYUpzszk-D-CrRokJdF9u$NK85`-7SxB`};ZJ-Ob z<#q*tkGw{7fkt@LrV0M(;v)lP=lt?P6N%RWwb6nn5#|o-0i-80k8f+k!1&LJ0f+%_ z->Y4)D}dM?MNAGsb%Bs7s4CENh-(WO}w(i9b+h)Dlz3luz@X`=6#Gsm8G%+%7?fCJo(tdc{r+b=afK z+XyT5>=JP$zSFQcd}%}_yA*`Kl~qKZvcrs)KdmNofC#uOIJmnsAZrNrL7S@h|d zm3}$1jKZy8A - drawerView = DrawerView(this, slider, presenter) - } - - val floatingActionMenu = findViewById(R.id.floatingActionMenu) - floatingActionMenuButton = MainActivityFloatingActionMenuButton(floatingActionMenu, permissionsService, presenter) - } - - override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.menu_main, menu) - - return true - } - - - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - permissionsService.onRequestPermissionsResult(requestCode, permissions, grantResults) - - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - val scanQrCodeResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data) - - if (scanQrCodeResult != null) { - // at this point camera activity is still displayed and not returned yet to MainActivity -> app would crash if we don't wait - Handler(Looper.getMainLooper()).postDelayed(250) { - handleQrCodeScanResult(scanQrCodeResult) - } - } - else { - super.onActivityResult(requestCode, resultCode, data) - } - } - - private fun handleQrCodeScanResult(scanQrCodeResult: IntentResult) { - scanQrCodeResult.contents?.let { decodedQrCode -> - val result = presenter.showTransferMoneyDialogWithDataFromQrCode(decodedQrCode) - - if (result.successful == false) { - showParseQrCodeError(result) - } - } - } - - protected fun showParseQrCodeError(result: ParseEpcQrCodeResult) { - // TODO: show localized error message that matches ParseEpcQrCodeResultCode - val errorMessage = getString(R.string.money_transfer_from_scanning_qr_code_error, result.error, result.decodedQrCode) - - AlertDialog.Builder(this) - .setMessage(errorMessage) - .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - - - override fun dispatchTouchEvent(event: MotionEvent): Boolean { - if(floatingActionMenuButton.handlesTouch(event)) { // close menu when menu is opened and touch is outside floatingActionMenuButton - return true - } - - return super.dispatchTouchEvent(event) - } - - override fun onBackPressed() { - if (floatingActionMenuButton.handlesBackButtonPress()) { // close menu when menu is opened and back button gets pressed - return - } - - super.onBackPressed() - } - -} diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/RouterAndroid.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/RouterAndroid.kt deleted file mode 100644 index 342084d2..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/RouterAndroid.kt +++ /dev/null @@ -1,57 +0,0 @@ -package net.dankito.banking.ui.android - -import net.dankito.banking.ui.android.util.CurrentActivityTracker -import net.dankito.banking.ui.IRouter -import net.dankito.banking.ui.android.dialogs.* -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.model.parameters.TransferMoneyData -import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult -import net.dankito.banking.ui.model.tan.EnterTanResult -import net.dankito.banking.ui.model.tan.TanChallenge -import net.dankito.banking.ui.model.tan.TanGeneratorTanMedium -import net.dankito.banking.ui.presenter.BankingPresenter - - -open class RouterAndroid(protected val activityTracker: CurrentActivityTracker) : IRouter { - - override fun showAddAccountDialog(presenter: BankingPresenter) { - activityTracker.currentOrNextActivity { activity -> - AddAccountDialog().show(activity) - } - } - - override fun getTanFromUserFromNonUiThread(bank: TypedBankData, tanChallenge: TanChallenge, presenter: BankingPresenter, callback: (EnterTanResult) -> Unit) { - activityTracker.currentOrNextActivity { activity -> - activity.runOnUiThread { - EnterTanDialog().show(bank, tanChallenge, activity, false) { result -> - callback(result) - } - } - } - } - - override fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium, callback: (EnterTanGeneratorAtcResult) -> Unit) { - activityTracker.currentOrNextActivity { activity -> - activity.runOnUiThread { - EnterAtcDialog().show(tanMedium, activity, false) { enteredResult -> - callback(enteredResult) - } - } - } - } - - override fun showTransferMoneyDialog(presenter: BankingPresenter, preselectedValues: TransferMoneyData?) { - activityTracker.currentOrNextActivity { activity -> - TransferMoneyDialog().show(activity, preselectedValues) - } - } - - override fun showSendMessageLogDialog(presenter: BankingPresenter) { - activityTracker.currentOrNextActivity { activity -> - activity.runOnUiThread { - SendMessageLogDialog().show(activity) - } - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/ActivityExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/ActivityExtensions.kt deleted file mode 100644 index ded62c06..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/ActivityExtensions.kt +++ /dev/null @@ -1,20 +0,0 @@ -package net.dankito.banking.ui.android.activities - -import android.app.Activity -import android.content.Intent -import android.util.DisplayMetrics - - -fun Activity.navigateToActivity(activityClass: Class) { - val intent = Intent(applicationContext, activityClass) - - startActivity(intent) -} - -val Activity.screenWidth: Int - get() { - val displayMetrics = DisplayMetrics() - windowManager.defaultDisplay.getMetrics(displayMetrics) - - return displayMetrics.widthPixels - } \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/BaseActivity.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/BaseActivity.kt deleted file mode 100644 index 45dae8df..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/BaseActivity.kt +++ /dev/null @@ -1,78 +0,0 @@ -package net.dankito.banking.ui.android.activities - -import android.content.pm.ActivityInfo -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.android.util.CurrentActivityTracker -import org.slf4j.LoggerFactory -import javax.inject.Inject - - -abstract class BaseActivity : AppCompatActivity() { - - companion object { - private val log = LoggerFactory.getLogger(BaseActivity::class.java) - } - - - @Inject - protected lateinit var currentActivityTracker: CurrentActivityTracker - - - init { - BankingComponent.component.inject(this) - } - - - open val isRunningOnTablet: Boolean - get() = resources.getBoolean(R.bool.isTablet) - - - override fun onCreate(savedInstanceState: Bundle?) { - log.info("Creating Activity $this") - - // a bit bad as it not clearly visible that orientation lock is done here - if (isRunningOnTablet == false) { // lock screen to portrait mode on phones as there app really looks bad and some EditTexts are almost unusable - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - } - - super.onCreate(savedInstanceState) - } - - override fun onStart() { - super.onStart() - - currentActivityTracker.currentActivity = this - - log.info("Started Activity $this") - } - - override fun onResume() { - super.onResume() - - currentActivityTracker.currentActivity = this - - log.info("Resumed Activity $this") - } - - override fun onPause() { - log.info("Paused Activity $this") - - super.onPause() - } - - override fun onStop() { - log.info("Stopped Activity $this") - - super.onStop() - } - - override fun onDestroy() { - log.info("Destroyed Activity $this") - - super.onDestroy() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LandingActivity.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LandingActivity.kt deleted file mode 100644 index c72b9aa9..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LandingActivity.kt +++ /dev/null @@ -1,42 +0,0 @@ -package net.dankito.banking.ui.android.activities - -import android.app.Activity -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import net.dankito.banking.ui.android.MainActivity -import net.dankito.banking.ui.android.authentication.AuthenticationService -import net.dankito.banking.ui.android.authentication.AuthenticationType -import net.dankito.banking.ui.android.di.BankingComponent -import javax.inject.Inject - - -open class LandingActivity : AppCompatActivity() { - - @Inject - protected lateinit var authenticationService: AuthenticationService - - - init { - BankingComponent.component.inject(this) - } - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - if (authenticationService.authenticationType == AuthenticationType.None) { - launchActivity(MainActivity::class.java) - } - else { - launchActivity(LoginActivity::class.java) - } - } - - - protected open fun launchActivity(activityClass: Class) { - navigateToActivity(activityClass) - - finish() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LoginActivity.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LoginActivity.kt deleted file mode 100644 index 2a67a43a..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/activities/LoginActivity.kt +++ /dev/null @@ -1,89 +0,0 @@ -package net.dankito.banking.ui.android.activities - -import android.os.Bundle -import android.view.View -import android.widget.Toast -import kotlinx.android.synthetic.main.activity_login.* -import kotlinx.android.synthetic.main.activity_login.btnBiometricAuthentication -import kotlinx.android.synthetic.main.view_biometric_authentication_button.* -import net.dankito.banking.ui.android.MainActivity -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.authentication.AuthenticationService -import net.dankito.banking.ui.android.authentication.AuthenticationType -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.android.extensions.addEnterPressedListener -import net.dankito.utils.android.extensions.hide -import javax.inject.Inject - - -open class LoginActivity : BaseActivity() { - - @Inject - protected lateinit var authenticationService: AuthenticationService - - - init { - BankingComponent.component.inject(this) - } - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - initUi() - } - - - protected open fun initUi() { - setContentView(R.layout.activity_login) - - if (authenticationService.authenticationType == AuthenticationType.Password) { - lytBiometricAuthentication.hide() - - edtxtLoginPassword.actualEditText.addEnterPressedListener { - checkEnteredPasswordAndLogIn() - true - } - - btnLogin.setOnClickListener { checkEnteredPasswordAndLogIn() } - } - else { - lytPasswordAuthentication.hide() - - btnBiometricAuthentication.customButtonClickHandler = { - authenticationService.loginUserWithBiometric { result -> - if (result) { - btnStartBiometricAuthentication.isEnabled = false - - biometricAuthenticationSuccessful() - } - } - } - - btnBiometricAuthentication.showBiometricPrompt() - } - } - - - protected open fun checkEnteredPasswordAndLogIn() { - btnLogin.isEnabled = false - - if (authenticationService.loginUserWithPassword(edtxtLoginPassword.chars)) { - navigateToMainActivity() - } - else { - btnLogin.isEnabled = true - - Toast.makeText(this, R.string.activity_login_incorrect_password_entered, Toast.LENGTH_SHORT).show() - } - } - - protected open fun biometricAuthenticationSuccessful() { - navigateToMainActivity() - } - - protected open fun navigateToMainActivity() { - navigateToActivity(MainActivity::class.java) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/AccountTransactionAdapter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/AccountTransactionAdapter.kt deleted file mode 100644 index fcf92c2c..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/AccountTransactionAdapter.kt +++ /dev/null @@ -1,81 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.view.ContextMenu -import android.view.View -import androidx.appcompat.app.AppCompatActivity -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.viewholder.AccountTransactionViewHolder -import net.dankito.banking.ui.android.dialogs.AccountTransactionDetailsDialog -import net.dankito.banking.ui.android.extensions.setIcon -import net.dankito.banking.ui.android.extensions.showAmount -import net.dankito.banking.ui.model.IAccountTransaction -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.utils.android.extensions.asActivity -import net.dankito.utils.android.extensions.hide -import net.dankito.utils.android.extensions.show -import net.dankito.utils.android.ui.adapter.ListRecyclerAdapter - - -open class AccountTransactionAdapter(protected val presenter: BankingPresenter) - : ListRecyclerAdapter() { - - - var selectedTransaction: IAccountTransaction? = null - - - override fun getListItemLayoutId() = R.layout.list_item_account_transaction - - override fun createViewHolder(itemView: View): AccountTransactionViewHolder { - val viewHolder = AccountTransactionViewHolder(itemView) - - itemView.setOnCreateContextMenuListener { menu, view, menuInfo -> createContextMenu(menu, view, menuInfo, viewHolder) } - - return viewHolder - } - - override fun bindItemToView(viewHolder: AccountTransactionViewHolder, item: IAccountTransaction) { - viewHolder.txtvwDate.text = presenter.formatToShortDate(item.valueDate) - - val label = if (item.showOtherPartyName) item.otherPartyName else item.bookingText - viewHolder.txtvwTransactionLabel.text = label ?: item.bookingText ?: "" - - viewHolder.txtvwReference.text = item.reference - - viewHolder.txtvwAmount.showAmount(presenter, item.amount, item.currency) - - if (presenter.areAllAccountSelected) { - viewHolder.imgvwBankIcon.setIcon(item.account.bank) - viewHolder.imgvwBankIcon.show() - } - else { - // TODO: if bank icon isn't set: Show default icon? show at least an empty space to that amount and date don't shift up causing an inconsistent view? - viewHolder.imgvwBankIcon.hide() - } - - viewHolder.itemView.setOnClickListener { - AccountTransactionDetailsDialog().show(item, viewHolder.itemView.context as AppCompatActivity) - } - } - - - protected open fun createContextMenu(menu: ContextMenu, view: View, menuInfo: ContextMenu.ContextMenuInfo?, - viewHolder: AccountTransactionViewHolder) { - - view.context.asActivity()?.menuInflater?.inflate(R.menu.context_menu_account_transactions, menu) - - selectedTransaction = getItem(viewHolder.adapterPosition) - - val canCreateMoneyTransferFrom = selectedTransaction?.canCreateMoneyTransferFrom ?: false - - menu.findItem(R.id.mnitmNewTransferWithSameData)?.isVisible = canCreateMoneyTransferFrom - - menu.findItem(R.id.mnitmNewTransferToSameTransactionParty)?.let { mnitmShowTransferMoneyDialog -> - mnitmShowTransferMoneyDialog.isVisible = canCreateMoneyTransferFrom - - val recipientName = selectedTransaction?.otherPartyName ?: "" - - mnitmShowTransferMoneyDialog.title = view.context.getString(R.string.fragment_home_transfer_money_to, recipientName) - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/BankDataAdapterItem.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/BankDataAdapterItem.kt deleted file mode 100644 index 84afc7ed..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/BankDataAdapterItem.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.view.View -import com.mikepenz.fastadapter.drag.IDraggable -import com.mikepenz.fastadapter.items.AbstractItem -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.viewholder.BankDataViewHolder -import net.dankito.banking.ui.model.TypedBankData - - -open class BankDataAdapterItem(open val bank: TypedBankData) : AbstractItem(), IDraggable { - - override var isDraggable = true - - override val type: Int - get() = R.id.bank_data_item_id - - override val layoutRes: Int - get() = R.layout.list_item_bank_data - - override fun getViewHolder(v: View): BankDataViewHolder { - return BankDataViewHolder(v) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/BankListAdapter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/BankListAdapter.kt deleted file mode 100644 index 90ca7fc8..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/BankListAdapter.kt +++ /dev/null @@ -1,43 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.view.View -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.viewholder.BankInfoViewHolder -import net.dankito.banking.bankfinder.BankInfo -import net.dankito.utils.android.extensions.setTintColor -import net.dankito.utils.android.ui.adapter.ListRecyclerAdapter - - -open class BankListAdapter(protected val itemClicked: ((BankInfo) -> Unit)? = null) : ListRecyclerAdapter() { - - override fun getListItemLayoutId() = R.layout.list_item_bank_info - - override fun createViewHolder(itemView: View): BankInfoViewHolder { - return BankInfoViewHolder(itemView) - } - - override fun bindItemToView(viewHolder: BankInfoViewHolder, item: BankInfo) { - if (item.supportsFinTs3_0) { - viewHolder.imgSupportsFints30.setImageResource(R.drawable.ic_check_circle_white_48dp) - viewHolder.imgSupportsFints30.setTintColor(R.color.list_item_bank_info_bank_supported) - } - else { - viewHolder.imgSupportsFints30.setImageResource(R.drawable.ic_clear_white_48dp) - viewHolder.imgSupportsFints30.setTintColor(R.color.list_item_bank_info_bank_not_supported) - } - - viewHolder.txtvwBankName.text = item.name - viewHolder.txtvwBankName.isEnabled = item.supportsFinTs3_0 - - viewHolder.txtvwBankCode.text = item.bankCode - viewHolder.txtvwBankCode.isEnabled = item.supportsFinTs3_0 - - viewHolder.txtvwBankAddress.text = item.postalCode + " " + item.city - viewHolder.txtvwBankAddress.isEnabled = item.supportsFinTs3_0 - - viewHolder.itemView.setOnClickListener { - itemClicked?.invoke(item) - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/CheckableValueAdapterItem.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/CheckableValueAdapterItem.kt deleted file mode 100644 index 0d18d1d0..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/CheckableValueAdapterItem.kt +++ /dev/null @@ -1,27 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.content.Context -import android.view.View -import androidx.annotation.StringRes -import com.mikepenz.fastadapter.items.AbstractItem -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.viewholder.CheckableValueViewHolder - - -open class CheckableValueAdapterItem(open val isChecked: Boolean, open val text: String) : AbstractItem() { - - constructor(isChecked: Boolean, context: Context, @StringRes textStringResourceId: Int) : this(isChecked, context.getString(textStringResourceId)) - - - override val type: Int - get() = R.id.checkable_value_item_id - - override val layoutRes: Int - get() = R.layout.list_item_checkable_value - - - override fun getViewHolder(v: View): CheckableValueViewHolder { - return CheckableValueViewHolder(v) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/DraggableBankAccountAdapterItem.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/DraggableBankAccountAdapterItem.kt deleted file mode 100644 index 1eb9022e..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/DraggableBankAccountAdapterItem.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.view.View -import com.mikepenz.fastadapter.drag.IDraggable -import com.mikepenz.fastadapter.items.AbstractItem -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.viewholder.DraggableBankAccountViewHolder -import net.dankito.banking.ui.model.TypedBankAccount - - -open class DraggableBankAccountAdapterItem(open val account: TypedBankAccount) : AbstractItem(), IDraggable { - - override var isDraggable = true - - override val type: Int - get() = R.id.draggable_bank_account_item_id - - override val layoutRes: Int - get() = R.layout.list_item_draggable_bank_account - - override fun getViewHolder(v: View): DraggableBankAccountViewHolder { - return DraggableBankAccountViewHolder(v) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/FastAdapterRecyclerView.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/FastAdapterRecyclerView.kt deleted file mode 100644 index 5351e464..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/FastAdapterRecyclerView.kt +++ /dev/null @@ -1,86 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import androidx.recyclerview.widget.DefaultItemAnimator -import androidx.recyclerview.widget.ItemTouchHelper -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import com.mikepenz.fastadapter.FastAdapter -import com.mikepenz.fastadapter.GenericItem -import com.mikepenz.fastadapter.adapters.ItemAdapter -import com.mikepenz.fastadapter.adapters.ItemAdapter.Companion.items -import com.mikepenz.fastadapter.drag.ItemTouchCallback -import com.mikepenz.fastadapter.drag.SimpleDragCallback -import com.mikepenz.fastadapter.select.getSelectExtension -import com.mikepenz.fastadapter.utils.DragDropUtil - - -open class FastAdapterRecyclerView( - recyclerView: RecyclerView, - items: List = listOf(), - enableDragAndDrop: Boolean = false, - open var itemDropped: ((oldPosition: Int, oldItem: Item, newPosition: Int, newItem: Item) -> Unit)? = null, - open var onClickListener: ((Item) -> Unit)? = null -) : ItemTouchCallback { - - - protected val fastAdapter: FastAdapter - protected val itemAdapter: ItemAdapter - - private lateinit var touchCallback: SimpleDragCallback - private lateinit var touchHelper: ItemTouchHelper - - - init { - itemAdapter = items() - - fastAdapter = FastAdapter.with(itemAdapter) - - init(recyclerView, items, enableDragAndDrop) - } - - - protected open fun init(recyclerView: RecyclerView, items: List, enableDragAndDrop: Boolean = true) { - val selectExtension = fastAdapter.getSelectExtension() - selectExtension.isSelectable = true - - fastAdapter.onClickListener = { _, _, item, _ -> - onClickListener?.invoke(item) - false - } - - recyclerView.layoutManager = LinearLayoutManager(recyclerView.context) - recyclerView.itemAnimator = DefaultItemAnimator() - recyclerView.adapter = fastAdapter - - itemAdapter.set(items) - - - if (enableDragAndDrop) { - touchCallback = SimpleDragCallback(this) - touchHelper = ItemTouchHelper(touchCallback) - touchHelper.attachToRecyclerView(recyclerView) - } - } - - - override fun itemTouchStartDrag(viewHolder: RecyclerView.ViewHolder) { - // add visual highlight to dragged item - } - - override fun itemTouchOnMove(oldPosition: Int, newPosition: Int): Boolean { - DragDropUtil.onMove(itemAdapter, oldPosition, newPosition) // change position - return true - } - - override fun itemTouchDropped(oldPosition: Int, newPosition: Int) { - // remove visual highlight to dropped item - - itemDropped?.invoke(oldPosition, itemAdapter.getAdapterItem(oldPosition), newPosition, itemAdapter.getAdapterItem(newPosition)) - } - - - open fun setItems(items: List) { - itemAdapter.set(items) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/IconedBankAccountsAdapter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/IconedBankAccountsAdapter.kt deleted file mode 100644 index 715cbf6e..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/IconedBankAccountsAdapter.kt +++ /dev/null @@ -1,32 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.content.Context -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import kotlinx.android.synthetic.main.list_item_iconed_bank_account.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.extensions.setIcon -import net.dankito.banking.ui.model.TypedBankAccount -import net.dankito.utils.android.ui.adapter.ListAdapter - - -open class IconedBankAccountsAdapter(accounts: List) : ListAdapter(accounts) { - - override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? { - - val item = getItem(position) - - val inflater = parent?.context?.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as? LayoutInflater - val view = convertView ?: inflater?.inflate(R.layout.list_item_iconed_bank_account, parent, false) - - view?.let { - view.txtBankAccountDisplayName.text = item.displayName - - view.imgBankIcon.setIcon(item.bank) - } - - return view - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/RecipientListAdapter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/RecipientListAdapter.kt deleted file mode 100644 index e46c03c1..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/RecipientListAdapter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.view.View -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.viewholder.RecipientViewHolder -import net.dankito.banking.search.TransactionParty -import net.dankito.utils.android.extensions.isGone -import net.dankito.utils.android.ui.adapter.ListRecyclerAdapter - - -open class RecipientListAdapter(protected val itemClicked: ((TransactionParty) -> Unit)? = null) : ListRecyclerAdapter() { - - override fun getListItemLayoutId() = R.layout.list_item_recipient - - override fun createViewHolder(itemView: View): RecipientViewHolder { - return RecipientViewHolder(itemView) - } - - override fun bindItemToView(viewHolder: RecipientViewHolder, item: TransactionParty) { - viewHolder.txtvwRecipientName.text = item.name - - viewHolder.txtvwRecipientBankName.text = item.bankName - viewHolder.txtvwRecipientBankName.isGone = item.bankName.isNullOrBlank() - - viewHolder.txtvwRecipientAccountId.text = item.iban - - viewHolder.txtvwRecipientBankCode.text = item.bic - - viewHolder.itemView.setOnClickListener { - itemClicked?.invoke(item) - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMediumAdapter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMediumAdapter.kt deleted file mode 100644 index de02b008..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMediumAdapter.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.model.tan.TanMedium -import net.dankito.utils.android.extensions.asActivity -import net.dankito.utils.android.ui.adapter.ListAdapter - - -open class TanMediumAdapter : ListAdapter() { - - override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? { - val tanMedium = getItem(position) - - val view = convertView ?: parent?.context?.asActivity()?.layoutInflater?.inflate( - R.layout.list_item_tan_medium, parent, false) - - view?.findViewById(R.id.txtTanMediumDisplayName)?.text = tanMedium.displayName - - return view - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMethodAdapterItem.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMethodAdapterItem.kt deleted file mode 100644 index 49798d3a..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMethodAdapterItem.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import net.dankito.banking.ui.model.tan.TanMethod - - -open class TanMethodAdapterItem(open val tanMethod: TanMethod, isSelectedTanMethod: Boolean) - : CheckableValueAdapterItem(isSelectedTanMethod, tanMethod.displayName) \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMethodsAdapter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMethodsAdapter.kt deleted file mode 100644 index 4be49be7..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/TanMethodsAdapter.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.dankito.banking.ui.android.adapter - -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.model.tan.TanMethod -import net.dankito.utils.android.extensions.asActivity -import net.dankito.utils.android.ui.adapter.ListAdapter - - -open class TanMethodsAdapter : ListAdapter() { - - override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? { - val method = getItem(position) - - val view = convertView ?: parent?.context?.asActivity()?.layoutInflater?.inflate( - R.layout.list_item_tan_method, parent, false) - - view?.findViewById(R.id.txtTanMethodDisplayName)?.text = method.displayName - - return view - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/presenter/BankInfoPresenter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/presenter/BankInfoPresenter.kt deleted file mode 100644 index 4fd503b8..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/presenter/BankInfoPresenter.kt +++ /dev/null @@ -1,38 +0,0 @@ -package net.dankito.banking.ui.android.adapter.presenter - -import android.content.Context -import androidx.recyclerview.widget.RecyclerView -import com.otaliastudios.autocomplete.RecyclerViewPresenter -import kotlinx.coroutines.* -import net.dankito.banking.ui.android.adapter.BankListAdapter -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.banking.bankfinder.BankInfo -import net.dankito.banking.ui.android.extensions.addHorizontalItemDivider - - -open class BankInfoPresenter(protected val presenter: BankingPresenter, context: Context) : RecyclerViewPresenter(context) { - - protected val adapter = BankListAdapter { dispatchClick(it) } - - protected var lastSearchBanksJob: Job? = null - - - override fun instantiateAdapter(): RecyclerView.Adapter<*> { - recyclerView?.addHorizontalItemDivider() - - return adapter - } - - override fun onQuery(query: CharSequence?) { - lastSearchBanksJob?.cancel() - - lastSearchBanksJob = GlobalScope.launch(Dispatchers.IO) { - val filteredBanks = presenter.findBanksByNameBankCodeOrCity(query?.toString()) - - withContext(Dispatchers.Main) { - adapter.items = filteredBanks - } - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/presenter/RecipientPresenter.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/presenter/RecipientPresenter.kt deleted file mode 100644 index cc71845c..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/presenter/RecipientPresenter.kt +++ /dev/null @@ -1,38 +0,0 @@ -package net.dankito.banking.ui.android.adapter.presenter - -import android.content.Context -import androidx.recyclerview.widget.RecyclerView -import com.otaliastudios.autocomplete.RecyclerViewPresenter -import kotlinx.coroutines.* -import net.dankito.banking.ui.android.adapter.RecipientListAdapter -import net.dankito.banking.search.TransactionParty -import net.dankito.banking.ui.android.extensions.addHorizontalItemDivider -import net.dankito.banking.ui.presenter.BankingPresenter - - -open class RecipientPresenter(protected val bankingPresenter: BankingPresenter, context: Context) : RecyclerViewPresenter(context) { - - protected val adapter = RecipientListAdapter { dispatchClick(it) } - - protected var lastSearchRecipientJob: Job? = null - - - override fun instantiateAdapter(): RecyclerView.Adapter<*> { - recyclerView?.addHorizontalItemDivider() - - return adapter - } - - override fun onQuery(query: CharSequence?) { - lastSearchRecipientJob?.cancel() - - lastSearchRecipientJob = GlobalScope.launch(Dispatchers.IO) { - val potentialRecipients = bankingPresenter.findRecipientsForName(query?.toString() ?: "") - - withContext(Dispatchers.Main) { - adapter.items = potentialRecipients - } - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/AccountTransactionViewHolder.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/AccountTransactionViewHolder.kt deleted file mode 100644 index d05eb757..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/AccountTransactionViewHolder.kt +++ /dev/null @@ -1,22 +0,0 @@ -package net.dankito.banking.ui.android.adapter.viewholder - -import android.view.View -import android.widget.ImageView -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.list_item_account_transaction.view.* - - -open class AccountTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - - val txtvwDate: TextView = itemView.txtvwDate - - val txtvwTransactionLabel: TextView = itemView.txtvwTransactionLabel - - val txtvwReference: TextView = itemView.txtvwReference - - val txtvwAmount: TextView = itemView.txtvwAmount - - val imgvwBankIcon: ImageView = itemView.imgvwBankIcon - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/BankDataViewHolder.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/BankDataViewHolder.kt deleted file mode 100644 index 8f166ee3..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/BankDataViewHolder.kt +++ /dev/null @@ -1,28 +0,0 @@ -package net.dankito.banking.ui.android.adapter.viewholder - -import android.view.View -import android.widget.ImageView -import android.widget.TextView -import com.mikepenz.fastadapter.FastAdapter -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.BankDataAdapterItem -import net.dankito.banking.ui.android.extensions.setIcon - - -open class BankDataViewHolder(view: View) : FastAdapter.ViewHolder(view) { - - protected var bankIcon: ImageView = view.findViewById(R.id.imgBankIcon) - protected var bankDisplayName: TextView = view.findViewById(R.id.txtBankDisplayName) - - - override fun bindView(item: BankDataAdapterItem, payloads: List) { - bankIcon.setIcon(item.bank) - bankDisplayName.text = item.bank.displayName - } - - override fun unbindView(item: BankDataAdapterItem) { - bankDisplayName.text = null - bankIcon.setImageURI(null) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/BankInfoViewHolder.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/BankInfoViewHolder.kt deleted file mode 100644 index b19ad1a3..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/BankInfoViewHolder.kt +++ /dev/null @@ -1,20 +0,0 @@ -package net.dankito.banking.ui.android.adapter.viewholder - -import android.view.View -import android.widget.ImageView -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.list_item_bank_info.view.* - - -open class BankInfoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - - val imgSupportsFints30: ImageView = itemView.imgSupportsFints30 - - val txtvwBankName: TextView = itemView.txtvwBankName - - val txtvwBankCode: TextView = itemView.txtvwBankCode - - val txtvwBankAddress: TextView = itemView.txtvwBankAddress - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/CheckableValueViewHolder.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/CheckableValueViewHolder.kt deleted file mode 100644 index 4d364c69..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/CheckableValueViewHolder.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.dankito.banking.ui.android.adapter.viewholder - -import android.view.View -import android.widget.ImageView -import android.widget.TextView -import com.mikepenz.fastadapter.FastAdapter -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.CheckableValueAdapterItem -import net.dankito.utils.android.extensions.setVisibleOrInvisible - - -open class CheckableValueViewHolder(view: View) : FastAdapter.ViewHolder(view) { - - protected var imgCheckmark: ImageView = view.findViewById(R.id.imgCheckmark) - - protected var txtValue: TextView = view.findViewById(R.id.txtValue) - - - override fun bindView(item: CheckableValueAdapterItem, payloads: List) { - imgCheckmark.setVisibleOrInvisible(item.isChecked) - - txtValue.text = item.text - } - - override fun unbindView(item: CheckableValueAdapterItem) { - imgCheckmark.setImageURI(null) - - txtValue.text = null - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/DraggableBankAccountViewHolder.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/DraggableBankAccountViewHolder.kt deleted file mode 100644 index 0e33ab52..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/DraggableBankAccountViewHolder.kt +++ /dev/null @@ -1,23 +0,0 @@ -package net.dankito.banking.ui.android.adapter.viewholder - -import android.view.View -import android.widget.TextView -import com.mikepenz.fastadapter.FastAdapter -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.DraggableBankAccountAdapterItem - - -open class DraggableBankAccountViewHolder(view: View) : FastAdapter.ViewHolder(view) { - - protected var accountDisplayName: TextView = view.findViewById(R.id.txtBankDisplayName) - - - override fun bindView(item: DraggableBankAccountAdapterItem, payloads: List) { - accountDisplayName.text = item.account.displayName - } - - override fun unbindView(item: DraggableBankAccountAdapterItem) { - accountDisplayName.text = null - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/RecipientViewHolder.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/RecipientViewHolder.kt deleted file mode 100644 index 80ad493f..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/adapter/viewholder/RecipientViewHolder.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.dankito.banking.ui.android.adapter.viewholder - -import android.view.View -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.list_item_recipient.view.* - - -open class RecipientViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - - val txtvwRecipientName: TextView = itemView.txtvwRecipientName - - val txtvwRecipientBankName: TextView = itemView.txtvwRecipientBankName - - val txtvwRecipientAccountId: TextView = itemView.txtvwRecipientAccountId - - val txtvwRecipientBankCode: TextView = itemView.txtvwRecipientBankCode - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/alerts/AskDeleteAccountAlert.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/alerts/AskDeleteAccountAlert.kt deleted file mode 100644 index 61665151..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/alerts/AskDeleteAccountAlert.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.dankito.banking.ui.android.alerts - -import android.content.Context -import androidx.appcompat.app.AlertDialog -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.presenter.BankingPresenter - - -open class AskDeleteAccountAlert { - - open fun show(bank: TypedBankData, presenter: BankingPresenter, context: Context, accountDeleted: (() -> Unit)? = null) { - AlertDialog.Builder(context) - .setTitle(context.getString(R.string.alert_ask_delete_account_title)) - .setMessage(context.getString(R.string.alert_ask_delete_account_message, bank.displayName)) - .setPositiveButton(R.string.delete) { dialog, _ -> - presenter.deleteAccount(bank) - dialog.dismiss() - accountDeleted?.invoke() - } - .setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() } - .show() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/alerts/AskDismissChangesAlert.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/alerts/AskDismissChangesAlert.kt deleted file mode 100644 index 6e01711d..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/alerts/AskDismissChangesAlert.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.dankito.banking.ui.android.alerts - -import androidx.appcompat.app.AlertDialog -import androidx.fragment.app.DialogFragment -import net.dankito.banking.ui.android.R - - -open class AskDismissChangesAlert { - - open fun show(dialog: DialogFragment) { - val context = dialog.requireContext() - - AlertDialog.Builder(context) - .setTitle(context.getString(R.string.alert_ask_discard_changes_title)) - .setMessage(context.getString(R.string.alert_ask_discard_changes_message)) - .setPositiveButton(R.string.discard) { alert, _ -> - alert.dismiss() - dialog.dismiss() - } - .setNegativeButton(R.string.cancel) { alert, _ -> alert.dismiss() } - .show() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationResult.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationResult.kt deleted file mode 100644 index d6c8111d..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationResult.kt +++ /dev/null @@ -1,18 +0,0 @@ -package net.dankito.banking.ui.android.authentication - - -open class AuthenticationResult( - open val successful: Boolean, - open val error: String? = null -) { - - override fun toString(): String { - return if (successful) { - "Successful" - } - else { - "Error occurred: $error" - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationService.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationService.kt deleted file mode 100644 index a95624f5..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationService.kt +++ /dev/null @@ -1,305 +0,0 @@ -package net.dankito.banking.ui.android.authentication - -import android.content.Context -import android.util.Base64 -import at.favre.lib.crypto.bcrypt.BCrypt -import com.yakivmospan.scytale.Crypto -import com.yakivmospan.scytale.Options -import com.yakivmospan.scytale.Store -import net.dankito.banking.persistence.IBankingPersistence -import net.dankito.banking.ui.android.security.CryptographyManager -import net.dankito.banking.util.ISerializer -import net.dankito.utils.multiplatform.File -import net.dankito.utils.multiplatform.asString -import org.slf4j.LoggerFactory -import javax.crypto.Cipher -import javax.crypto.SecretKey - - -open class AuthenticationService( - protected open val applicationContext: Context, - protected open val biometricAuthenticationService: IBiometricAuthenticationService, - protected open val persistence: IBankingPersistence, - protected open val dataFolder: File, - protected open val serializer: ISerializer, - protected open val cryptographyManager: CryptographyManager = CryptographyManager() -) { - - companion object { - private const val AuthenticationSettingsFilename = "a" - - private const val AuthenticationSettingsFileKey = "AuthenticationSettingsFileKey" - - private val AuthenticationSettingsFileKeyPassword = "AuthenticationSettingsFileKeyAuthenticationSettingsFileKeyPassword".toCharArray() // TODO: store in a secure place - - private const val EncryptionKeyName = "BankingAndroidKey" - - private const val DefaultPasswordEncryptionKey = "AnyData" // TODO: store in a secure place - - private val log = LoggerFactory.getLogger(AuthenticationService::class.java) - } - - - open val isBiometricAuthenticationSupported: Boolean - get() = biometricAuthenticationService.supportsBiometricAuthentication - - open var authenticationType: AuthenticationType = AuthenticationType.None - protected set - - protected open var encryptionCipherForBiometric: Cipher? = null - - - init { - log.info("Initializing AuthenticationService (at the end database must get opened) ...") - - val settings = loadAuthenticationSettings() - - if (settings == null) { // first app run -> create a default password - removeAppProtection() - } - else { - authenticationType = settings.type - - if (settings.type == AuthenticationType.None) { - openDatabase(settings) - } - } - } - - - open fun loginUserWithPassword(enteredPassword: CharArray): Boolean { - if (isCorrectUserPassword(enteredPassword)) { - loadAuthenticationSettings()?.let { settings -> - return openDatabase(settings, enteredPassword) - } - } - - return false - } - - open fun isCorrectUserPassword(enteredPassword: CharArray): Boolean { - loadAuthenticationSettings()?.let { settings -> - val result = BCrypt.verifyer().verify(enteredPassword, settings.hashedUserPassword) - - return result.verified - } - - return false - } - - open fun authenticateUserWithBiometricToSetAsNewAuthenticationMethod(authenticationResult: (AuthenticationResult) -> Unit) { - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) { - authenticationResult(AuthenticationResult(false, "Biometric authentication is only supported on Android 6 and above")) - return - } - - val cipher = cryptographyManager.getInitializedCipherForEncryption(EncryptionKeyName) - - biometricAuthenticationService.authenticate(cipher) { result -> - if (result.successful) { - this.encryptionCipherForBiometric = cipher - } - - authenticationResult(result) - } - } - - open fun loginUserWithBiometric(result: (Boolean) -> Unit) { - // Biometric authentication is only supported on Android 6 and above - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) { - result(false) - return - } - - loadAuthenticationSettings()?.let { settings -> - val iv = decodeFromBase64(settings.initializationVector ?: "") - - val cipher = cryptographyManager.getInitializedCipherForDecryption(EncryptionKeyName, iv) - biometricAuthenticationService.authenticate(cipher) { authenticationResult -> - if (authenticationResult.successful) { - settings.defaultPassword?.let { - val encryptedUserPassword = decodeFromBase64(it) - val decrypted = cryptographyManager.decryptData(encryptedUserPassword, cipher) - - result(openDatabase(decrypted)) - } - } - else { - result(false) - } - } - } - ?: run { result(false) } - } - - protected open fun openDatabase(settings: AuthenticationSettings, userPassword: CharArray? = null): Boolean { - settings.defaultPassword?.let { encryptedPassword -> - settings.initializationVector?.let { iv -> - settings.salt?.let { salt -> - val defaultPassword = cryptographyManager.decryptDataWithPbe(decodeFromBase64(encryptedPassword), DefaultPasswordEncryptionKey, - decodeFromBase64(iv), decodeFromBase64(salt)) - - if (userPassword != null) { - return openDatabase(concatPasswords(userPassword, defaultPassword)) - } - else { - return openDatabase(defaultPassword) - } - } - } - } - - return false - } - - protected open fun openDatabase(password: CharArray): Boolean { - val result = persistence.decryptData(password) - - log.info("Did decrypting data / opening database succeed? $result") - - return result - } - - - open fun setAuthenticationMethodToBiometric() { - saveNewAuthenticationMethod(AuthenticationType.Biometric, null) - } - - open fun setAuthenticationMethodToPassword(newPassword: CharArray) { - saveNewAuthenticationMethod(AuthenticationType.Password, newPassword) - } - - open fun removeAppProtection() { - saveNewAuthenticationMethod(AuthenticationType.None, null) - } - - - protected open fun saveNewAuthenticationMethod(type: AuthenticationType, newUserPassword: CharArray?): Boolean { - val settings = loadOrCreateDefaultAuthenticationSettings() - val newDefaultPassword = generateRandomPassword() - var newDatabasePassword = newDefaultPassword - - settings.type = type - settings.hashedUserPassword = null - settings.initializationVector = null - settings.salt = null - - if (type == AuthenticationType.Biometric) { - encryptionCipherForBiometric?.let { encryptionCipher -> - val encryptedPassword = cryptographyManager.encryptData(newDefaultPassword, encryptionCipher) - settings.defaultPassword = encodeToBase64(encryptedPassword) - settings.initializationVector = encodeToBase64(encryptionCipher.iv) - } - } - else { - val salt = cryptographyManager.generateRandomBytes(8) - val (encryptedPassword, iv) = cryptographyManager.encryptDataWithPbe(newDefaultPassword, DefaultPasswordEncryptionKey, salt) - settings.defaultPassword = encodeToBase64(encryptedPassword) - settings.initializationVector = encodeToBase64(iv) - settings.salt = encodeToBase64(salt) - - if (newUserPassword != null) { - settings.hashedUserPassword = BCrypt.withDefaults().hashToString(6, newUserPassword) - newDatabasePassword = concatPasswords(newUserPassword, newDefaultPassword) - } - } - - if (persistence.changePassword(newDatabasePassword)) { - if (saveAuthenticationSettings(settings)) { - this.authenticationType = type - this.encryptionCipherForBiometric = null - - return true - } - } - - return false - } - - protected open fun concatPasswords(userPassword: CharArray, defaultPassword: CharArray): CharArray { - val concatenated = StringBuilder(userPassword.size + defaultPassword.size + 1) - - concatenated.append(userPassword) - concatenated.append("_") - concatenated.append(defaultPassword) - - return concatenated.toList().toCharArray() - } - - protected open fun loadOrCreateDefaultAuthenticationSettings(): AuthenticationSettings { - return loadAuthenticationSettings() ?: AuthenticationSettings(AuthenticationType.None) - } - - protected open fun loadAuthenticationSettings(): AuthenticationSettings? { - try { - val file = File(dataFolder, AuthenticationSettingsFilename) - - if (file.exists()) { - val (key, crypto) = getAuthenticationSettingsFileKey() - val encryptedJson = file.readText() - - val json = crypto.decrypt(encryptedJson, key) - - return serializer.deserializeObject(json, AuthenticationSettings::class) - } - } catch (e: Exception) { - log.error("Could not load AuthenticationSettings", e) - } - - return null - } - - protected open fun saveAuthenticationSettings(settings: AuthenticationSettings): Boolean { - try { - serializer.serializeObjectToString(settings)?.let { json -> - val (key, crypto) = getAuthenticationSettingsFileKey() - val encryptedJson = crypto.encrypt(json, key) - - val file = File(dataFolder, AuthenticationSettingsFilename) - - file.writeText(encryptedJson) - - return true - } - } catch (e: Exception) { - log.error("Could not save AuthenticationSettings", e) - } - - return false - } - - protected open fun getAuthenticationSettingsFileKey(): Pair { - val store = Store(applicationContext) - - val key = if (store.hasKey(AuthenticationSettingsFileKey)) store.getSymmetricKey(AuthenticationSettingsFileKey, AuthenticationSettingsFileKeyPassword) - else store.generateSymmetricKey(AuthenticationSettingsFileKey, AuthenticationSettingsFileKeyPassword) - - return Pair(key, Crypto(Options.TRANSFORMATION_SYMMETRIC)) - } - - - open fun generateRandomPassword(): CharArray { - return generateRandomPassword(30) - } - - open fun generateRandomPassword(passwordLength: Int): CharArray { - val dictionary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789§±!@#$%^&*-_=+;:|/?.>,<" - - val password = CharArray(passwordLength) - IntRange(0, passwordLength - 1).forEach { index -> - password[index] = dictionary.random() - } - - return password - } - - - open fun encodeToBase64(data: ByteArray): String { - return Base64.encodeToString(data, Base64.DEFAULT) - } - - open fun decodeFromBase64(data: String): ByteArray { - return Base64.decode(data, Base64.DEFAULT) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationSettings.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationSettings.kt deleted file mode 100644 index 1b490ad6..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationSettings.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.dankito.banking.ui.android.authentication - - -open class AuthenticationSettings( - open var type: AuthenticationType, - open var hashedUserPassword: String? = null, - open var defaultPassword: String? = null, - open var initializationVector: String? = null, - open var salt: String? = null -) { - - internal constructor() : this(AuthenticationType.None) // for object deserializers - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationType.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationType.kt deleted file mode 100644 index 578613a1..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/AuthenticationType.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.dankito.banking.ui.android.authentication - - -enum class AuthenticationType(internal val rawValue: Int) { - - None(3), - - Password(7), - - Biometric(9) - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/BiometricAuthenticationService.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/BiometricAuthenticationService.kt deleted file mode 100644 index 740f7d28..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/BiometricAuthenticationService.kt +++ /dev/null @@ -1,60 +0,0 @@ -package net.dankito.banking.ui.android.authentication - -import android.content.Context -import androidx.biometric.BiometricManager -import androidx.biometric.BiometricPrompt -import androidx.core.content.ContextCompat -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.util.CurrentActivityTracker -import javax.crypto.Cipher - - -open class BiometricAuthenticationService( - protected open val context: Context, - protected open val activityTracker: CurrentActivityTracker, - protected open val biometricManager: BiometricManager = BiometricManager.from(context) -) : IBiometricAuthenticationService { - - override val supportsBiometricAuthentication: Boolean - get() = biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS - - - override fun authenticate(cipher: Cipher?, authenticationResult: (AuthenticationResult) -> Unit) { - activityTracker.currentOrNextActivity { activity -> - val executor = ContextCompat.getMainExecutor(context) - - val biometricPrompt = BiometricPrompt(activity, executor, - object : BiometricPrompt.AuthenticationCallback() { - - override fun onAuthenticationError(errorCode: Int, errorString: CharSequence) { - super.onAuthenticationError(errorCode, errorString) - authenticationResult(AuthenticationResult(false, errorString.toString())) - } - - override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { - super.onAuthenticationSucceeded(result) - - authenticationResult(AuthenticationResult(true)) - } - - override fun onAuthenticationFailed() { - super.onAuthenticationFailed() - authenticationResult(AuthenticationResult(false)) - } - }) - - val promptInfo = BiometricPrompt.PromptInfo.Builder() - .setTitle(context.getString(R.string.activity_login_authenticate_with_biometrics_prompt)) - .setNegativeButtonText(context.getString(android.R.string.cancel)) - .build() - - if (cipher == null) { - biometricPrompt.authenticate(promptInfo) - } - else { - biometricPrompt.authenticate(promptInfo, BiometricPrompt.CryptoObject(cipher)) - } - } - - } -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/IBiometricAuthenticationService.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/IBiometricAuthenticationService.kt deleted file mode 100644 index 1b890988..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/authentication/IBiometricAuthenticationService.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.dankito.banking.ui.android.authentication - -import javax.crypto.Cipher - - -interface IBiometricAuthenticationService { - - val supportsBiometricAuthentication: Boolean - - - fun authenticate(cipher: Cipher? = null, authenticationResult: (AuthenticationResult) -> Unit) - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingComponent.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingComponent.kt deleted file mode 100644 index b0c88668..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingComponent.kt +++ /dev/null @@ -1,55 +0,0 @@ -package net.dankito.banking.ui.android.di - -import dagger.Component -import net.dankito.banking.ui.android.MainActivity -import net.dankito.banking.ui.android.activities.BaseActivity -import net.dankito.banking.ui.android.activities.LandingActivity -import net.dankito.banking.ui.android.activities.LoginActivity -import net.dankito.banking.ui.android.dialogs.AddAccountDialog -import net.dankito.banking.ui.android.dialogs.EnterTanDialog -import net.dankito.banking.ui.android.dialogs.SendMessageLogDialog -import net.dankito.banking.ui.android.dialogs.TransferMoneyDialog -import net.dankito.banking.ui.android.dialogs.settings.ProtectAppSettingsDialog -import net.dankito.banking.ui.android.dialogs.settings.SettingsDialog -import net.dankito.banking.ui.android.dialogs.settings.SettingsDialogBase -import net.dankito.banking.ui.android.home.HomeFragment -import net.dankito.banking.ui.android.views.BiometricAuthenticationButton -import javax.inject.Singleton - - -@Singleton -@Component(modules = arrayOf(BankingModule::class)) -interface BankingComponent { - - companion object { - lateinit var component: BankingComponent - } - - - fun inject(baseActivity: BaseActivity) - - fun inject(landingActivity: LandingActivity) - - fun inject(loginActivity: LoginActivity) - - fun inject(mainActivity: MainActivity) - - fun inject(homeFragment: HomeFragment) - - fun inject(addAccountDialog: AddAccountDialog) - - fun inject(enterTanDialog: EnterTanDialog) - - fun inject(transferMoneyDialog: TransferMoneyDialog) - - fun inject(settingsDialogBase: SettingsDialogBase) - - fun inject(settingsDialog: SettingsDialog) - - fun inject(protectAppSettingsDialog: ProtectAppSettingsDialog) - - fun inject(biometricAuthenticationButton: BiometricAuthenticationButton) - - fun inject(sendMessageLogDialog: SendMessageLogDialog) - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingModule.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingModule.kt deleted file mode 100644 index 277d91ed..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/di/BankingModule.kt +++ /dev/null @@ -1,209 +0,0 @@ -package net.dankito.banking.ui.android.di - -import android.content.Context -import androidx.appcompat.app.AppCompatActivity -import dagger.Module -import dagger.Provides -import net.dankito.utils.multiplatform.File -import net.dankito.banking.ui.android.RouterAndroid -import net.dankito.banking.ui.android.util.CurrentActivityTracker -import net.dankito.banking.fints4kBankingClientCreator -import net.dankito.banking.persistence.IBankingPersistence -import net.dankito.banking.search.ITransactionPartySearcher -import net.dankito.banking.ui.IBankingClientCreator -import net.dankito.banking.ui.IRouter -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.banking.bankfinder.IBankFinder -import net.dankito.banking.bankfinder.InMemoryBankFinder -import net.dankito.banking.bankfinder.LuceneBankFinder -import net.dankito.banking.persistence.RoomBankingPersistence -import net.dankito.banking.persistence.model.RoomModelCreator -import net.dankito.banking.ui.android.authentication.AuthenticationService -import net.dankito.banking.ui.android.authentication.BiometricAuthenticationService -import net.dankito.banking.ui.android.authentication.IBiometricAuthenticationService -import net.dankito.banking.ui.model.mapper.IModelCreator -import net.dankito.banking.ui.util.CurrencyInfoProvider -import net.dankito.utils.multiplatform.toFile -import net.dankito.banking.util.* -import net.dankito.banking.util.extraction.* -import net.dankito.text.extraction.TextExtractorRegistry -import net.dankito.text.extraction.pdf.PdfBoxAndroidPdfTextExtractor -import net.dankito.text.extraction.pdf.iText2PdfTextExtractor -import net.dankito.utils.ThreadPool -import net.dankito.utils.android.permissions.IPermissionsService -import net.dankito.utils.android.permissions.PermissionsService -import net.dankito.utils.web.client.IWebClient -import net.dankito.utils.web.client.OkHttpWebClient -import javax.inject.Named -import javax.inject.Singleton - - -@Module -class BankingModule(private val applicationContext: Context) { - - companion object { - - const val DataFolderKey = "data.folder" - - const val DatabaseFolderKey = "database.folder" - - const val IndexFolderKey = "index.folder" - - // TODO: implement activity listener to always get latest activity - lateinit var mainActivity: AppCompatActivity - } - - - @Provides - @Singleton - fun provideApplicationContext() : Context { - return applicationContext - } - - @Provides - @Singleton - @Named(DataFolderKey) - fun provideDataFolder(applicationContext: Context) : File { - return ensureFolderExists(applicationContext.filesDir.toFile(), "data") - } - - @Provides - @Singleton - @Named(DatabaseFolderKey) - fun provideDatabaseFolder(@Named(DataFolderKey) dataFolder: File) : File { - return ensureFolderExists(dataFolder, "db") - } - - @Provides - @Singleton - @Named(IndexFolderKey) - fun provideIndexFolder(@Named(DataFolderKey) dataFolder: File) : File { - return ensureFolderExists(dataFolder, "index") - } - - private fun ensureFolderExists(parentFolder: File, folderName: String): File { - val folder = File(parentFolder, folderName) - - folder.mkdirs() - - return folder - } - - - @Provides - @Singleton - fun providePermissionsService() : IPermissionsService { - return PermissionsService(mainActivity) - } - - - @Provides - @Singleton - fun provideAuthenticationService(biometricAuthenticationService: IBiometricAuthenticationService, persistence: IBankingPersistence, - @Named(DataFolderKey) dataFolder: File, serializer: ISerializer) : AuthenticationService { - return AuthenticationService(applicationContext, biometricAuthenticationService, persistence, dataFolder, serializer) - } - - @Provides - @Singleton - fun provideBiometricAuthenticationService(context: Context, currentActivityTracker: CurrentActivityTracker) : IBiometricAuthenticationService { - return BiometricAuthenticationService(context, currentActivityTracker) - } - - - @Provides - @Singleton - fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, bankFinder: IBankFinder, - @Named(DataFolderKey) dataFolder: File, - persister: IBankingPersistence, transactionPartySearcher: ITransactionPartySearcher, bankIconFinder: IBankIconFinder, - textExtractorRegistry: ITextExtractorRegistry, router: IRouter, invoiceDataExtractor: IInvoiceDataExtractor, - modelCreator: IModelCreator, asyncRunner: IAsyncRunner) : BankingPresenter { - return BankingPresenter(bankingClientCreator, bankFinder, dataFolder, persister, router, modelCreator, - transactionPartySearcher, bankIconFinder, textExtractorRegistry, invoiceDataExtractor, CurrencyInfoProvider(), asyncRunner) - } - - @Provides - @Singleton - fun provideBankFinder(@Named(IndexFolderKey) indexFolder: File) : IBankFinder { - //return LuceneBankFinder(indexFolder) // TODO: undo - return InMemoryBankFinder() - } - - @Provides - @Singleton - fun provideBankIconFinder() : IBankIconFinder { - return BankIconFinder() - } - - @Provides - @Singleton - fun provideBankingClientCreator(modelCreator: IModelCreator, serializer: ISerializer) : IBankingClientCreator { - return fints4kBankingClientCreator(modelCreator, serializer) - } - - @Provides - @Singleton - fun provideBankingPersistence() : IBankingPersistence { - return RoomBankingPersistence(applicationContext) - } - - @Provides - @Singleton - fun provideTransactionPartySearcher(bankingPersistence: IBankingPersistence) : ITransactionPartySearcher { - return bankingPersistence as RoomBankingPersistence - } - - @Provides - @Singleton - fun provideCurrentActivityTracker() : CurrentActivityTracker { - return CurrentActivityTracker() - } - - @Provides - @Singleton - fun provideRouter(currentActivityTracker: CurrentActivityTracker) : IRouter { - return RouterAndroid(currentActivityTracker) - } - - - @Provides - @Singleton - fun provideTextExtractorRegistry(applicationContext: Context) : ITextExtractorRegistry { - // TODO: add PdfTypeDetector - return JavaTextExtractorRegistry(TextExtractorRegistry(listOf( - iText2PdfTextExtractor(), PdfBoxAndroidPdfTextExtractor(applicationContext) - ))) - } - - @Provides - @Singleton - fun provideInvoiceDataExtractor() : IInvoiceDataExtractor { - return JavaInvoiceDataExtractor() - } - - - @Provides - @Singleton - fun provideWebClient() : IWebClient { - return OkHttpWebClient() - } - - @Provides - @Singleton - fun provideSerializer() : ISerializer { - return JacksonJsonSerializer() - } - - @Provides - @Singleton - fun provideModelCreator() : IModelCreator { - return RoomModelCreator() - } - - @Provides - @Singleton - fun provideAsyncRunner() : IAsyncRunner { - return ThreadPoolAsyncRunner(ThreadPool()) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/AccountTransactionDetailsDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/AccountTransactionDetailsDialog.kt deleted file mode 100644 index 4edff1b1..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/AccountTransactionDetailsDialog.kt +++ /dev/null @@ -1,80 +0,0 @@ -package net.dankito.banking.ui.android.dialogs - -import android.os.Bundle -import android.view.* -import androidx.fragment.app.FragmentActivity -import kotlinx.android.synthetic.main.dialog_account_transaction_details.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.dialogs.settings.SettingsDialogBase -import net.dankito.banking.ui.android.views.FormLabelledValue -import net.dankito.banking.ui.model.IAccountTransaction -import net.dankito.utils.multiplatform.BigDecimal - - -open class AccountTransactionDetailsDialog : SettingsDialogBase() { - - companion object { - const val DialogTag = "AccountTransactionDetailsDialog" - } - - - protected lateinit var transaction: IAccountTransaction - - - - fun show(transaction: IAccountTransaction, activity: FragmentActivity) { - this.transaction = transaction - - show(activity, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.dialog_account_transaction_details, container, false) - - setupUI(rootView) - - return rootView - } - - protected open fun setupUI(rootView: View) { - rootView.apply { - toolbar.apply { - setupToolbar(this, context.getString(R.string.dialog_account_transaction_details_title), false) - } - - sender_or_recipient_section_title.setTitle(if (transaction.amount.isPositive) R.string.dialog_account_transaction_details_sender else R.string.dialog_account_transaction_details_recipient) - lvlOtherPartyName.value = transaction.otherPartyName ?: "" - lvlOtherPartyAccountId.value = transaction.otherPartyAccountId ?: "" - lvlOtherPartyBankCode.value = transaction.otherPartyBankCode ?: "" - - lvlAmount.showAmount(presenter, transaction.amount, transaction.currency) - lvlReference.value = transaction.reference - - lvlBookingText.value = transaction.bookingText ?: "" - lvlBookingDate.value = presenter.formatToMediumDate(transaction.bookingDate) - lvlValueDate.value = presenter.formatToMediumDate(transaction.valueDate) - - showAmountIfSet(lvlOpeningBalance, transaction.openingBalance, transaction.account.currency) - showAmountIfSet(lvlClosingBalance, transaction.closingBalance, transaction.account.currency) - } - } - - protected open fun showAmountIfSet(labelledValue: FormLabelledValue, amount: BigDecimal?, currencyCode: String) { - if (amount != null) { - labelledValue.showAmount(presenter, amount, currencyCode) - } - else { - labelledValue.visibility = View.GONE - } - } - - - override val hasUnsavedChanges: Boolean - get() = false - - override fun saveChanges() { - - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/AddAccountDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/AddAccountDialog.kt deleted file mode 100644 index 39792b0d..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/AddAccountDialog.kt +++ /dev/null @@ -1,222 +0,0 @@ -package net.dankito.banking.ui.android.dialogs - -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.text.Editable -import android.text.TextWatcher -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.EditText -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.DialogFragment -import com.otaliastudios.autocomplete.Autocomplete -import kotlinx.android.synthetic.main.dialog_add_account.* -import kotlinx.android.synthetic.main.dialog_add_account.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.android.adapter.presenter.BankInfoPresenter -import net.dankito.banking.ui.android.extensions.addEnterPressedListener -import net.dankito.banking.ui.android.extensions.closePopupOnBackButtonPress -import net.dankito.banking.ui.android.util.StandardAutocompleteCallback -import net.dankito.banking.ui.model.responses.AddAccountResponse -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.banking.bankfinder.BankInfo -import net.dankito.banking.ui.android.util.StandardTextWatcher -import net.dankito.utils.android.extensions.asActivity -import net.dankito.utils.android.extensions.hide -import net.dankito.utils.android.extensions.show -import net.dankito.utils.android.extensions.showKeyboardDelayed -import javax.inject.Inject - - -open class AddAccountDialog : DialogFragment() { - - companion object { - const val DialogTag = "AddAccountDialog" - } - - - protected var selectedBank: BankInfo? = null - - protected var justDidSelectBank: Boolean = false - - - @Inject - protected lateinit var presenter: BankingPresenter - - - init { - BankingComponent.component.inject(this) - } - - - fun show(activity: AppCompatActivity, fullscreen: Boolean = true) { - val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog - setStyle(STYLE_NORMAL, style) - - show(activity.supportFragmentManager, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.dialog_add_account, container, false) - - rootView?.let { - setupUI(rootView) - } - - return rootView - } - - protected open fun setupUI(rootView: View) { - rootView.apply { - initBankListAutocompletion(edtxtBank.actualEditText) - - edtxtUserName.actualEditText.addTextChangedListener(otherEditTextChangedWatcher) - bankCredentialsPassword.passwordBox.addTextChangedListener(otherEditTextChangedWatcher) - - addAccountIfEnterPressed(edtxtBank.actualEditText) - addAccountIfEnterPressed(edtxtUserName.actualEditText) - addAccountIfEnterPressed(bankCredentialsPassword.passwordBox) - - btnAddAccount.setOnClickListener { addAccount() } - btnCancel.setOnClickListener { dismiss() } - - edtxtBank.actualEditText.showKeyboardDelayed(250) - } - } - - private fun initBankListAutocompletion(edtxtBank: EditText) { - edtxtBank.addTextChangedListener(StandardTextWatcher { - mayClearSelectedBank() - }) - - val autocompleteCallback = StandardAutocompleteCallback { _, item -> - bankSelected(item) - true - } - - Autocomplete.on(edtxtBank) - .with(6f) - .with(ColorDrawable(Color.WHITE)) - .with(autocompleteCallback) - .with(BankInfoPresenter(presenter, edtxtBank.context)) - .build() - .closePopupOnBackButtonPress(dialog) - } - - private fun addAccountIfEnterPressed(editText: EditText) { - editText.addEnterPressedListener { - if (btnAddAccount.isEnabled) { // required data has been entered - addAccount() - - return@addEnterPressedListener true - } - - false - } - } - - - protected open fun addAccount() { - selectedBank?.let { selectedBank -> // should always be non-null at this stage - val userName = edtxtUserName.text - val password = bankCredentialsPassword.password - - btnAddAccount.isEnabled = false - pgrbrAddAccount.show() - - presenter.addAccountAsync(selectedBank, userName, password) { response -> - context?.asActivity()?.runOnUiThread { - btnAddAccount.isEnabled = true - pgrbrAddAccount.hide() - - handleAccountCheckResponseOnUiThread(response) - } - } - } - } - - protected open fun handleAccountCheckResponseOnUiThread(response: AddAccountResponse) { - context?.let { context -> - if (response.successful) { - this.dismiss() - } - else { - AlertDialog.Builder(context) - .setMessage(context.getString(R.string.dialog_add_account_message_could_not_add_account, response.errorToShowToUser)) - .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - } - } - - - protected val otherEditTextChangedWatcher = object : TextWatcher { - - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } - - override fun onTextChanged(enteredText: CharSequence?, start: Int, before: Int, count: Int) { - checkIfRequiredDataEnteredOnUiThread() - } - - override fun afterTextChanged(s: Editable?) { } - - } - - protected open fun bankSelected(bank: BankInfo) { - val didSelectSupportedBank = bank.supportsFinTs3_0 - - selectedBank = if (didSelectSupportedBank) bank else null - - justDidSelectBank = true - - if (didSelectSupportedBank) { - edtxtBank.text = bank.bankCode + " " + bank.name - } - - justDidSelectBank = false - - checkIfRequiredDataEnteredOnUiThread() - - if (didSelectSupportedBank) { - edtxtUserName.requestFocus() - } - else { - showBankDoesNotSupportFinTs30ErrorMessage(bank) - edtxtBank.actualEditText.selectAll() - } - } - - protected open fun mayClearSelectedBank() { - if (justDidSelectBank == false) { - selectedBank = null - } - - checkIfRequiredDataEnteredOnUiThread() - } - - private fun showBankDoesNotSupportFinTs30ErrorMessage(bank: BankInfo) { - activity?.let { context -> - val errorMessage = context.getString(R.string.dialog_add_account_bank_does_not_support_fints_3_error_message, bank.name) - - AlertDialog.Builder(context) - .setMessage(errorMessage) - .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - } - - protected open fun checkIfRequiredDataEnteredOnUiThread() { - val requiredDataEntered = selectedBank != null - && selectedBank?.supportsFinTs3_0 == true - && edtxtUserName.text.isNotEmpty() - && bankCredentialsPassword.password.isNotEmpty() - - btnAddAccount.isEnabled = requiredDataEntered - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterAtcDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterAtcDialog.kt deleted file mode 100644 index ba1ea367..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterAtcDialog.kt +++ /dev/null @@ -1,91 +0,0 @@ -package net.dankito.banking.ui.android.dialogs - -import android.os.Bundle -import android.text.Html -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.DialogFragment -import kotlinx.android.synthetic.main.dialog_enter_atc.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.model.tan.EnterTanGeneratorAtcResult -import net.dankito.banking.ui.model.tan.TanMedium -import net.dankito.utils.android.extensions.getSpannedFromHtml - - -open class EnterAtcDialog : DialogFragment() { - - companion object { - const val DialogTag = "EnterAtcDialog" - } - - - protected lateinit var tanMedium: TanMedium - - protected lateinit var atcEnteredCallback: (EnterTanGeneratorAtcResult) -> Unit - - - open fun show(tanMedium: TanMedium, activity: AppCompatActivity, - fullscreen: Boolean = false, atcEnteredCallback: (EnterTanGeneratorAtcResult) -> Unit) { - - this.tanMedium = tanMedium - this.atcEnteredCallback = atcEnteredCallback - - val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog - setStyle(STYLE_NORMAL, style) - - show(activity.supportFragmentManager, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.dialog_enter_atc, container, false) - - setupUI(rootView) - - return rootView - } - - protected open fun setupUI(rootView: View) { - val explanationHtml = rootView.context.getString(R.string.dialog_enter_atc_explanation, tanMedium.displayName) - rootView.txtAtcExplanationToShowToUser.text = explanationHtml.getSpannedFromHtml() - - rootView.btnCancel.setOnClickListener { enteringAtcDone(null, null) } - - rootView.btnEnteringAtcDone.setOnClickListener { enteringAtcDone(rootView.edtxtEnteredTan.text.toString(), rootView.edtxtEnteredAtc.text.toString()) } - } - - - protected open fun enteringAtcDone(enteredTan: String?, enteredAtcString: String?) { - var enteredAtc: Int? = null - - if (enteredAtcString != null) { - try { - enteredAtc = enteredAtcString.toInt() - } catch (e: Exception) { - showEnteredAtcIsNotANumberError(enteredAtcString) - - return - } - } - - val result = if (enteredTan == null || enteredAtc == null) EnterTanGeneratorAtcResult.userDidNotEnterAtc() - else EnterTanGeneratorAtcResult.userEnteredAtc(enteredTan, enteredAtc) - - atcEnteredCallback(result) - - dismiss() - } - - protected open fun showEnteredAtcIsNotANumberError(enteredAtcString: String) { - activity?.let { context -> - AlertDialog.Builder(context) - .setMessage(context.getString(R.string.dialog_enter_atc_error_entered_atc_is_not_a_number, enteredAtcString)) - .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterTanDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterTanDialog.kt deleted file mode 100644 index 9685bc36..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/EnterTanDialog.kt +++ /dev/null @@ -1,272 +0,0 @@ -package net.dankito.banking.ui.android.dialogs - -import android.content.Context -import android.os.Bundle -import android.os.Handler -import android.text.InputFilter -import android.text.InputType -import android.view.KeyEvent -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.Spinner -import androidx.appcompat.app.AlertDialog -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.FragmentActivity -import kotlinx.android.synthetic.main.dialog_enter_tan.* -import kotlinx.android.synthetic.main.dialog_enter_tan.view.* -import kotlinx.android.synthetic.main.view_collapsible_text.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.TanMediumAdapter -import net.dankito.banking.ui.android.adapter.TanMethodsAdapter -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.android.listener.ListItemSelectedListener -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.model.responses.BankingClientResponse -import net.dankito.banking.ui.model.tan.* -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.utils.android.extensions.getSpannedFromHtml -import net.dankito.utils.android.extensions.show -import javax.inject.Inject - - -open class EnterTanDialog : DialogFragment() { - - companion object { - const val DialogTag = "EnterTanDialog" - } - - - protected lateinit var bank: TypedBankData - - protected lateinit var tanChallenge: TanChallenge - - protected lateinit var tanEnteredCallback: (EnterTanResult) -> Unit - - protected val tanMediumAdapter = TanMediumAdapter() - - - @Inject - protected lateinit var presenter: BankingPresenter - - - init { - BankingComponent.component.inject(this) - } - - - open fun show(bank: TypedBankData, tanChallenge: TanChallenge, activity: FragmentActivity, - fullscreen: Boolean = false, tanEnteredCallback: (EnterTanResult) -> Unit) { - - this.bank = bank - this.tanChallenge = tanChallenge - this.tanEnteredCallback = tanEnteredCallback - - val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog - setStyle(STYLE_NORMAL, style) - - show(activity.supportFragmentManager, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.dialog_enter_tan, container, false) - - setupUI(rootView) - - return rootView - } - - protected open fun setupUI(rootView: View) { - setupSelectTanMethodView(rootView) - - setupTanView(rootView) - - setupEnteringTan(rootView) - - rootView.txtvwCollapsibleText.text = tanChallenge.messageToShowToUser.getSpannedFromHtml() - - rootView.btnCancel.setOnClickListener { enteringTanDone(null) } - - rootView.btnEnteringTanDone.setOnClickListener { enteringTanDone(rootView.edtxtEnteredTan.text.toString()) } - } - - protected open fun setupSelectTanMethodView(rootView: View) { - val adapter = TanMethodsAdapter() - val tanMethodsWithoutUnsupported = bank.supportedTanMethods.filterNot { it.type == TanMethodType.ChipTanUsb } // USB tan generators are not supported on Android - adapter.setItems(tanMethodsWithoutUnsupported) - - rootView.findViewById(R.id.spnTanMethods)?.let { spinner -> - spinner.adapter = adapter - - val selectedTanMethod = bank.selectedTanMethod - ?: tanMethodsWithoutUnsupported.firstOrNull { it.type != TanMethodType.ChipTanManuell && it.type != TanMethodType.ChipTanUsb } - ?: tanMethodsWithoutUnsupported.firstOrNull() - selectedTanMethod?.let { spinner.setSelection(adapter.getItems().indexOf(selectedTanMethod)) } - - spinner.onItemSelectedListener = ListItemSelectedListener(adapter) { newSelectedTanMethod -> - if (newSelectedTanMethod != selectedTanMethod) { - tanEnteredCallback(EnterTanResult.userAsksToChangeTanMethod(newSelectedTanMethod)) - // TODO: find a way to update account.selectedTanMethod afterwards - - dismiss() - } - } - } - } - - protected open fun setupSelectTanMediumView(rootView: View) { - val tanMediaForTanMethod = presenter.getTanMediaForTanMethod(bank, tanChallenge.tanMethod) - - if (tanMediaForTanMethod.size > 1) { - rootView.lytTanMedium.show() - - tanMediumAdapter.setItems(bank.tanMediaSorted) - - rootView.spnTanMedium.adapter = tanMediumAdapter - rootView.spnTanMedium.onItemSelectedListener = ListItemSelectedListener(tanMediumAdapter) { selectedTanMedium -> - // TODO: implement logic to change a mobile phone as TAN medium - if (selectedTanMedium.status != TanMediumStatus.Used) { - (selectedTanMedium as? TanGeneratorTanMedium)?.let { tanGeneratorTanMedium -> - tanEnteredCallback(EnterTanResult.userAsksToChangeTanMedium(tanGeneratorTanMedium) { response -> - handleChangeTanMediumResponse(selectedTanMedium, response) - }) - // TODO: find a way to update account.tanMedia afterwards - } - - // TODO: ensure that only TanGeneratorTanMedium instances get added to spinner? - } - } - } - } - - protected open fun setupTanView(rootView: View) { - if (presenter.isOpticalTanMethod(tanChallenge.tanMethod)) { - setupSelectTanMediumView(rootView) - - if (tanChallenge is FlickerCodeTanChallenge) { - setupFlickerCodeTanView(rootView) - } - else if (tanChallenge is ImageTanChallenge) { - setupImageTanView(rootView) - } - } - } - - protected open fun setupEnteringTan(rootView: View) { - if (tanChallenge.tanMethod.isNumericTan) { - rootView.edtxtEnteredTan.inputType = InputType.TYPE_CLASS_NUMBER - } - - tanChallenge.tanMethod.maxTanInputLength?.let { maxInputLength -> - rootView.edtxtEnteredTan.filters = arrayOf(InputFilter.LengthFilter(maxInputLength)) - } - - rootView.edtxtEnteredTan.setOnKeyListener { _, keyCode, _ -> - if (keyCode == KeyEvent.KEYCODE_ENTER) { - enteringTanDone(rootView.edtxtEnteredTan.text.toString()) - return@setOnKeyListener true - } - false - } - } - - protected open fun setupFlickerCodeTanView(rootView: View) { - val flickerCodeView = rootView.flickerCodeView - flickerCodeView.show() - - val flickerCode = (tanChallenge as FlickerCodeTanChallenge).flickerCode - if (flickerCode.decodingSuccessful) { - flickerCodeView.setCode(flickerCode, presenter.appSettings.flickerCodeSettings) - } - else { - showDecodingTanChallengeFailedErrorDelayed(flickerCode.decodingError) - } - } - - protected open fun setupImageTanView(rootView: View) { - rootView.tanImageView.show() - - val decodedImage = (tanChallenge as ImageTanChallenge).image - if (decodedImage.decodingSuccessful) { - rootView.tanImageView.setImage(tanChallenge as ImageTanChallenge, if (isQrTan(tanChallenge)) presenter.appSettings.qrCodeSettings else presenter.appSettings.photoTanSettings) - } - else { - showDecodingTanChallengeFailedErrorDelayed(decodedImage.decodingError) - } - } - - - /** - * This method gets called right on start up before dialog is shown -> Alert would get displayed before dialog and - * therefore covered by dialog -> delay displaying alert. - */ - protected open fun showDecodingTanChallengeFailedErrorDelayed(error: Exception?) { - val handler = Handler() - - handler.postDelayed({ showDecodingTanChallengeFailedError(error) }, 500) - } - - protected open fun showDecodingTanChallengeFailedError(error: Exception?) { - activity?.let { context -> - AlertDialog.Builder(context) - .setMessage(context.getString(R.string.dialog_enter_tan_error_could_not_decode_tan_image, error?.localizedMessage)) - .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - } - - - protected open fun handleChangeTanMediumResponse(newUsedTanMedium: TanMedium, response: BankingClientResponse) { - activity?.let { activity -> - activity.runOnUiThread { - handleChangeTanMediumResponseOnUiThread(activity, newUsedTanMedium, response) - } - } - } - - protected open fun handleChangeTanMediumResponseOnUiThread(context: Context, newUsedTanMedium: TanMedium, response: BankingClientResponse) { - if (response.successful) { - AlertDialog.Builder(context) - .setMessage(context.getString(R.string.dialog_enter_tan_tan_medium_successfully_changed, newUsedTanMedium.displayName)) - .setPositiveButton(android.R.string.ok) { dialog, _ -> - dialog.dismiss() - dismiss() - } - .show() - } - else if (response.userCancelledAction == false) { - AlertDialog.Builder(context) - .setMessage(context.getString(R.string.dialog_enter_tan_error_changing_tan_medium, newUsedTanMedium.displayName, response.errorToShowToUser)) - .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - } - - - protected open fun enteringTanDone(enteredTan: String?) { - val result = if (enteredTan != null) EnterTanResult.userEnteredTan(enteredTan) else EnterTanResult.userDidNotEnterTan() - - tanEnteredCallback(result) - - checkIfAppSettingsChanged() - - dismiss() - } - - - protected open fun checkIfAppSettingsChanged() { - if (flickerCodeView.didTanMethodSettingsChange) { - presenter.updateTanMethodSettings(tanChallenge.tanMethod, flickerCodeView.tanMethodSettings) - } - - if (tanImageView.didTanMethodSettingsChange) { - presenter.updateTanMethodSettings(tanChallenge.tanMethod, tanImageView.tanMethodSettings) - } - } - - protected open fun isQrTan(tanChallenge: TanChallenge): Boolean { - return presenter.isQrTanMethod(tanChallenge.tanMethod) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/SendMessageLogDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/SendMessageLogDialog.kt deleted file mode 100644 index fad45448..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/SendMessageLogDialog.kt +++ /dev/null @@ -1,165 +0,0 @@ -package net.dankito.banking.ui.android.dialogs - -import android.content.ActivityNotFoundException -import android.content.Intent -import android.os.Build -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.DialogFragment -import kotlinx.android.synthetic.main.dialog_send_message_log.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.utils.android.extensions.hide -import net.dankito.utils.android.extensions.show -import net.dankito.utils.multiplatform.getInnerExceptionMessage -import net.dankito.utils.multiplatform.os.DeviceInfo -import net.dankito.banking.ui.model.issues.CreateTicketRequestDto -import net.dankito.banking.ui.model.issues.IssueDescriptionFormat -import net.dankito.utils.android.extensions.asActivity -import net.dankito.utils.serialization.JacksonJsonSerializer -import net.dankito.utils.web.client.OkHttpWebClient -import net.dankito.utils.web.client.RequestParameters -import net.dankito.utils.web.client.WebClientResponse -import javax.inject.Inject - - -open class SendMessageLogDialog : DialogFragment() { - - companion object { - const val DialogTag = "SendMessageLogDialog" - } - - - @Inject - protected lateinit var presenter: BankingPresenter - - - init { - BankingComponent.component.inject(this) - } - - - fun show(activity: AppCompatActivity, fullscreen: Boolean = true) { - val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog - setStyle(STYLE_NORMAL, style) - - show(activity.supportFragmentManager, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.dialog_send_message_log, container, false) - - rootView?.let { - setupUI(rootView) - } - - return rootView - } - - protected open fun setupUI(rootView: View) { - val messageLog = presenter.getFormattedMessageLogForAccounts(presenter.allBanksSortedByDisplayIndex) - - if (messageLog.isBlank()) { - rootView.txtvwInfoNoMessageLogEntriesYet.show() - rootView.lytMessageLog.hide() - - rootView.btnSendMessageLogDirectly.isEnabled = false - rootView.btnSendMessageLogViaEMail.isEnabled = false - } - else { - rootView.edtxtMessageLog.setText(context?.getString(R.string.dialog_send_message_courteously_add_error_description, getDeviceInfoLine() + "\n\n" + messageLog)) - } - - rootView.btnSendMessageLogDirectly.setOnClickListener { sendMessageLogDirectly(rootView.edtxtMessageLog.text.toString()) } - rootView.btnSendMessageLogViaEMail.setOnClickListener { sendMessageLogViaEMail(rootView.edtxtMessageLog.text.toString()) } - - rootView.btnCancel.setOnClickListener { dismiss() } - } - - protected open fun sendMessageLogViaEMail(messageLog: String) { - // TODO: check if message log exceeds 120.000 characters - - val sendMailActivity = Intent(Intent.ACTION_SEND) - sendMailActivity.type = "message/rfc822" - sendMailActivity.putExtra(Intent.EXTRA_EMAIL, arrayOf("issues@bankmeister.de")) - sendMailActivity.putExtra(Intent.EXTRA_SUBJECT, context?.getString(R.string.dialog_send_message_log_mail_subject)) - sendMailActivity.putExtra(Intent.EXTRA_TEXT, messageLog) - - try { - startActivity(Intent.createChooser(sendMailActivity, context?.getString(R.string.dialog_send_message_log_action_send_chooser_title))) - - showSuccessfullySentMessageLog() - } catch (e: ActivityNotFoundException) { - Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_error_no_app_to_send_message_found), Toast.LENGTH_LONG).show() - } - } - - protected open fun sendMessageLogDirectly(messageLog: String) { - val deviceInfo = getDeviceInfo() - - // TODO: sending with Ktor did not work - //presenter.sendMessageLogDirectly(messageLog, deviceInfo) - - val requestBodyDto = CreateTicketRequestDto(messageLog, "Bankmeister", IssueDescriptionFormat.PlainText, - deviceInfo.osName, deviceInfo.osVersion, deviceInfo.manufacturer, deviceInfo.deviceModel) - val requestBody = JacksonJsonSerializer().serializeObject(requestBodyDto) - - OkHttpWebClient().postAsync(RequestParameters("https://codinux.uber.space/issues", requestBody, "application/json")) { response -> - context?.asActivity()?.runOnUiThread { - handleSendMessageLogDirectlyResponseOnUiThread(response) - } - } - } - - protected open fun getDeviceInfoLine(): String { - val deviceInfo = getDeviceInfo() - - var line = deviceInfo.manufacturer ?: "" - - deviceInfo.deviceModel?.let { model -> - line += (if (line.isEmpty()) "" else " ") + model - } - - deviceInfo.osName?.let { osName -> - line += (if (line.isEmpty()) "" else " - ") + osName - } - - deviceInfo.osVersion?.let { osVersion -> - line += (if (line.isEmpty()) "" else " ") + osVersion - } - - deviceInfo.osArch?.let { osArch -> - line += (if (line.isEmpty()) "" else " ") + osArch - } - - return line - - } - - protected open fun getDeviceInfo(): DeviceInfo { - return DeviceInfo(Build.MANUFACTURER.capitalize(), Build.MODEL, "Android", Build.VERSION.RELEASE, System.getProperty("os.arch") ?: "") - } - - protected open fun handleSendMessageLogDirectlyResponseOnUiThread(response: WebClientResponse) { - if (response.isSuccessResponse) { - showSuccessfullySentMessageLog() - } - else { - Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_error_could_not_sent_message_log, response.error?.getInnerExceptionMessage()), - Toast.LENGTH_LONG).show() - } - } - - protected open fun showSuccessfullySentMessageLog() { - Toast.makeText(context, context?.getString(R.string.dialog_send_message_log_thanks_for_helping_making_app_better), Toast.LENGTH_LONG).show() - - dismiss() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/TransferMoneyDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/TransferMoneyDialog.kt deleted file mode 100644 index cf979ad3..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/TransferMoneyDialog.kt +++ /dev/null @@ -1,485 +0,0 @@ -package net.dankito.banking.ui.android.dialogs - -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.text.TextWatcher -import android.text.method.DigitsKeyListener -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.* -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.DialogFragment -import com.google.android.material.textfield.TextInputLayout -import com.otaliastudios.autocomplete.Autocomplete -import kotlinx.android.synthetic.main.dialog_transfer_money.* -import kotlinx.android.synthetic.main.dialog_transfer_money.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.android.adapter.IconedBankAccountsAdapter -import net.dankito.banking.ui.android.adapter.presenter.RecipientPresenter -import net.dankito.banking.ui.android.extensions.addEnterPressedListener -import net.dankito.banking.ui.android.extensions.closePopupOnBackButtonPress -import net.dankito.banking.ui.android.listener.ListItemSelectedListener -import net.dankito.banking.ui.android.util.StandardAutocompleteCallback -import net.dankito.banking.ui.android.util.StandardTextWatcher -import net.dankito.banking.search.TransactionParty -import net.dankito.banking.ui.model.TypedBankAccount -import net.dankito.banking.ui.model.parameters.TransferMoneyData -import net.dankito.banking.ui.model.responses.BankingClientResponse -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.banking.util.InputValidator -import net.dankito.banking.bankfinder.BankInfo -import net.dankito.banking.ui.android.extensions.isEllipsized -import net.dankito.banking.ui.android.views.InfoPopupWindow -import net.dankito.banking.util.ValidationResult -import net.dankito.utils.android.extensions.* -import net.dankito.utils.multiplatform.toBigDecimal -import java.math.BigDecimal -import java.text.DecimalFormatSymbols -import java.util.* -import javax.inject.Inject -import kotlin.concurrent.schedule - - -open class TransferMoneyDialog : DialogFragment() { - - companion object { - const val DialogTag = "TransferMoneyDialog" - } - - - protected lateinit var account: TypedBankAccount - - protected var preselectedValues: TransferMoneyData? = null - - protected val inputValidator = InputValidator() // TODO: move to presenter - - - protected var recipientBic: String? = null - - - protected var validRecipientNameEntered = false - - protected var validRecipientIbanEntered = false - - protected var validRecipientBicEntered = false - - protected var validReferenceEntered = true - - protected var validAmountEntered = false - - protected var didJustCorrectInput = mutableMapOf() - - - @Inject - protected lateinit var presenter: BankingPresenter - - - init { - BankingComponent.component.inject(this) - } - - open fun show(activity: AppCompatActivity, fullscreen: Boolean = true) { - show(activity, null, fullscreen) - } - - open fun show(activity: AppCompatActivity, preselectedValues: TransferMoneyData?, fullscreen: Boolean = true) { - this.preselectedValues = preselectedValues - - val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog - setStyle(STYLE_NORMAL, style) - - show(activity.supportFragmentManager, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.dialog_transfer_money, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - setupUI(view) - } - - protected open fun setupUI(rootView: View) { - val accountsSupportingTransferringMoney = presenter.accountsSupportingTransferringMoneySortedByDisplayIndex - account = preselectedValues?.account ?: accountsSupportingTransferringMoney.first() - - if (accountsSupportingTransferringMoney.size > 1) { - rootView.lytSelectBankAccount.show() - - val adapter = IconedBankAccountsAdapter(accountsSupportingTransferringMoney) - rootView.spnBankAccounts.adapter = adapter - rootView.spnBankAccounts.onItemSelectedListener = ListItemSelectedListener(adapter) { selectedBankAccount -> - this.account = selectedBankAccount - setRealTimeTransferControlsVisibility(rootView) - } - preselectedValues?.account?.let { rootView.spnBankAccounts.setSelection(adapter.getItems().indexOf(it)) } - } - - initRecipientAutocompletion(rootView.edtxtRecipientName) - - rootView.edtxtRecipientName.addTextChangedListener(checkRequiredDataWatcher { - checkIfEnteredRecipientNameIsValidWhileUserIsTyping() - }) - - rootView.edtxtRecipientIban.addTextChangedListener(StandardTextWatcher { - checkIfEnteredRecipientIbanIsValidWhileUserIsTyping() - tryToGetBicFromIban(it) - }) - - rootView.edtxtAmount.addTextChangedListener(checkRequiredDataWatcher { - checkIfEnteredAmountIsValid() - }) - rootView.edtxtReference.addTextChangedListener(checkRequiredDataWatcher { - checkIfEnteredReferenceTextIsValid() - }) - - rootView.edtxtRecipientName.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredRecipientNameIsValidAfterFocusLost() } - rootView.edtxtRecipientIban.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredRecipientIbanIsValidAfterFocusLost() } - rootView.edtxtAmount.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredAmountIsValid() } - rootView.edtxtReference.setOnFocusChangeListener { _, hasFocus -> if (hasFocus == false) checkIfEnteredReferenceTextIsValid() } - - transferMoneyIfEnterPressed(rootView.edtxtRecipientName) - transferMoneyIfEnterPressed(rootView.edtxtRecipientIban) - transferMoneyIfEnterPressed(rootView.edtxtAmount) - transferMoneyIfEnterPressed(rootView.edtxtReference) - - rootView.btnShowRealTimeTransferInfo.setOnClickListener { showRealTimeTransferInfo(rootView.btnShowRealTimeTransferInfo) } - - setRealTimeTransferControlsVisibility(rootView) - - rootView.btnCancel.setOnClickListener { dismiss() } - - rootView.btnTransferMoney.setOnClickListener { transferMoney() } - - adjustCheckBoxRealTimeTransferWidth() - } - - - protected open fun adjustCheckBoxRealTimeTransferWidth() { - // wait some time till CheckBox is layout and lineCount is set - val timer = Timer() - timer.schedule(10) { activity?.runOnUiThread { adjustCheckBoxRealTimeTransferWidthOnUiThread() }} - timer.schedule(2500) { activity?.runOnUiThread { adjustCheckBoxRealTimeTransferWidthOnUiThread() }} - } - - protected open fun adjustCheckBoxRealTimeTransferWidthOnUiThread() { - if (chkbxRealTimeTransfer.isEllipsized == false) { - // by default chkbxRealTimeTransfer uses full width, even though if its text doesn't need this space -> there - chkbxRealTimeTransfer.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 0f) - chkbxRealTimeTransfer.requestLayout() - } - } - - protected open fun setRealTimeTransferControlsVisibility(rootView: View) { - rootView.lytRealTimeTransfer.setVisibility(account.supportsRealTimeTransfer) - } - - protected open fun showRealTimeTransferInfo(btnShowRealTimeTransferInfo: ImageButton) { - activity?.let { activity -> - InfoPopupWindow(activity, R.string.dialog_transfer_money_real_time_transfer_info) - .show(btnShowRealTimeTransferInfo) - } - } - - private fun transferMoneyIfEnterPressed(editText: EditText) { - editText.addEnterPressedListener { - if (isRequiredDataEntered()) { - transferMoney() - - return@addEnterPressedListener true - } - - false - } - } - - private fun isRequiredDataEntered() = btnTransferMoney.isEnabled - - private fun initRecipientAutocompletion(edtxtRecipientName: EditText) { - val autocompleteCallback = StandardAutocompleteCallback { _, item -> - recipientSelected(item) - true - } - - Autocomplete.on(edtxtRecipientName) - .with(6f) - .with(ColorDrawable(Color.WHITE)) - .with(autocompleteCallback) - .with(RecipientPresenter(presenter, edtxtRecipientName.context)) - .build() - .closePopupOnBackButtonPress(dialog) - } - - - override fun onStart() { - super.onStart() - - setPreselectedValues() - - if (recipientBic != null) { - tryToGetBicFromIban(edtxtRecipientIban.text.toString()) - } - } - - - protected open fun setPreselectedValues() { - preselectedValues?.let { data -> - preselectedValues = null - - edtxtRecipientName.setText(data.recipientName) - - if (data.recipientAccountId.isNotBlank()) { // set only if recipientAccountId has a value as otherwise recipientBankCode would be overridden by empty search result - edtxtRecipientIban.setText(data.recipientAccountId) - } - - // a little bit inconsistent as if IBAN is not set bank's name won't be displayed even though it can be retrieved by BIC - recipientBic = data.recipientBankCode - - if (data.amount > BigDecimal.ZERO) { - edtxtAmount.setText(data.amount.toString()) - } - - edtxtReference.setText(data.reference) - - focusEditTextAccordingToPreselectedValues() - } - } - - protected open fun focusEditTextAccordingToPreselectedValues() { - when { - edtxtRecipientName.text.toString().isBlank() -> edtxtRecipientName.requestFocus() - edtxtRecipientIban.text.toString().isBlank() -> edtxtRecipientIban.requestFocus() - edtxtAmount.text.toString().isBlank() -> edtxtAmount.requestFocus() - edtxtReference.text.toString().isBlank() -> edtxtReference.requestFocus() - else -> edtxtReference.requestFocus() - } - } - - - protected open fun recipientSelected(item: TransactionParty) { - edtxtRecipientName.setText(item.name) - edtxtRecipientIban.setText(item.iban) - recipientBic = item.bic - - focusEditTextAccordingToPreselectedValues() - } - - protected open fun transferMoney() { - getEnteredAmount()?.let { amount -> // should only come at this stage when a valid amount has been entered - val data = TransferMoneyData( - account, - inputValidator.convertToAllowedSepaCharacters(edtxtRecipientName.text.toString()), - edtxtRecipientIban.text.toString().replace(" ", ""), - recipientBic?.replace(" ", "") ?: "", // should always be != null at this point - amount.toBigDecimal(), - inputValidator.convertToAllowedSepaCharacters(edtxtReference.text.toString()), - chkbxRealTimeTransfer.isChecked - ) - - presenter.transferMoneyAsync(data) { - context?.asActivity()?.runOnUiThread { - handleTransferMoneyResultOnUiThread(data, it) - } - } - } - } - - protected open fun handleTransferMoneyResultOnUiThread(transferData: TransferMoneyData, response: BankingClientResponse) { - context?.let { context -> - if (response.userCancelledAction == false) { - val message = if (response.successful) { - context.getString(R.string.dialog_transfer_money_message_transfer_successful, - String.format("%.02f", transferData.amount), "€", transferData.recipientName) // TODO: where to get currency from? - } - else { - context.getString(R.string.dialog_transfer_money_message_transfer_failed, - String.format("%.02f", transferData.amount), "€", transferData.recipientName, // TODO: where to get currency from? - response.errorToShowToUser - ) - } - - AlertDialog.Builder(context) - .setMessage(message) - .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - - if (response.successful || response.userCancelledAction) { // do not close dialog if an error occurred - this.dismiss() - } - } - } - - - protected fun checkRequiredDataWatcher(additionalCheck: (() -> Unit)? = null): TextWatcher { - return StandardTextWatcher { - additionalCheck?.invoke() - - checkIfRequiredDataEnteredOnUiThread() - } - } - - protected open fun tryToGetBicFromIban(enteredIban: CharSequence) { - presenter.findUniqueBankForIbanAsync(enteredIban.toString()) { foundBank -> - context?.asActivity()?.runOnUiThread { - showValuesForFoundBankOnUiThread(enteredIban, foundBank) - } - } - } - - private fun showValuesForFoundBankOnUiThread(enteredIban: CharSequence, foundBank: BankInfo?) { - validRecipientBicEntered = foundBank != null - recipientBic = foundBank?.bic - - if (foundBank != null) { - txtRecipientBankInfo.text = getString(R.string.dialog_transfer_money_bic_detected_from_iban, foundBank.bic, foundBank.name) - txtRecipientBankInfo.show() - setIbanValidationErrorVisibility() - } - else if (enteredIban.length >= InputValidator.MinimumLengthToDetermineBicFromIban) { - txtRecipientBankInfo.text = getString(R.string.dialog_transfer_money_could_not_determine_bic_from_iban, enteredIban.substring(4, InputValidator.MinimumLengthToDetermineBicFromIban)) - txtRecipientBankInfo.show() - setIbanValidationErrorVisibility() - } - else { - txtRecipientBankInfo.hide() - } - - checkIfRequiredDataEnteredOnUiThread() - } - - protected open fun setIbanValidationErrorVisibility() { - getIbanTextInputErrorView()?.let { textInputError -> - val displaysErrorOrHint = lytRecipientIban.error != null || lytRecipientIban.helperText != null - (textInputError.parent?.parent as? ViewGroup)?.setVisibility(displaysErrorOrHint) - } - } - - protected open fun getIbanTextInputErrorView(): TextView? { - requireContext().getResourceIdentifier("textinput_error", "id")?.let { textInputErrorId -> - return lytRecipientIban.findViewById(textInputErrorId) - } - - return null - } - - protected open fun checkIfRequiredDataEnteredOnUiThread() { - btnTransferMoney.isEnabled = validRecipientNameEntered && validRecipientIbanEntered - && validRecipientBicEntered - && validAmountEntered && validReferenceEntered - } - - protected open fun checkIfEnteredRecipientNameIsValidWhileUserIsTyping() { - val enteredRecipientName = edtxtRecipientName.text.toString() - val validationResult = inputValidator.validateRecipientNameWhileTyping(enteredRecipientName) - - this.validRecipientNameEntered = validationResult.validationSuccessfulOrCouldCorrectString - - showValidationResult(lytRecipientName, validationResult) - } - - protected open fun checkIfEnteredRecipientNameIsValidAfterFocusLost() { - val enteredRecipientName = edtxtRecipientName.text.toString() - val validationResult = inputValidator.validateRecipientName(enteredRecipientName) - - this.validRecipientNameEntered = validationResult.validationSuccessfulOrCouldCorrectString - - if (validationResult.validationSuccessful == false) { // only update hint / error if validation fails, don't hide previous hint / error otherwise - showValidationResult(lytRecipientName, validationResult) - } - } - - protected open fun checkIfEnteredRecipientIbanIsValidWhileUserIsTyping() { - val enteredIban = edtxtRecipientIban.text.toString() - val validationResult = inputValidator.validateIbanWhileTyping(enteredIban) - - this.validRecipientIbanEntered = validationResult.validationSuccessfulOrCouldCorrectString - - showValidationResult(lytRecipientIban, validationResult) - setIbanValidationErrorVisibility() - } - - protected open fun checkIfEnteredRecipientIbanIsValidAfterFocusLost() { - val validationResult = inputValidator.validateIban(edtxtRecipientIban.text.toString()) - - this.validRecipientIbanEntered = validationResult.validationSuccessfulOrCouldCorrectString - - if (validationResult.validationSuccessful == false) { // only update hint / error if validation fails, don't hide previous hint / error otherwise - showValidationResult(lytRecipientIban, validationResult) - setIbanValidationErrorVisibility() - } - } - - protected open fun checkIfEnteredAmountIsValid() { - val validationResult = inputValidator.validateAmount(edtxtAmount.text.toString()) - - this.validAmountEntered = validationResult.validationSuccessfulOrCouldCorrectString - - showValidationResult(lytAmount, validationResult) - } - - protected open fun getEnteredAmount(): BigDecimal? { - try { - val amountString = edtxtAmount.text.toString().replace(',', '.') - - return amountString.toBigDecimal() - } catch (ignored: Exception) { } - - return null - } - - protected open fun checkIfEnteredReferenceTextIsValid() { - val validationResult = inputValidator.validateReference(edtxtReference.text.toString()) - - this.validReferenceEntered = validationResult.validationSuccessfulOrCouldCorrectString - - showValidationResult(lytReference, validationResult) - } - - protected open fun showValidationResult(textInputLayout: TextInputLayout, validationResult: ValidationResult) { - if (didJustCorrectInput.containsKey(textInputLayout)) { // we have just auto corrected TextInputLayout's EditText's text below, don't overwrite its displayed hints and error - return - } - - if (validationResult.didCorrectString) { - textInputLayout.editText?.let { editText -> - val selectionStart = editText.selectionStart - val selectionEnd = editText.selectionEnd - val lengthDiff = validationResult.correctedInputString.length - validationResult.inputString.length - - didJustCorrectInput.put(textInputLayout, true) - - editText.setText(validationResult.correctedInputString) - - if (validationResult.correctedInputString.isNotEmpty()) { - editText.setSelection(selectionStart + lengthDiff, selectionEnd + lengthDiff) - } - - didJustCorrectInput.remove(textInputLayout) - } - } - - val showHintOrError = validationResult.validationError != null || validationResult.validationHint != null - - val textInputErrorLayout = textInputLayout.getResourceIdentifier("textinput_error", "id")?.let { textInputErrorId -> textInputLayout.findViewById(textInputErrorId)?.parent?.parent as? View } - textInputErrorLayout?.setVisibility(showHintOrError) - - textInputLayout.error = validationResult.validationError - if (validationResult.validationError == null) { // don't overwrite error text - textInputLayout.helperText = validationResult.validationHint - } - - (textInputLayout.layoutParams as? ViewGroup.MarginLayoutParams)?.let { params -> - params.bottomMargin = if (showHintOrError == false || textInputLayout == lytReference) 0 - else context!!.getDimension(R.dimen.dialog_transfer_money_input_fields_bottom_margin_when_displaying_validation_label) - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/BankAccountSettingsDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/BankAccountSettingsDialog.kt deleted file mode 100644 index 669eefb5..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/BankAccountSettingsDialog.kt +++ /dev/null @@ -1,125 +0,0 @@ -package net.dankito.banking.ui.android.dialogs.settings - -import android.content.Intent -import android.os.Bundle -import android.view.* -import androidx.fragment.app.FragmentActivity -import kotlinx.android.synthetic.main.dialog_bank_account_settings.* -import kotlinx.android.synthetic.main.dialog_bank_account_settings.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.CheckableValueAdapterItem -import net.dankito.banking.ui.android.adapter.FastAdapterRecyclerView -import net.dankito.banking.ui.model.BankAccountType -import net.dankito.banking.ui.model.TypedBankAccount - - -open class BankAccountSettingsDialog : SettingsDialogBase() { - - companion object { - const val DialogTag = "BankAccountSettingsDialog" - } - - - protected lateinit var account: TypedBankAccount - - - - fun show(account: TypedBankAccount, activity: FragmentActivity) { - this.account = account - - show(activity, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.dialog_bank_account_settings, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - toolbar.apply { - setupToolbar(this, account.displayName) - } - - edtxtBankAccountName.text = account.displayName - - swtchHideAccount.setOnCheckedChangeListener { _, hideAccount -> swtchIncludeInAutomaticAccountsUpdate.isEnabled = hideAccount == false } - - swtchHideAccount.isChecked = account.hideAccount - swtchIncludeInAutomaticAccountsUpdate.isChecked = account.includeInAutomaticAccountsUpdate - - btnShareAccountData.setOnClickListener { shareAccountData() } - - lvlAccountHolderName.value = account.accountHolderName - lvlAccountIdentifier.value = account.identifier - lvlSubAccountNumber.setValueAndVisibilityIfValueIsSet(account.subAccountNumber) - lvlIban.setValueAndVisibilityIfValueIsSet(account.iban) - lvlAccountType.value = getString(getBankAccountTypeResId(account.type)) - - val context = view.context - val accountFeaturesItems = listOf( - CheckableValueAdapterItem(account.supportsRetrievingBalance, context, R.string.dialog_bank_account_settings_account_features_supports_retrieving_balance), - CheckableValueAdapterItem(account.supportsRetrievingAccountTransactions, context, R.string.dialog_bank_account_settings_account_features_supports_retrieving_account_transactions), - CheckableValueAdapterItem(account.supportsTransferringMoney, context, R.string.dialog_bank_account_settings_account_features_supports_money_transfer), - CheckableValueAdapterItem(account.supportsRealTimeTransfer, context, R.string.dialog_bank_account_settings_account_features_supports_real_time_transfer) - ) - FastAdapterRecyclerView(view.rcyAccountFeatures, accountFeaturesItems) - } - - protected open fun getBankAccountTypeResId(type: BankAccountType): Int { - return when (type) { - BankAccountType.CheckingAccount -> R.string.checking_account - BankAccountType.SavingsAccount -> R.string.savings_account - BankAccountType.FixedTermDepositAccount -> R.string.fixed_term_deposit_account - BankAccountType.SecuritiesAccount -> R.string.securities_account - BankAccountType.LoanAccount -> R.string.loan_account - BankAccountType.CreditCardAccount -> R.string.credit_card_account - BankAccountType.FundDeposit -> R.string.fund_deposit - BankAccountType.BuildingLoanContract -> R.string.building_loan_contract - BankAccountType.InsuranceContract -> R.string.insurance_contract - else -> R.string.other - } - } - - - protected open fun shareAccountData() { - val accountData = StringBuilder(account.accountHolderName + "\n" + account.bank.bankName) - - account.iban?.let { iban -> - accountData.append("\n" + getString(R.string.share_account_data_iban, iban)) - } - - accountData.append("\n" + getString(R.string.share_account_data_bic, account.bank.bic)) - accountData.append("\n" + getString(R.string.share_account_data_bank_code, account.bank.bankCode)) - accountData.append("\n" + getString(R.string.share_account_data_account_number, account.identifier)) - - - val sendIntent: Intent = Intent().apply { - action = Intent.ACTION_SEND - putExtra(Intent.EXTRA_TEXT, accountData.toString()) - type = "text/plain" - } - - val shareIntent = Intent.createChooser(sendIntent, null) - startActivity(shareIntent) - - } - - - override val hasUnsavedChanges: Boolean - get() = didChange(edtxtBankAccountName, account.displayName) - || swtchHideAccount.isChecked != account.hideAccount - || swtchIncludeInAutomaticAccountsUpdate.isChecked != account.includeInAutomaticAccountsUpdate - - override fun saveChanges() { - account.userSetDisplayName = edtxtBankAccountName.text - - val didHideAccountChange = account.hideAccount != swtchHideAccount.isChecked - account.hideAccount = swtchHideAccount.isChecked - account.includeInAutomaticAccountsUpdate = swtchIncludeInAutomaticAccountsUpdate.isChecked - - presenter.accountUpdated(account, didHideAccountChange) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/BankSettingsDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/BankSettingsDialog.kt deleted file mode 100644 index 5009c749..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/BankSettingsDialog.kt +++ /dev/null @@ -1,143 +0,0 @@ -package net.dankito.banking.ui.android.dialogs.settings - -import android.os.Bundle -import android.view.* -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.FragmentActivity -import kotlinx.android.synthetic.main.dialog_bank_settings.* -import kotlinx.android.synthetic.main.dialog_bank_settings.view.* -import kotlinx.android.synthetic.main.dialog_bank_settings.view.toolbar -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.DraggableBankAccountAdapterItem -import net.dankito.banking.ui.android.adapter.FastAdapterRecyclerView -import net.dankito.banking.ui.android.adapter.TanMethodAdapterItem -import net.dankito.banking.ui.android.alerts.AskDeleteAccountAlert -import net.dankito.banking.ui.model.TypedBankAccount -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.model.tan.TanMethod - - -open class BankSettingsDialog : SettingsDialogBase() { - - companion object { - const val DialogTag = "BankSettingsDialog" - } - - - protected lateinit var bank: TypedBankData - - protected var selectedTanMethod: TanMethod? = null - - protected lateinit var bankAccountsAdapter: FastAdapterRecyclerView - - protected var banksChangedListener = { _: List -> - updateBankAccountsAdapterItems() - } - - - - fun show(bank: TypedBankData, activity: FragmentActivity) { - this.bank = bank - this.selectedTanMethod = bank.selectedTanMethod - - show(activity, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.dialog_bank_settings, container, false) - - setupUI(rootView) - - presenter.addBanksChangedListener(banksChangedListener) - - return rootView - } - - protected open fun setupUI(rootView: View) { - rootView.apply { - toolbar.apply { - setupToolbar(this, bank.displayName) - } - - edtxtBankName.text = bank.displayName - edtxtUserName.text = bank.userName - bankCredentialsPassword.password = bank.password - - val tanMethodItems = createTanMethodItems() - val tanMethodsAdapter = FastAdapterRecyclerView(rootView.rcyTanMethods, tanMethodItems) - tanMethodsAdapter.onClickListener = { - selectedTanMethod = it.tanMethod - tanMethodsAdapter.setItems(createTanMethodItems()) - } - - lvlBankCode.value = bank.bankCode - lvlBic.value = bank.bic - lvlCustomerName.value = bank.customerName - lvlFinTsServerAddress.value = bank.finTsServerAddress - - val items = createBankAccountsAdapterItems() - bankAccountsAdapter = FastAdapterRecyclerView(rootView.rcyBankAccounts, items, true) - bankAccountsAdapter.onClickListener = { navigationToBankAccountSettingsDialog(it.account) } - bankAccountsAdapter.itemDropped = { oldPosition, oldItem, newPosition, newItem -> reorderedBankAccounts(oldPosition, oldItem.account, newPosition, newItem.account) } - - btnDeleteAccount.setOnClickListener { askUserToDeleteAccount() } - } - } - - - override fun onDestroy() { - presenter.removeBanksChangedListener(banksChangedListener) - - super.onDestroy() - } - - - protected open fun createTanMethodItems(): List { - return bank.supportedTanMethods.map { TanMethodAdapterItem(it, it == selectedTanMethod) } - } - - - protected open fun createBankAccountsAdapterItems(): List { - return bank.accountsSorted.map { DraggableBankAccountAdapterItem(it) } - } - - protected open fun updateBankAccountsAdapterItems() { - bankAccountsAdapter.setItems(createBankAccountsAdapterItems()) - } - - - protected open fun navigationToBankAccountSettingsDialog(account: TypedBankAccount) { - (activity as? AppCompatActivity)?.let { activity -> - BankAccountSettingsDialog().show(account, requireActivity() as AppCompatActivity) - } - } - - protected open fun reorderedBankAccounts(oldPosition: Int, oldItem: TypedBankAccount, newPosition: Int, newItem: TypedBankAccount) { - oldItem.displayIndex = oldPosition - newItem.displayIndex = newPosition - - presenter.accountUpdated(oldItem, false) - presenter.accountUpdated(newItem, false) - } - - - override val hasUnsavedChanges: Boolean - get() = didChange(edtxtBankName, bank.displayName) - || didChange(edtxtUserName, bank.userName) - || bankCredentialsPassword.password != bank.password - || bank.selectedTanMethod != selectedTanMethod - - override fun saveChanges() { - bank.userSetDisplayName = edtxtBankName.text - - presenter.bankUpdated(bank, edtxtUserName.text, bankCredentialsPassword.password, selectedTanMethod) - } - - protected open fun askUserToDeleteAccount() { - AskDeleteAccountAlert().show(bank, presenter, requireContext()) { - closeDialog() - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/ProtectAppSettingsDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/ProtectAppSettingsDialog.kt deleted file mode 100644 index 404152d3..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/ProtectAppSettingsDialog.kt +++ /dev/null @@ -1,183 +0,0 @@ -package net.dankito.banking.ui.android.dialogs.settings - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.view.doOnNextLayout -import androidx.fragment.app.FragmentActivity -import kotlinx.android.synthetic.main.dialog_protect_app_settings.* -import kotlinx.android.synthetic.main.dialog_protect_app_settings.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.authentication.AuthenticationService -import net.dankito.banking.ui.android.authentication.AuthenticationType -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.android.extensions.addEnterPressedListener -import net.dankito.banking.ui.android.util.StandardTextWatcher -import net.dankito.utils.android.extensions.hideKeyboardDelayed -import net.dankito.utils.android.extensions.hide -import net.dankito.utils.android.extensions.setVisibility -import net.dankito.utils.android.extensions.show -import org.slf4j.LoggerFactory -import javax.inject.Inject - - -open class ProtectAppSettingsDialog : SettingsDialogBase() { - - companion object { - const val DialogTag = "ProtectAppSettingsDialog" - - private val log = LoggerFactory.getLogger(ProtectAppSettingsDialog::class.java) - } - - - @Inject - protected lateinit var authenticationService: AuthenticationService - - - init { - BankingComponent.component.inject(this) - } - - - fun show(activity: FragmentActivity) { - show(activity, SettingsDialog.DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.dialog_protect_app_settings, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - setupUI(view) - } - - protected open fun setupUI(rootView: View) { - rootView.apply { - toolbar.apply { - setupToolbar(this, context.getString(R.string.settings), false) - } - - val authenticationType = authenticationService.authenticationType - val isBiometricAuthenticationSupported = authenticationService.isBiometricAuthenticationSupported - - val showAuthenticationMethods = isBiometricAuthenticationSupported || authenticationType != AuthenticationType.None // hide select authentication method if password is the only option to choose - segmentedGroup.setVisibility(showAuthenticationMethods) - segmentedGroup.doOnNextLayout { - val segmentedControlButtonWidth = segmentedGroup.measuredWidth / 3 - btnShowBiometricAuthenticationSection.layoutParams.width = segmentedControlButtonWidth - btnShowPasswordAuthenticationSection.layoutParams.width = segmentedControlButtonWidth - btnShowRemoveAppProtectionSection.layoutParams.width = segmentedControlButtonWidth - } - - btnShowBiometricAuthenticationSection.setVisibility(isBiometricAuthenticationSupported) - btnShowBiometricAuthenticationSection.setOnCheckedChangeListener { _, isChecked -> - if (isChecked) { - showAuthenticationLayout(rootView, lytBiometricAuthentication) - } - } - - btnShowPasswordAuthenticationSection.setOnCheckedChangeListener { _, isChecked -> - if (isChecked) { - showAuthenticationLayout(rootView, lytPasswordAuthentication) - checkIfEnteredPasswordsMatch() - } - } - - btnShowRemoveAppProtectionSection.setOnCheckedChangeListener { _, isChecked -> - if (isChecked) { - showAuthenticationLayout(rootView, lytRemoveAppProtection) - } - } - - btnBiometricAuthentication.customButtonClickHandler = { - authenticationService.authenticateUserWithBiometricToSetAsNewAuthenticationMethod { result -> - btnSetAuthenticationMethod.isEnabled = result.successful - } - } - - edtxtPassword.actualEditText.addTextChangedListener(StandardTextWatcher { checkIfEnteredPasswordsMatch() } ) - edtxtPassword.actualEditText.addEnterPressedListener { checkIfEnteredPasswordsMatchAndSetAuthenticationMethod() } - edtxtPasswordConfirmation.actualEditText.addTextChangedListener(StandardTextWatcher { checkIfEnteredPasswordsMatch() } ) - edtxtPasswordConfirmation.actualEditText.addEnterPressedListener { checkIfEnteredPasswordsMatchAndSetAuthenticationMethod() } - - btnSetAuthenticationMethod.setOnClickListener { setAuthenticationMethod() } - - if (isBiometricAuthenticationSupported && authenticationType == AuthenticationType.Biometric) { - btnShowBiometricAuthenticationSection.isChecked = true - } - else { - btnShowPasswordAuthenticationSection.isChecked = true - } - - } - } - - protected open fun showAuthenticationLayout(rootView: View, authenticationLayoutToShow: ViewGroup) { - lytBiometricAuthentication.hide() - lytPasswordAuthentication.hide() - lytRemoveAppProtection.hide() - - authenticationLayoutToShow.show() - - if (authenticationLayoutToShow == lytRemoveAppProtection) { - btnSetAuthenticationMethod.setText(R.string.dialog_protect_app_settings_button_remove_app_protection_title) - btnSetAuthenticationMethod.setBackgroundResource(R.color.destructiveColor) - btnSetAuthenticationMethod.isEnabled = true - } - else { - btnSetAuthenticationMethod.setText(R.string.dialog_protect_app_settings_button_set_new_authentication_method_title) - btnSetAuthenticationMethod.setBackgroundResource(R.drawable.conditionally_disabled_view_background) - btnSetAuthenticationMethod.isEnabled = false - } - - authenticationLayoutToShow.hideKeyboardDelayed(10) - } - - - protected open fun checkIfEnteredPasswordsMatchAndSetAuthenticationMethod(): Boolean { - if (checkIfEnteredPasswordsMatch()) { - setAuthenticationMethod() - - return true - } - - return false - } - - protected open fun checkIfEnteredPasswordsMatch(): Boolean { - val enteredPassword = edtxtPassword.text - - if (enteredPassword.isNotBlank() && enteredPassword == edtxtPasswordConfirmation.text) { - btnSetAuthenticationMethod.isEnabled = true - return true - } - else { - btnSetAuthenticationMethod.isEnabled = false - return false - } - } - - protected open fun setAuthenticationMethod() { - when { - btnShowPasswordAuthenticationSection.isChecked -> authenticationService.setAuthenticationMethodToPassword(edtxtPassword.chars) - btnShowBiometricAuthenticationSection.isChecked -> authenticationService.setAuthenticationMethodToBiometric() - btnShowRemoveAppProtectionSection.isChecked -> authenticationService.removeAppProtection() - else -> log.error("This should never occur! Has there a new authentication method been added?") - } - - closeDialog() - } - - - override val hasUnsavedChanges: Boolean - get() = false - - override fun saveChanges() { - - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/SettingsDialog.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/SettingsDialog.kt deleted file mode 100644 index 2c02c78b..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/SettingsDialog.kt +++ /dev/null @@ -1,200 +0,0 @@ -package net.dankito.banking.ui.android.dialogs.settings - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.content.res.AppCompatResources -import androidx.fragment.app.FragmentActivity -import kotlinx.android.synthetic.main.dialog_settings.* -import kotlinx.android.synthetic.main.dialog_settings.view.* -import net.codinux.banking.tools.importerexporter.CsvAccountTransactionsExporter -import net.codinux.banking.tools.importerexporter.model.AccountTransaction -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.BankDataAdapterItem -import net.dankito.banking.ui.android.adapter.FastAdapterRecyclerView -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.model.IAccountTransaction -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.filechooserdialog.FileChooserDialog -import net.dankito.filechooserdialog.model.FileChooserDialogConfig -import net.dankito.utils.android.permissions.IPermissionsService -import net.dankito.utils.multiplatform.toFile -import java.io.File -import java.text.SimpleDateFormat -import javax.inject.Inject - - -open class SettingsDialog : SettingsDialogBase() { - - companion object { - val ExportTransactionsDateFormat = SimpleDateFormat("yyyyMMdd") - - const val DialogTag = "SettingsDialog" - } - - - @Inject - protected lateinit var permissionsService: IPermissionsService - - protected lateinit var banksAdapter: FastAdapterRecyclerView - - protected var banksChangedListener = { _: List -> - updateBanksAdapterItems() - } - - - init { - BankingComponent.component.inject(this) - } - - - fun show(activity: FragmentActivity) { - show(activity, DialogTag) - } - - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.dialog_settings, container, false) - - setupUI(rootView) - - presenter.addBanksChangedListener(banksChangedListener) - - return rootView - } - - protected open fun setupUI(rootView: View) { - rootView.apply { - toolbar.apply { - setupToolbar(this, rootView.context.getString(R.string.settings)) - } - - val items = createBanksAdapterItems() - banksAdapter = FastAdapterRecyclerView(rootView.rcyBankCredentials, items, true) - banksAdapter.onClickListener = { navigationToBankSettingsDialog(it.bank) } - banksAdapter.itemDropped = { oldPosition, oldItem, newPosition, newItem -> reorderedBanks(oldPosition, oldItem.bank, newPosition, newItem.bank) } - - btnAddAccount.setOnClickListener { presenter.showAddAccountDialog() } - - selectUpdateAccountsAfter.periodInMinutes = presenter.appSettings.automaticallyUpdateAccountsAfterMinutes - - btnSetAppProtection.setOnClickListener { navigateToProtectAppSettingsDialog() } - selectLockAppAfter.periodInMinutes = presenter.appSettings.lockAppAfterMinutes - - btnExportAccountTransactions.setOnClickListener { exportAccountTransactions() } - - // on Pre Lollipop devices setting vector drawables in xml is not supported -> set left drawable here - val sendIcon = AppCompatResources.getDrawable(context, R.drawable.ic_baseline_send_24) - btnShowSendMessageLogDialog.setCompoundDrawablesWithIntrinsicBounds(sendIcon, null, null, null) - btnShowSendMessageLogDialog.setOnClickListener { presenter.showSendMessageLogDialog() } - } - } - - - override fun onDestroy() { - presenter.removeBanksChangedListener(banksChangedListener) - - super.onDestroy() - } - - - protected open fun createBanksAdapterItems(): List { - return presenter.allBanksSortedByDisplayIndex.map { BankDataAdapterItem(it) } - } - - protected open fun updateBanksAdapterItems() { - activity?.runOnUiThread { - banksAdapter.setItems(createBanksAdapterItems()) - } - } - - - protected open fun navigationToBankSettingsDialog(bank: TypedBankData) { - activity?.let { activity -> - BankSettingsDialog().show(bank, activity) - } - } - - protected open fun navigateToProtectAppSettingsDialog() { - activity?.let { activity -> - ProtectAppSettingsDialog().show(activity) - } - } - - - protected open fun exportAccountTransactions() { - val initialDirectory = presenter.appSettings.lastSelectedExportFolder.toFile() - val suggestedFilename = getExportCsvSuggestedFilename() - -// val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) -// intent.addCategory(Intent.CATEGORY_OPENABLE) -// intent.type = "text/csv" -// -// intent.putExtra(Intent.EXTRA_TITLE, suggestedFilename) -// -// startActivityForResult(intent, 1) - - activity?.let { activity -> - val config = FileChooserDialogConfig(initialDirectory = initialDirectory, suggestedFilenameForSaveFileDialog = suggestedFilename) - FileChooserDialog().showSaveFileInFullscreenDialog(activity, permissionsService, config) { _, selectedFile -> - selectedFile?.let { - val transactions = presenter.allTransactionsSorted.map { mapTransaction(it) } - - CsvAccountTransactionsExporter().export(selectedFile, transactions) - - presenter.appSettings.lastSelectedExportFolder = selectedFile.parentFile.absolutePath - presenter.appSettingsChanged() - } - } - } - } - - // TODO: this is almost the same code as in JavaFX MainMenuBar.getExportCsvSuggestedFilename() -> merge - protected open fun getExportCsvSuggestedFilename(): String? { - val transactions = presenter.allTransactions - val transactionsDates = transactions.map { it.valueDate } - val transactionsStartDate = transactionsDates.min() - val transactionsEndDate = transactionsDates.max() - - return context?.getString(R.string.dialog_settings_export_account_transactions_suggested_file_name, - transactionsStartDate?.let { ExportTransactionsDateFormat.format(it) } ?: "", transactionsEndDate?.let { ExportTransactionsDateFormat.format(it) } ?: "") - } - - // TODO: this is exactly the same code as in JavaFX MainMenuBar.mapTransaction() -> merge - protected open fun mapTransaction(transaction: IAccountTransaction): AccountTransaction { - return AccountTransaction( - transaction.account.iban ?: transaction.account.identifier, - transaction.amount, - transaction.currency, - transaction.reference, - transaction.bookingDate, - transaction.valueDate, - transaction.otherPartyName, - transaction.otherPartyBankCode, - transaction.otherPartyAccountId, - transaction.bookingText - ) - } - - - protected open fun reorderedBanks(oldPosition: Int, oldItem: TypedBankData, newPosition: Int, newItem: TypedBankData) { - oldItem.displayIndex = oldPosition - newItem.displayIndex = newPosition - - presenter.bankDisplayIndexUpdated(oldItem) - presenter.bankDisplayIndexUpdated(newItem) - } - - - override val hasUnsavedChanges: Boolean - get() = presenter.appSettings.automaticallyUpdateAccountsAfterMinutes != selectUpdateAccountsAfter.periodInMinutes - || presenter.appSettings.lockAppAfterMinutes != selectLockAppAfter.periodInMinutes - - override fun saveChanges() { - presenter.appSettings.automaticallyUpdateAccountsAfterMinutes = selectUpdateAccountsAfter.periodInMinutes - presenter.appSettings.lockAppAfterMinutes = selectLockAppAfter.periodInMinutes - presenter.appSettingsChanged() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/SettingsDialogBase.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/SettingsDialogBase.kt deleted file mode 100644 index a21f6ffd..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/dialogs/settings/SettingsDialogBase.kt +++ /dev/null @@ -1,149 +0,0 @@ -package net.dankito.banking.ui.android.dialogs.settings - -import android.app.Dialog -import android.content.DialogInterface -import android.os.Bundle -import android.view.* -import androidx.appcompat.widget.Toolbar -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.FragmentActivity -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.alerts.AskDismissChangesAlert -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.android.views.FormEditText -import net.dankito.banking.ui.presenter.BankingPresenter -import org.slf4j.LoggerFactory -import javax.inject.Inject - - -abstract class SettingsDialogBase : DialogFragment() { - - companion object { - private val log = LoggerFactory.getLogger(SettingsDialogBase::class.java) - } - - - protected abstract val hasUnsavedChanges: Boolean - - protected abstract fun saveChanges() - - - @Inject - protected lateinit var presenter: BankingPresenter - - - init { - BankingComponent.component.inject(this) - } - - - - fun show(activity: FragmentActivity, dialogTag: String, fullscreen: Boolean = true) { - val style = if (fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog - setStyle(STYLE_NORMAL, style) - - show(activity.supportFragmentManager, dialogTag) - } - - - override fun setupDialog(dialog: Dialog, style: Int) { - super.setupDialog(dialog, style) - - dialog.setOnKeyListener { _, keyCode, event -> - if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { - return@setOnKeyListener handleBackButtonPress() - } - - false - } - } - - protected open fun handleBackButtonPress(): Boolean { - askToDismissChanges() - - return hasUnsavedChanges - } - - - protected open fun setupToolbar(toolbar: Toolbar, dialogTitle: String, showSaveButton: Boolean = true) { - toolbar.apply { - title = dialogTitle - - inflateMenu(R.menu.menu_settings_dialog) - menu.findItem(R.id.mnitmSaveChanges).isVisible = showSaveButton - - setOnMenuItemClickListener { item -> onOptionsItemSelected(item) } - - setNavigationOnClickListener { askToDismissChanges() } - } - } - - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { - R.id.mnitmSaveChanges -> saveChangesAndCloseDialog() - else -> super.onOptionsItemSelected(item) - } - } - - - protected open fun didChange(editedValue: FormEditText, originalValue: String): Boolean { - return editedValue.text != originalValue - } - - - protected open fun saveChangesAndCloseDialog(): Boolean { - if (hasUnsavedChanges) { - saveChanges() - } - - closeDialog() - - return true - } - - protected open fun askToDismissChanges() { - if (hasUnsavedChanges) { - AskDismissChangesAlert().show(this) - } - else { - closeDialog() - } - } - - protected open fun closeDialog() { - dismiss() - } - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - log.info("Creating Fragment $this") - } - - override fun onDismiss(dialog: DialogInterface) { - log.info("Dismissing Fragment $this") - - super.onDismiss(dialog) - } - - override fun onPause() { - log.info("Pausing Fragment $this") - - super.onPause() - } - - override fun onStop() { - log.info("Stopping Fragment $this") - - super.onStop() - } - - override fun onDestroy() { - log.info("Destroying Fragment $this") - - super.onDestroy() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/AutocompleteExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/AutocompleteExtensions.kt deleted file mode 100644 index 9b764549..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/AutocompleteExtensions.kt +++ /dev/null @@ -1,28 +0,0 @@ -package net.dankito.banking.ui.android.extensions - -import android.app.Dialog -import android.view.KeyEvent -import com.otaliastudios.autocomplete.Autocomplete - - -/** - * This will not work if Dialog is null! - * - * Making the Dialog parameter nullable is just for convienience to be able to call - * Autocomplete - * .on<>(view) - * .build() - * .closePopupOnBackButtonPress(dialog) - */ -fun Autocomplete<*>.closePopupOnBackButtonPress(dialog: Dialog?) { - dialog?.setOnKeyListener { _, keyCode, _ -> - if (keyCode == KeyEvent.KEYCODE_BACK) { - if (this.isPopupShowing) { // close autocomplete popup on back button press - this.dismissPopup() - return@setOnKeyListener true - } - } - - false - } -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ByteArrayExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ByteArrayExtensions.kt deleted file mode 100644 index 8692542b..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ByteArrayExtensions.kt +++ /dev/null @@ -1,16 +0,0 @@ -package net.dankito.banking.ui.android.extensions - -import android.content.res.Resources -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.graphics.drawable.BitmapDrawable -import android.graphics.drawable.Drawable - - -fun ByteArray.toBitmap(): Bitmap { - return BitmapFactory.decodeByteArray(this, 0, this.size) -} - -fun ByteArray.toDrawable(resources: Resources): Drawable { - return BitmapDrawable(resources, this.toBitmap()) -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ContextExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ContextExtensions.kt deleted file mode 100644 index b562f6b6..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ContextExtensions.kt +++ /dev/null @@ -1,16 +0,0 @@ -package net.dankito.banking.ui.android.extensions - -import android.content.Context -import android.os.IBinder -import android.view.View -import android.view.inputmethod.InputMethodManager - - -fun Context.hideKeyboard(anyViewInHierarchy: View, flags: Int = 0) { - hideKeyboard(anyViewInHierarchy.windowToken, flags) -} - -fun Context.hideKeyboard(windowToken: IBinder, flags: Int = 0) { - val keyboard = this.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - keyboard.hideSoftInputFromWindow(windowToken, flags) -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/EditTextExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/EditTextExtensions.kt deleted file mode 100644 index 5bceda8e..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/EditTextExtensions.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.dankito.banking.ui.android.extensions - -import android.view.KeyEvent -import android.widget.EditText - - -val EditText.textString: String - get() = this.text.toString() - - -fun EditText.addEnterPressedListener(enterPressed: () -> Boolean) { - this.setOnKeyListener { _, keyCode, event -> - if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) { - return@setOnKeyListener enterPressed() - } - - false - } -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/IDrawerItemExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/IDrawerItemExtensions.kt deleted file mode 100644 index 53e9106e..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/IDrawerItemExtensions.kt +++ /dev/null @@ -1,20 +0,0 @@ -package net.dankito.banking.ui.android.extensions - -import android.content.Context -import com.mikepenz.iconics.typeface.IIcon -import com.mikepenz.materialdrawer.iconics.withIcon -import com.mikepenz.materialdrawer.model.BaseDescribeableDrawerItem -import com.mikepenz.materialdrawer.model.BaseViewHolder -import com.mikepenz.materialdrawer.model.interfaces.withIconColor -import net.dankito.utils.android.extensions.createColorStateList - - -fun BaseDescribeableDrawerItem.withIcon(context: Context, icon: IIcon, iconColorId: Int) - : BaseDescribeableDrawerItem { - - withIcon(icon) - - withIconColor(context.createColorStateList(iconColorId)) - - return this -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ImageViewExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ImageViewExtensions.kt deleted file mode 100644 index 2dd1b018..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/ImageViewExtensions.kt +++ /dev/null @@ -1,28 +0,0 @@ -package net.dankito.banking.ui.android.extensions - -import android.widget.ImageView -import net.dankito.banking.ui.model.IBankData -import net.dankito.utils.android.extensions.hide -import net.dankito.utils.android.extensions.show - - -fun ImageView.setIcon(bank: IBankData<*, *>) { - try { - val iconData = bank.iconData - - if (iconData != null) { - this.show() - this.setImageFromBytes(iconData) - } - else { - this.hide() - this.setImageURI(null) - } - } catch (e: Exception) { - this.hide() - } -} - -fun ImageView.setImageFromBytes(data: ByteArray) { - this.setImageBitmap(data.toBitmap()) -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/RecyclerViewExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/RecyclerViewExtensions.kt deleted file mode 100644 index 9f86f958..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/RecyclerViewExtensions.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.dankito.banking.ui.android.extensions - -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.RecyclerView - - -fun RecyclerView.addHorizontalItemDivider() { - this.addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL)) -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/TextViewExtensions.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/TextViewExtensions.kt deleted file mode 100644 index 8c399563..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/extensions/TextViewExtensions.kt +++ /dev/null @@ -1,30 +0,0 @@ -package net.dankito.banking.ui.android.extensions - -import android.widget.TextView -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.utils.android.extensions.setTextColorToColorResource -import net.dankito.utils.multiplatform.BigDecimal - - -fun TextView.showAmount(presenter: BankingPresenter, amount: BigDecimal, currencyIsoCode: String? = null) { - text = presenter.formatAmount(amount, currencyIsoCode) - setTextColorForAmount(amount) -} - -fun TextView.setTextColorForAmount(amount: BigDecimal) { - setTextColorToColorResource(if (amount >= java.math.BigDecimal.ZERO) R.color.positiveAmount else R.color.negativeAmount) -} - -val TextView.isEllipsized: Boolean - get() { - this.layout?.let { layout -> - for (i in 0..layout.lineCount) { - if (layout.getEllipsisCount(i) > 0) { - return true - } - } - } - - return false - } \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt deleted file mode 100644 index 7d0d6e2c..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/home/HomeFragment.kt +++ /dev/null @@ -1,363 +0,0 @@ -package net.dankito.banking.ui.android.home - -import android.app.SearchManager -import android.content.Context -import android.os.Bundle -import android.view.* -import android.view.inputmethod.EditorInfo -import android.widget.EditText -import android.widget.ImageButton -import androidx.appcompat.widget.Toolbar -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.widget.SearchView -import androidx.core.content.ContextCompat -import androidx.core.graphics.drawable.DrawableCompat -import androidx.fragment.app.Fragment -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.fragment_home.* -import kotlinx.android.synthetic.main.fragment_home.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.adapter.AccountTransactionAdapter -import net.dankito.banking.ui.android.di.BankingComponent -import net.dankito.banking.ui.android.extensions.addHorizontalItemDivider -import net.dankito.banking.ui.android.extensions.showAmount -import net.dankito.banking.ui.android.views.InfoPopupWindow -import net.dankito.banking.ui.model.SelectedAccountType -import net.dankito.banking.ui.model.TransactionsRetrievalState -import net.dankito.banking.ui.model.TypedBankAccount -import net.dankito.banking.ui.model.parameters.TransferMoneyData -import net.dankito.banking.ui.model.responses.GetTransactionsResponse -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.utils.android.extensions.* -import net.dankito.utils.multiplatform.sum -import javax.inject.Inject - - -class HomeFragment : Fragment() { - - companion object { - - val TransactionsCannotBeRetrievedStates = listOf(TransactionsRetrievalState.AccountTypeNotSupported, TransactionsRetrievalState.AccountDoesNotSupportFetchingTransactions) - - } - - - private lateinit var mnitmSearchTransactions: MenuItem - - private lateinit var mnitmUpdateTransactions: MenuItem - - - private var accountsForWhichNotAllTransactionsHaveBeenFetched = listOf() - - private var showTopFetchAllTransactionsView = true // TODO: read from db - - - private val transactionAdapter: AccountTransactionAdapter - - protected var appliedTransactionsFilter = "" - - - @Inject - protected lateinit var presenter: BankingPresenter - - - init { - BankingComponent.component.inject(this) - - transactionAdapter = AccountTransactionAdapter(presenter) - } - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setHasOptionsMenu(true) - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.fragment_home, container, false) - - val rcyvwAccountTransactions: RecyclerView = rootView.findViewById(R.id.rcyvwAccountTransactions) - rcyvwAccountTransactions.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - rcyvwAccountTransactions.adapter = transactionAdapter - rcyvwAccountTransactions.addHorizontalItemDivider() - rcyvwAccountTransactions.isNestedScrollingEnabled = false - - registerForContextMenu(rcyvwAccountTransactions) // this is actually bad, splits code as context menu is created in AccountTransactionAdapter - - rootView.btnTopFetchAllTransactions.setOnClickListener { - fetchAllTransactions() - } - - rootView.btnBottomFetchAllTransactions.setOnClickListener { - fetchAllTransactions() - } - - rootView.btnShowFetchAllTransactionsInfo.setOnClickListener { showFetchAllTransactionsInfo(rootView.btnShowFetchAllTransactionsInfo) } - - rootView.btnHideTopFetchAllTransactionsView.setOnClickListener { - hideTopFetchAllTransactionsView() - } - - rootView.btnRetrieveTransactions.setOnClickListener { fetchTransactions() } - rootView.btnAddAccount.setOnClickListener { presenter.showAddAccountDialog() } - - return rootView - } - - override fun onResume() { - super.onResume() - - if (this::mnitmSearchTransactions.isInitialized) { // restore displayed transactions after onStop() - updateMenuItemsStateAndTransactionsToDisplay() - } - } - - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - super.onCreateOptionsMenu(menu, inflater) - - mnitmSearchTransactions = menu.findItem(R.id.mnitmSearchTransactions) - mnitmUpdateTransactions = menu.findItem(R.id.mnitmUpdateTransactions) - - initSearchView() - - initLogicAfterUiInitialized() - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - R.id.mnitmUpdateTransactions -> { - updateAccountsTransactions() - return true - } - } - - return super.onOptionsItemSelected(item) - } - - private fun initSearchView() { - context?.asActivity()?.let { context -> - (context.getSystemService(Context.SEARCH_SERVICE) as? SearchManager)?.let { searchManager -> - (mnitmSearchTransactions.actionView as? SearchView)?.let { searchView -> - searchView.setSearchableInfo(searchManager.getSearchableInfo(context.componentName)) - - // if imeOptions aren't set like this searchView would take whole remaining screen when focused in landscape mode (see https://stackoverflow.com/questions/15296129/searchview-and-keyboard) - val searchInput = - searchView.findViewById(androidx.appcompat.R.id.search_src_text) as? EditText - searchInput?.imeOptions = EditorInfo.IME_ACTION_SEARCH or EditorInfo.IME_FLAG_NO_EXTRACT_UI - - searchView.setOnQueryTextListener(searchAccountTransactionsTextListener) - } - } - } - } - - - override fun onContextItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - R.id.mnitmNewTransferToSameTransactionParty -> { - newTransferToSameTransactionParty() - return true - } - R.id.mnitmNewTransferWithSameData -> { - newTransferWithSameData() - return true - } - } - - return super.onContextItemSelected(item) - } - - - private fun initLogicAfterUiInitialized() { - presenter.addBanksChangedListener { updateMenuItemsStateAndTransactionsToDisplay() } // on account addition or deletion may menu items' state changes - presenter.addSelectedAccountsChangedListener { updateMenuItemsStateAndTransactionsToDisplay() } - - presenter.addRetrievedAccountTransactionsResponseListener { response -> - handleGetTransactionsResponseOffUiThread(response) - } - - updateMenuItemsStateAndTransactionsToDisplay() - } - - - private fun updateMenuItemsStateAndTransactionsToDisplay() { - context?.asActivity()?.runOnUiThread { - mnitmSearchTransactions.isVisible = presenter.doSelectedAccountsSupportRetrievingTransactions - mnitmUpdateTransactions.isVisible = presenter.doSelectedAccountsSupportRetrievingTransactions - - updateTransactionsToDisplayOnUiThread() - } - } - - private fun updateAccountsTransactions() { - mnitmUpdateTransactions.isEnabled = false - - val icon = mnitmUpdateTransactions.icon?.let { DrawableCompat.wrap(it) } - icon?.let { DrawableCompat.setTint(it, ContextCompat.getColor(context!!, R.color.disabledColor)) } - - presenter.updateSelectedAccountsTransactionsAsync { - context?.asActivity()?.runOnUiThread { - mnitmUpdateTransactions.isEnabled = true - icon?.let { DrawableCompat.setTintList(it, null) } - } - } - } - - private fun handleGetTransactionsResponseOffUiThread(response: GetTransactionsResponse) { - context?.asActivity()?.let { activity -> - activity.runOnUiThread { - handleGetTransactionsResponseOnUiThread(activity, response) - } - } - } - - private fun handleGetTransactionsResponseOnUiThread(context: Context, response: GetTransactionsResponse) { - response.retrievedData.forEach { retrievedData -> - if (retrievedData.successfullyRetrievedData) { - updateTransactionsToDisplayOnUiThread() - } - else if (response.userCancelledAction == false) { // if user cancelled entering TAN then don't show a error message - AlertDialog.Builder(context) - .setMessage(context.getString(R.string.fragment_home_could_not_retrieve_account_transactions, - retrievedData.account.displayName, response.errorToShowToUser)) - .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } - .show() - } - } - } - - - private fun newTransferToSameTransactionParty() { - transactionAdapter.selectedTransaction?.let { selectedTransaction -> - presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransactionWithoutAmountAndReference(selectedTransaction)) - } - } - - private fun newTransferWithSameData() { - transactionAdapter.selectedTransaction?.let { selectedTransaction -> - presenter.showTransferMoneyDialog(TransferMoneyData.fromAccountTransaction(selectedTransaction)) - } - } - - - private val searchAccountTransactionsTextListener: SearchView.OnQueryTextListener = object : SearchView.OnQueryTextListener { - override fun onQueryTextChange(query: String): Boolean { - appliedTransactionsFilter = query - - updateTransactionsToDisplayOnUiThread() - - return true - } - - override fun onQueryTextSubmit(query: String): Boolean { - return true - } - } - - - private fun updateTransactionsToDisplayOnUiThread() { - setToolbarTitle() - - transactionAdapter.items = presenter.searchSelectedAccountTransactions(appliedTransactionsFilter) - - lytTransactionsSummary.setVisibility(presenter.doSelectedAccountsSupportRetrievingBalance) - - txtCountTransactions.text = context?.getString(R.string.fragment_home_count_transactions, transactionAdapter.items.size) - - val sumOfDisplayedTransactions = if (appliedTransactionsFilter.isBlank()) presenter.balanceOfSelectedAccounts - else transactionAdapter.items.map { it.amount }.sum() - txtTransactionsBalance.showAmount(presenter, sumOfDisplayedTransactions) - - setRecyclerViewAndNoTransactionsFetchedView() - - setFetchAllTransactionsView() - } - - private fun setToolbarTitle() { - // TODO: also set selected account's icon - - if (presenter.allBanks.isNotEmpty()) { - activity?.findViewById(R.id.toolbar)?.let { toolbar -> - toolbar.title = when (presenter.selectedAccountType) { - SelectedAccountType.AllAccounts -> context?.getString(R.string.drawer_menu_all_bank_accounts_title) - SelectedAccountType.SingleBank -> presenter.getSingleSelectedBank()?.displayName - SelectedAccountType.SingleAccount -> presenter.getSingleSelectedAccount()?.displayName - } - } - } - } - - private fun setRecyclerViewAndNoTransactionsFetchedView() { - val transactionsRetrievalState = presenter.selectedAccountsTransactionRetrievalState - val haveTransactionsBeenRetrieved = transactionsRetrievalState == TransactionsRetrievalState.RetrievedTransactions - val noAccountsAddedYet = presenter.allBanks.isEmpty() - - lytTransactionsTopBar.setVisibility(haveTransactionsBeenRetrieved) - rcyvwAccountTransactions.setVisibility(haveTransactionsBeenRetrieved) - lytNoTransactionsFetched.isGone = haveTransactionsBeenRetrieved || noAccountsAddedYet - btnRetrieveTransactions.isGone = TransactionsCannotBeRetrievedStates.contains(transactionsRetrievalState) - btnAddAccount.setVisibility(noAccountsAddedYet) - - val messageArgs = mutableListOf() - val transactionsRetrievalStateMessageId = when (transactionsRetrievalState) { - TransactionsRetrievalState.AccountTypeNotSupported -> R.string.fragment_home_transactions_retrieval_state_account_type_not_supported - TransactionsRetrievalState.AccountDoesNotSupportFetchingTransactions -> R.string.fragment_home_transactions_retrieval_state_account_does_not_support_retrieving_transactions - TransactionsRetrievalState.NoTransactionsInRetrievedPeriod -> { - val account = presenter.selectedAccounts.first() - account.retrievedTransactionsFromOn?.let { messageArgs.add(presenter.formatToMediumDate(it)) } - account.retrievedTransactionsUpTo?.let { messageArgs.add(presenter.formatToMediumDate(it)) } - R.string.fragment_home_transactions_retrieval_state_no_transactions_in_retrieved_period - } - TransactionsRetrievalState.NeverRetrievedTransactions -> R.string.fragment_home_transactions_retrieval_state_never_retrieved_transactions - else -> null - } - txtNoTransactionsFetchedMessage.text = transactionsRetrievalStateMessageId?.let { requireContext().getString(transactionsRetrievalStateMessageId, *messageArgs.toTypedArray()) } ?: "" - } - - private fun setFetchAllTransactionsView() { - accountsForWhichNotAllTransactionsHaveBeenFetched = presenter.selectedAccountsForWhichNotAllTransactionsHaveBeenFetched - showTopFetchAllTransactionsView = presenter.showStrikingFetchAllTransactionsViewForSelectedAccounts - val showFetchAllTransactionsView = presenter.showFetchAllTransactionsViewForSelectedAccounts - - lytTopFetchAllTransactions.setVisibility(showFetchAllTransactionsView && showTopFetchAllTransactionsView) - - if (showFetchAllTransactionsView && showTopFetchAllTransactionsView == false) { - // TODO: implement CoordinatorLayout to show lytBottomFetchAllTransactions below rcyvwAccountTransactions -// lytBottomFetchAllTransactions.visibility = View.VISIBLE - } - else { - lytBottomFetchAllTransactions.hide() - } - } - - private fun hideTopFetchAllTransactionsView() { - presenter.doNotShowStrikingFetchAllTransactionsViewAnymore(accountsForWhichNotAllTransactionsHaveBeenFetched) - - setFetchAllTransactionsView() - } - - private fun showFetchAllTransactionsInfo(btnShowFetchAllTransactionsInfo: ImageButton) { - activity?.let { activity -> - val account = presenter.selectedAccountsForWhichNotAllTransactionsHaveBeenFetched.first() - - val dateOfFirstRetrievedTransaction = account.retrievedTransactionsFromOn?.let { presenter.formatToMediumDate(it) } ?: "" - val info = activity.getString(R.string.popup_fetch_all_transactions_info, dateOfFirstRetrievedTransaction, - account.countDaysForWhichTransactionsAreKept, presenter.formatToMediumDate(presenter.getDayOfFirstTransactionStoredOnBankServer(account))) - - InfoPopupWindow(activity, info).show(btnShowFetchAllTransactionsInfo, Gravity.BOTTOM) - } - } - - - private fun fetchTransactions() { - presenter.fetchTransactionsOfSelectedAccounts() - } - - private fun fetchAllTransactions() { - presenter.fetchAllTransactionsOfSelectedAccounts() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/listener/ItemSelectedListener.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/listener/ItemSelectedListener.kt deleted file mode 100644 index f61d348f..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/listener/ItemSelectedListener.kt +++ /dev/null @@ -1,15 +0,0 @@ -package net.dankito.banking.ui.android.listener - -import android.view.View -import android.widget.AdapterView - - -open class ItemSelectedListener(val itemSelected: (position: Int) -> Unit) : AdapterView.OnItemSelectedListener { - - override fun onNothingSelected(parent: AdapterView<*>?) { } - - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - itemSelected(position) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/listener/ListItemSelectedListener.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/listener/ListItemSelectedListener.kt deleted file mode 100644 index 60db4616..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/listener/ListItemSelectedListener.kt +++ /dev/null @@ -1,16 +0,0 @@ -package net.dankito.banking.ui.android.listener - -import android.view.View -import android.widget.AdapterView -import net.dankito.utils.android.ui.adapter.ListAdapter - - -open class ListItemSelectedListener(val adapter: ListAdapter, val itemSelected: (item: T) -> Unit) : AdapterView.OnItemSelectedListener { - - override fun onNothingSelected(parent: AdapterView<*>?) { } - - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - itemSelected(adapter.getItem(position)) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/security/CryptographyManager.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/security/CryptographyManager.kt deleted file mode 100644 index 4b71cd5e..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/security/CryptographyManager.kt +++ /dev/null @@ -1,181 +0,0 @@ -package net.dankito.banking.ui.android.security - -import android.os.Build -import android.security.keystore.KeyGenParameterSpec -import android.security.keystore.KeyProperties -import androidx.annotation.RequiresApi -import java.security.KeyStore -import java.security.SecureRandom -import java.security.Security -import javax.crypto.Cipher -import javax.crypto.KeyGenerator -import javax.crypto.SecretKey -import javax.crypto.SecretKeyFactory -import javax.crypto.spec.GCMParameterSpec -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.PBEKeySpec -import javax.crypto.spec.SecretKeySpec - - -open class CryptographyManager { - - companion object { - - const val AndroidKeyStore = "AndroidKeyStore" - - private const val KeySize: Int = 256 - private const val IterationCount = 4096 - private const val PbeCipher = "AES/GCM/NoPadding" - private const val EncryptionBlockMode = KeyProperties.BLOCK_MODE_GCM - private const val EncryptionPadding = KeyProperties.ENCRYPTION_PADDING_NONE - private const val EncryptionAlgorithm = KeyProperties.KEY_ALGORITHM_AES - - private const val CipherTransformation = "$EncryptionAlgorithm/$EncryptionBlockMode/$EncryptionPadding" - - } - - - @RequiresApi(Build.VERSION_CODES.M) - open fun getInitializedCipherForEncryption(keyName: String): Cipher { - return getInitializedCipher(keyName, Cipher.ENCRYPT_MODE) - } - - @RequiresApi(Build.VERSION_CODES.M) - open fun getInitializedCipherForDecryption(keyName: String, initializationVector: ByteArray): Cipher { - return getInitializedCipher(keyName, Cipher.DECRYPT_MODE, initializationVector) - } - - @RequiresApi(Build.VERSION_CODES.M) - protected open fun getInitializedCipher(keyName: String, cipherMode: Int, initializationVector: ByteArray? = null): Cipher { - val cipher = Cipher.getInstance(CipherTransformation) - val secretKey = getOrCreateSecretKey(keyName) - - cipher.init(cipherMode, secretKey, initializationVector?.let { GCMParameterSpec(128, initializationVector) }) - - return cipher - } - - @RequiresApi(Build.VERSION_CODES.M) - protected open fun getOrCreateSecretKey(keyName: String): SecretKey { - val keyStore = KeyStore.getInstance(AndroidKeyStore) - keyStore.load(null) - keyStore.getKey(keyName, null)?.let { return it as SecretKey } - - val paramsBuilder = KeyGenParameterSpec.Builder(keyName, - KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT) - paramsBuilder.apply { - setBlockModes(EncryptionBlockMode) - setEncryptionPaddings(EncryptionPadding) - setKeySize(KeySize) - setUserAuthenticationRequired(true) - } - - val keyGenParams = paramsBuilder.build() - val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, - AndroidKeyStore) - keyGenerator.init(keyGenParams) - return keyGenerator.generateKey() - } - - - open fun encryptData(plaintext: CharArray, cipher: Cipher): ByteArray { - return cipher.doFinal(mapToBytes(plaintext)) - } - - open fun decryptData(cipherText: ByteArray, cipher: Cipher): CharArray { - val plainTextBytes = cipher.doFinal(cipherText) - return mapToChars(plainTextBytes) - } - - - open fun encryptDataWithPbe(plaintext: CharArray, password: String, salt: ByteArray): Pair { - val secret: SecretKey = generatePbeSecretKey(password, salt) - - val cipher: Cipher = Cipher.getInstance(PbeCipher) - cipher.init(Cipher.ENCRYPT_MODE, secret) - val initializationVector = cipher.iv - - return Pair(cipher.doFinal(mapToBytes(plaintext)), initializationVector) - } - - open fun decryptDataWithPbe(cipherText: ByteArray, password: String, initializationVector: ByteArray, salt: ByteArray): CharArray { - val secret: SecretKey = generatePbeSecretKey(password, salt) - val cipher = Cipher.getInstance(PbeCipher) - cipher.init(Cipher.DECRYPT_MODE, secret, IvParameterSpec(initializationVector)) - - val plainTextBytes = cipher.doFinal(cipherText) - return mapToChars(plainTextBytes) - } - - protected open fun generatePbeSecretKey(userPassword: String, salt: ByteArray): SecretKey { - // Initialize PBE with password - val factory = SecretKeyFactory.getInstance(findBestPbeAlgorithm()!!) - val spec = PBEKeySpec(userPassword.toCharArray(), salt, IterationCount, KeySize) - val key = factory.generateSecret(spec) - - return SecretKeySpec(key.encoded, "AES") - } - - open fun generateRandomBytes(countBytes: Int): ByteArray { - return ByteArray(countBytes).apply { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - SecureRandom.getInstanceStrong().nextBytes(this) - } else { - SecureRandom().nextBytes(this) - } - } - } - - - protected open fun mapToBytes(chars: CharArray): ByteArray { - return chars.map { it.toByte() }.toByteArray() - } - - protected open fun mapToChars(plainTextBytes: ByteArray): CharArray { - return plainTextBytes.map { mapToChar(it) }.toCharArray() - } - - protected open fun mapToChar(byte: Byte): Char { - // Byte is signed but Char isn't -> convert negative byte values to positive ones - if (byte.toInt() < 0) { - return (256 + byte.toInt()).toChar() - } - else { - return byte.toChar() - } - } - - - open fun findBestPbeAlgorithm(): String? { - return findBestMatchingAlgorithm(SecurityProviderServiceType.SecretKeyFactory, "PBKDF2","PBKDF2WithHmacSHA256") - ?: findBestMatchingAlgorithm(SecurityProviderServiceType.SecretKeyFactory, "PBE") - } - - open fun findBestMatchingAlgorithm(type: SecurityProviderServiceType, nameStartsWith: String, vararg preferredAlgorithms: String): String? { - val supportedAlgorithms = listServiceTypeAlgorithmsWithName(type, nameStartsWith) - - val bestMatchingAlgorithm = preferredAlgorithms.firstOrNull { supportedAlgorithms.contains(it) } - ?: supportedAlgorithms.maxBy { it.length } - - return bestMatchingAlgorithm - } - - open fun listServiceTypeAlgorithmsWithName(type: SecurityProviderServiceType, nameStartsWith: String): List { - return listServiceTypeAlgorithms(type) - .filter { it.startsWith(nameStartsWith, true) } - } - - open fun listServiceTypeAlgorithms(type: SecurityProviderServiceType): List { - val algorithms = mutableListOf() - - Security.getProviders().forEach { provider -> - algorithms.addAll(provider.services - .filter { it.type == type.type } - .map { it.algorithm } - ) - } - - return algorithms - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/security/SecurityProviderServiceType.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/security/SecurityProviderServiceType.kt deleted file mode 100644 index 34c75a7d..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/security/SecurityProviderServiceType.kt +++ /dev/null @@ -1,44 +0,0 @@ -package net.dankito.banking.ui.android.security - - -enum class SecurityProviderServiceType(val type: String) { - - AlgorithmParameterGenerator("AlgorithmParameterGenerator"), - - AlgorithmParameters("AlgorithmParameters"), - - CertPathBuilder("CertPathBuilder"), - - CertPathValidator("CertPathValidator"), - - CertStore("CertStore"), - - CertificateFactory("CertificateFactory"), - - Cipher("Cipher"), - - KeyAgreement("KeyAgreement"), - - KeyFactory("KeyFactory"), - - KeyGenerator("KeyGenerator"), - - KeyManagerFactory("KeyManagerFactory"), - - KeyPairGenerator("KeyPairGenerator"), - - KeyStore("KeyStore"), - - Mac("Mac"), - - MessageDigest("MessageDigest"), - - SSLContext("SSLContext"), - - SecretKeyFactory("SecretKeyFactory"), - - SecureRandom("SecureRandom"), - - Signature("Signature"), - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/CurrentActivityTracker.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/CurrentActivityTracker.kt deleted file mode 100644 index 916a28d6..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/CurrentActivityTracker.kt +++ /dev/null @@ -1,53 +0,0 @@ -package net.dankito.banking.ui.android.util - -import net.dankito.banking.ui.android.activities.BaseActivity -import java.util.* -import java.util.concurrent.CopyOnWriteArrayList -import kotlin.concurrent.schedule - - -open class CurrentActivityTracker { - - protected val nextActivitySetListeners = CopyOnWriteArrayList<(BaseActivity) -> Unit>() - - - var currentActivity: BaseActivity? = null - set(value) { - field = value // TODO: check field != value - - if (value != null) { - callAndClearNextActivitySetListeners(value) - } - } - - - open fun currentOrNextActivity(activity: (BaseActivity) -> Unit) { - currentActivity?.let { - activity(it) - } - ?: addNextActivitySetListener { - activity(it) - } - } - - open fun addNextActivitySetListener(listener: (BaseActivity) -> Unit) { - synchronized(nextActivitySetListeners) { - nextActivitySetListeners.add(listener) - } - } - - protected open fun callAndClearNextActivitySetListeners(activity: BaseActivity) { - synchronized(nextActivitySetListeners) { - val listenersCopy = ArrayList(nextActivitySetListeners) - - nextActivitySetListeners.clear() - - Timer().schedule(500) { // wait some time till activity is initialized - activity.runOnUiThread { - listenersCopy.forEach { it(activity) } - } - } - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/StandardAutocompleteCallback.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/StandardAutocompleteCallback.kt deleted file mode 100644 index 99a38a69..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/StandardAutocompleteCallback.kt +++ /dev/null @@ -1,20 +0,0 @@ -package net.dankito.banking.ui.android.util - -import android.text.Editable -import com.otaliastudios.autocomplete.AutocompleteCallback - - -open class StandardAutocompleteCallback( - protected val onPopupVisibilityChanged: ((shown: Boolean) -> Unit)? = null, - protected val onPopupItemClicked: ((editable: Editable?, item: T) -> Boolean)? = null -) : AutocompleteCallback { - - override fun onPopupItemClicked(editable: Editable?, item: T): Boolean { - return onPopupItemClicked?.invoke(editable, item) ?: false - } - - override fun onPopupVisibilityChanged(shown: Boolean) { - onPopupVisibilityChanged?.invoke(shown) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/StandardTextWatcher.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/StandardTextWatcher.kt deleted file mode 100644 index 83c69886..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/util/StandardTextWatcher.kt +++ /dev/null @@ -1,27 +0,0 @@ -package net.dankito.banking.ui.android.util - -import android.text.Editable -import android.text.TextWatcher - - -open class StandardTextWatcher( - protected val beforeTextChanged: ((string: CharSequence?, start: Int, count: Int, after: Int) -> Unit)? = null, - protected val onFullParameterizedTextChanged: ((string: CharSequence?, start: Int, before: Int, count: Int) -> Unit)? = null, - protected val afterTextChanged: ((editable: Editable?) -> Unit)? = null, - protected val onTextChanged: ((string: CharSequence) -> Unit)? = null -) : TextWatcher { - - override fun beforeTextChanged(string: CharSequence?, start: Int, count: Int, after: Int) { - beforeTextChanged?.invoke(string, start, count, after) - } - - override fun onTextChanged(string: CharSequence?, start: Int, before: Int, count: Int) { - onTextChanged?.invoke(string ?: "") // can string parameter ever be null? - onFullParameterizedTextChanged?.invoke(string, start, before, count) - } - - override fun afterTextChanged(editable: Editable?) { - afterTextChanged?.invoke(editable) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/AccountDrawerItem.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/AccountDrawerItem.kt deleted file mode 100644 index 2fb24a08..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/AccountDrawerItem.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.dankito.banking.ui.android.views - - -class AccountDrawerItem : SecondaryIconDrawerItem() { - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/BankCredentialsPasswordView.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/BankCredentialsPasswordView.kt deleted file mode 100644 index b394ab05..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/BankCredentialsPasswordView.kt +++ /dev/null @@ -1,41 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.view.inputmethod.EditorInfo -import android.widget.EditText -import android.widget.LinearLayout -import com.google.android.material.textfield.TextInputEditText -import com.google.android.material.textfield.TextInputLayout -import kotlinx.android.synthetic.main.view_bank_credentials_password.view.* -import kotlinx.android.synthetic.main.view_form_edit_text.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.extensions.textString - - -open class BankCredentialsPasswordView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr) { - - - init { - setupUi(context, attrs) - } - - private fun setupUi(context: Context, attrs: AttributeSet?) { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - inflater.inflate(R.layout.view_bank_credentials_password, this, true) - } - - - open var password: String - get() = edtxtPassword.text - set(value) { - edtxtPassword.text = value - } - - open val passwordBox: TextInputEditText - get() = textInputEditText - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/BiometricAuthenticationButton.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/BiometricAuthenticationButton.kt deleted file mode 100644 index d06e27f9..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/BiometricAuthenticationButton.kt +++ /dev/null @@ -1,57 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.LinearLayout -import kotlinx.android.synthetic.main.view_biometric_authentication_button.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.authentication.IBiometricAuthenticationService -import net.dankito.banking.ui.android.di.BankingComponent -import javax.inject.Inject - - -open class BiometricAuthenticationButton @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr) { - - @Inject - protected lateinit var biometricAuthenticationService: IBiometricAuthenticationService - - - open var authenticationSuccessful: (() -> Unit)? = null - - open var customButtonClickHandler: (() -> Unit)? = null - - - init { - BankingComponent.component.inject(this) - - setupUi(context) - } - - private fun setupUi(context: Context) { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rootView = inflater.inflate(R.layout.view_biometric_authentication_button, this, true) - - rootView.apply { - btnStartBiometricAuthentication.setOnClickListener { - customButtonClickHandler?.invoke() ?: doBiometricAuthenticationAndLogIn() - } - } - } - - protected open fun doBiometricAuthenticationAndLogIn() { - biometricAuthenticationService.authenticate { result -> - if (result.successful) { - authenticationSuccessful?.invoke() - } - } - } - - - open fun showBiometricPrompt() { - btnStartBiometricAuthentication.performClick() - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/ChipTanFlickerCodeStripeView.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/ChipTanFlickerCodeStripeView.kt deleted file mode 100644 index a84b3fe1..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/ChipTanFlickerCodeStripeView.kt +++ /dev/null @@ -1,60 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.graphics.Color -import android.util.AttributeSet -import android.view.View -import net.dankito.banking.ui.util.Bit - - -open class ChipTanFlickerCodeStripeView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : View(context, attrs, defStyleAttr) { - - - companion object { - val White = Color.WHITE - val Black = Color.BLACK - } - - - protected var currentColor = 0 - - - init { - drawWhite() - } - - - open fun setStripeVisibility(stripe: Bit) { - setStripeVisibility(stripe.isHigh) - } - - open fun setStripeVisibility(showStripe: Boolean) { - if (showStripe) { - drawWhite() - } - else { - drawBlack() - } - } - - open fun drawWhite() { - drawInColor(White) - } - - open fun drawBlack() { - drawInColor(Black) - } - - open fun drawInColor(color: Int) { - if (color != currentColor) { - setBackgroundColor(color) - - currentColor = color - - invalidate() - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/ChipTanFlickerCodeView.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/ChipTanFlickerCodeView.kt deleted file mode 100644 index 1c580aec..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/ChipTanFlickerCodeView.kt +++ /dev/null @@ -1,242 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.view.View -import android.widget.ImageButton -import android.widget.LinearLayout -import kotlinx.android.synthetic.main.view_flicker_code.view.* -import kotlinx.android.synthetic.main.view_tan_image_size_controls.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.model.tan.FlickerCode -import net.dankito.banking.ui.util.FlickerCodeAnimator -import net.dankito.banking.ui.model.settings.ITanView -import net.dankito.banking.ui.model.settings.TanMethodSettings -import net.dankito.banking.ui.util.Step - - -open class ChipTanFlickerCodeView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr), ITanView { - - companion object { - const val FrequencyStepSize = 2 - const val MinFrequency = 2 - const val MaxFrequency = 40 - const val DefaultFrequency = 30 - - const val StripesHeightStepSize = 7 - const val StripesWidthStepSize = 2 - const val SpaceBetweenStripesStepSize = 1 - } - - - protected lateinit var stripe1: ChipTanFlickerCodeStripeView - protected lateinit var stripe2: ChipTanFlickerCodeStripeView - protected lateinit var stripe3: ChipTanFlickerCodeStripeView - protected lateinit var stripe4: ChipTanFlickerCodeStripeView - protected lateinit var stripe5: ChipTanFlickerCodeStripeView - - protected lateinit var allStripes: List - - protected lateinit var tanGeneratorLeftMarker: View - protected lateinit var tanGeneratorRightMarker: View - - protected lateinit var btnPauseFlickerCode: ImageButton - - protected val animator = FlickerCodeAnimator() - - - protected var stripesHeight = 360 - protected var stripesWidth = 120 - protected var spaceBetweenStripes = 30 - - protected var currentFrequency = DefaultFrequency - - protected var isFlickerCodePaused = false - - - override var didTanMethodSettingsChange: Boolean = false - protected set - - override var tanMethodSettings: TanMethodSettings? = null - protected set - - - init { - setupUi(context) - } - - private fun setupUi(context: Context) { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rootView = inflater.inflate(R.layout.view_flicker_code, this, true) - - rootView.btnDecreaseSize.setOnClickListener { decreaseSize() } - rootView.btnIncreaseSize.setOnClickListener { increaseSize() } - - rootView.btnDecreaseSpeed.setOnClickListener { decreaseFrequency() } - rootView.btnIncreaseSpeed.setOnClickListener { increaseFrequency() } - - btnPauseFlickerCode = rootView.btnPauseFlickerCode - btnPauseFlickerCode.setOnClickListener { togglePauseFlickerCode() } - - stripe1 = rootView.findViewById(R.id.flickerCodeStripe1) - stripe2 = rootView.findViewById(R.id.flickerCodeStripe2) - stripe3 = rootView.findViewById(R.id.flickerCodeStripe3) - stripe4 = rootView.findViewById(R.id.flickerCodeStripe4) - stripe5 = rootView.findViewById(R.id.flickerCodeStripe5) - - allStripes = listOf(stripe1, stripe2, stripe3, stripe4, stripe5) - - stripesHeight = stripe1.layoutParams.height - stripesWidth = stripe1.layoutParams.width - (stripe1.layoutParams as? MarginLayoutParams)?.let { spaceBetweenStripes = it.rightMargin } - - tanGeneratorLeftMarker = rootView.findViewById(R.id.tanGeneratorLeftMarker) - tanGeneratorRightMarker = rootView.findViewById(R.id.tanGeneratorRightMarker) - - setMarkerPositionAfterStripesLayoutSet() - - tanMethodSettings?.let { - setSize(it.width, it.height, it.space) - setFrequency(it.frequency) - } - } - - - override fun onDetachedFromWindow() { - animator.stop() - - super.onDetachedFromWindow() - } - - - - open fun decreaseSize() { - setSize( - stripesWidth - StripesWidthStepSize, - stripesHeight - StripesHeightStepSize, - spaceBetweenStripes - SpaceBetweenStripesStepSize - ) - } - - open fun increaseSize() { - setSize( - stripesWidth + StripesWidthStepSize, - stripesHeight + StripesHeightStepSize, - spaceBetweenStripes + SpaceBetweenStripesStepSize - ) - } - - open fun setSize(width: Int, height: Int, spaceBetweenStripes: Int) { - this.stripesWidth = width - this.stripesHeight = height - this.spaceBetweenStripes = spaceBetweenStripes - - applySize() - } - - protected open fun applySize() { - allStripes.forEach { stripe -> - val params = stripe.layoutParams - params.height = stripesHeight - params.width = stripesWidth - - (params as? MarginLayoutParams)?.let { marginParams -> - if (marginParams.rightMargin > 0) { // don't set a margin right on fifth stripe - marginParams.rightMargin = spaceBetweenStripes - } - } - - stripe.layoutParams = params - } - - requestLayout() - - setMarkerPositionAfterStripesLayoutSet() - - tanMethodSettingsChanged() - } - - protected open fun setMarkerPositionAfterStripesLayoutSet() { - postDelayed({ setMarkerPosition() }, 10L) // we need to wait till layout for stripes is applied before we can set marker positions correctly - } - - protected open fun setMarkerPosition() { - tanGeneratorLeftMarker.x = stripe1.x + (stripe1.width - tanGeneratorLeftMarker.layoutParams.width) / 2 - - tanGeneratorRightMarker.x = stripe5.x + (stripe5.width - tanGeneratorRightMarker.layoutParams.width) / 2 - } - - - open fun decreaseFrequency() { - if (currentFrequency - FrequencyStepSize >= MinFrequency) { - setFrequency(currentFrequency - FrequencyStepSize) - } - } - - open fun increaseFrequency() { - if (currentFrequency + FrequencyStepSize <= MaxFrequency) { - setFrequency(currentFrequency + FrequencyStepSize) - } - } - - open fun setFrequency(frequency: Int) { - currentFrequency = frequency - - animator.setFrequency(frequency) - - tanMethodSettingsChanged() - } - - protected open fun tanMethodSettingsChanged() { - tanMethodSettings = TanMethodSettings(stripesWidth, stripesHeight, spaceBetweenStripes, currentFrequency) - - didTanMethodSettingsChange = true // we don't check if settings really changed, it's not that important - } - - - open fun togglePauseFlickerCode() { - if (isFlickerCodePaused == false) { - animator.pause() - btnPauseFlickerCode.setImageResource(R.drawable.ic_baseline_play_arrow_24) - } - else { - animator.resume() - btnPauseFlickerCode.setImageResource(R.drawable.ic_baseline_pause_24) - } - - isFlickerCodePaused = !!! isFlickerCodePaused - } - - - open fun setCode(flickerCode: FlickerCode, tanMethodSettings: TanMethodSettings?) { - animator.stop() - - tanMethodSettings?.let { - setSize(it.width, it.height, it.space) - setFrequency(it.frequency) - } - ?: run { - setFrequency(DefaultFrequency) - } - - this.tanMethodSettings = tanMethodSettings - this.didTanMethodSettingsChange = false - - animator.animateFlickerCode(flickerCode) { step -> - showStepOnUiThread(step) - } - } - - protected open fun showStepOnUiThread(step: Step) { - - stripe1.setStripeVisibility(step.bit1) - stripe2.setStripeVisibility(step.bit2) - stripe3.setStripeVisibility(step.bit3) - stripe4.setStripeVisibility(step.bit4) - stripe5.setStripeVisibility(step.bit5) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/CollapsibleTextView.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/CollapsibleTextView.kt deleted file mode 100644 index 47f988cb..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/CollapsibleTextView.kt +++ /dev/null @@ -1,73 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.view.View -import android.widget.ScrollView -import kotlinx.android.synthetic.main.view_collapsible_text.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.util.StandardTextWatcher -import net.dankito.utils.android.extensions.asActivity -import net.dankito.utils.android.extensions.setVisibility -import java.util.* -import kotlin.concurrent.schedule - - -open class CollapsibleTextView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : ScrollView(context, attrs, defStyleAttr) { - - companion object { - - const val CountDisplayedLinesWhenCollapsed = 3 - - } - - protected var isCollapsed = true - - - init { - setupUi(context) - } - - private fun setupUi(context: Context) { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rootView = inflater.inflate(R.layout.view_collapsible_text, this, true) - - rootView.apply { - txtvwCollapsibleText.setOnClickListener { toggleIsCollapsed() } - btnExpandCollapseTextView.setOnClickListener { toggleIsCollapsed() } - - txtvwCollapsibleText.addTextChangedListener(StandardTextWatcher { - checkIfExpandCollapseButtonShouldBeDisplayed(context) - }) - } - } - - - protected open fun toggleIsCollapsed() { - if (isCollapsed) { - txtvwCollapsibleText.maxLines = Int.MAX_VALUE - btnExpandCollapseTextView.setImageResource(R.drawable.ic_baseline_expand_less_24) - - isCollapsed = false - } - else { - txtvwCollapsibleText.maxLines = CountDisplayedLinesWhenCollapsed - btnExpandCollapseTextView.setImageResource(R.drawable.ic_baseline_expand_more_24) - - isCollapsed = true - } - } - - protected open fun checkIfExpandCollapseButtonShouldBeDisplayed(context: Context) { - Timer().schedule(500) { // wait some time till txtvwCollapsibleText is layout and lineCount is set - context.asActivity()?.runOnUiThread { - val showExpandButton = isCollapsed == false || txtvwCollapsibleText.lineCount > CountDisplayedLinesWhenCollapsed - btnExpandCollapseTextView.setVisibility(showExpandButton) - } - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/DrawerView.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/DrawerView.kt deleted file mode 100644 index fcf35634..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/DrawerView.kt +++ /dev/null @@ -1,218 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.graphics.drawable.Drawable -import android.view.View -import android.widget.TextView -import androidx.annotation.ColorRes -import androidx.annotation.DrawableRes -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.content.res.AppCompatResources -import androidx.core.graphics.drawable.DrawableCompat -import androidx.core.view.GravityCompat -import androidx.drawerlayout.widget.DrawerLayout -import com.mikepenz.materialdrawer.model.DividerDrawerItem -import com.mikepenz.materialdrawer.model.PrimaryDrawerItem -import com.mikepenz.materialdrawer.model.SecondaryDrawerItem -import com.mikepenz.materialdrawer.model.SectionDrawerItem -import com.mikepenz.materialdrawer.model.interfaces.* -import com.mikepenz.materialdrawer.util.addItems -import com.mikepenz.materialdrawer.util.addItemsAtPosition -import com.mikepenz.materialdrawer.util.getDrawerItem -import com.mikepenz.materialdrawer.util.removeItemByPosition -import com.mikepenz.materialdrawer.widget.MaterialDrawerSliderView -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.dialogs.settings.BankSettingsDialog -import net.dankito.banking.ui.android.dialogs.settings.SettingsDialog -import net.dankito.banking.ui.android.extensions.toDrawable -import net.dankito.banking.ui.model.TypedBankData -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.utils.android.extensions.getColorFromResource -import org.slf4j.LoggerFactory - - -open class DrawerView( - protected val activity: AppCompatActivity, - protected val slider: MaterialDrawerSliderView, - protected val presenter: BankingPresenter -) { - - companion object { - private const val BankLevel = 2 - - private const val AccountLevel = 7 - - private const val AccountsSectionHeaderId = 1000L - private const val AllAccountsId = 1001L - private const val AddAccountId = 1002L - - private const val CountDefaultAccountItems = 5 - private const val CountDefaultAccountItemsAtTop = 3 - - - private val log = LoggerFactory.getLogger(DrawerView::class.java) - } - - - init { - setupDrawerView() - } - - - protected open fun setupDrawerView() { - slider.headerView = activity.layoutInflater.inflate(R.layout.nav_header_main, null) - - showAppVersion(slider.headerView) - - setDefaultDrawerItems() - - presenter.addBanksChangedListener { - activity.runOnUiThread { updateDrawerItems() } - } - - presenter.addSelectedAccountsChangedListener { - activity.runOnUiThread { updateDrawerItems() } - } - - updateDrawerItems() - } - - private fun setDefaultDrawerItems() { - slider.apply { - addItems( - SectionDrawerItem() - .withName(R.string.accounts) - .withIdentifier(AccountsSectionHeaderId) - .withDivider(false) - , - - PrimaryDrawerItem() - .withName(R.string.drawer_menu_all_bank_accounts_title) - .withIdentifier(AllAccountsId) - .withLevel(BankLevel) - .withSelected(true) - .withIcon(getVectorDrawable(R.drawable.ic_accounts, R.color.primaryTextColor_Dark)) - .withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.selectedAllAccounts() } } - , - - PrimaryDrawerItem() - .withName(R.string.add_account) - .withIdentifier(AddAccountId) - .withLevel(BankLevel) - .withIcon(getVectorDrawable(R.drawable.ic_baseline_add_24, R.color.primaryTextColor_Dark)) - .withSelectable(false) - .withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.showAddAccountDialog() } } - , - - DividerDrawerItem() - .withSelectable(false) - , - - PrimaryDrawerItem() - .withName(R.string.settings) - .withIcon(getVectorDrawable(R.drawable.ic_baseline_settings_24, R.color.primaryTextColor_Dark)) - .withSelectable(false) - .withOnDrawerItemClickListener { _, _, _ -> itemClicked { SettingsDialog().show(activity) } } - - ) - } - } - - private fun updateDrawerItems() { - // removes previously shown accounts; index 1 = 'Accounts header', 1 = 'All accounts', index 2 = 'Add account', don't remove these - while (slider.itemAdapter.adapterItems.size > CountDefaultAccountItems) { - slider.removeItemByPosition(CountDefaultAccountItemsAtTop) - } - - val accountItems = createAccountsDrawerItems() - - slider.addItemsAtPosition(CountDefaultAccountItemsAtTop, *accountItems.toTypedArray()) - - slider.getDrawerItem(AllAccountsId)?.let { allAccountsItem -> - if (presenter.areAllAccountSelected) slider.selectExtension.select(allAccountsItem, false) - else slider.selectExtension.deselectByItems(setOf(allAccountsItem)) - } - } - - private fun createAccountsDrawerItems(): List> { - return presenter.allBanksSortedByDisplayIndex.map { account -> - val accountItem = createAccountDrawerItem(account) - - val accountsItems = createBankAccountsDrawerItems(account).toMutableList() - accountsItems.add(0, accountItem) - - return@map accountsItems - }.flatten() - } - - private fun createAccountDrawerItem(bank: TypedBankData): IDrawerItem<*> { - - val accountItem = AccountDrawerItem() - .withName(bank.displayName) - .withLevel(BankLevel) - .withSecondaryIcon(getVectorDrawable(R.drawable.ic_baseline_settings_24, R.color.primaryTextColor_Dark)) - .withOnSecondaryIconClickedListener { closeDrawerAndEditAccount(bank) } - .withIcon(bank.iconData?.toDrawable(activity.resources)) - .withSelected(presenter.isSingleSelectedBank(bank)) - .withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.selectedBank(bank) } } - - if (bank.iconData == null) { - accountItem.withIcon(getVectorDrawable(R.drawable.ic_accounts, R.color.primaryTextColor_Dark)) - } - - - return accountItem - } - - private fun createBankAccountsDrawerItems(bank: TypedBankData): List> { - return bank.visibleAccountsSorted.map { account -> - SecondaryDrawerItem() - .withName(account.displayName) - .withLevel(AccountLevel) - .withSelected(presenter.isSingleSelectedAccount(account)) - .withOnDrawerItemClickListener { _, _, _ -> itemClicked { presenter.selectedAccount(account) } } - } - } - - private fun itemClicked(action: () -> Unit): Boolean { - action() - - return false - } - - private fun closeDrawerAndEditAccount(bank: TypedBankData) { - closeDrawer() - - editAccount(bank) - } - - private fun editAccount(bank: TypedBankData) { - BankSettingsDialog().show(bank, activity) - } - - private fun showAppVersion(navigationHeaderView: View?) { - try { - val packageInfo = activity.packageManager.getPackageInfo(activity.packageName, 0) - val version = packageInfo.versionName - (navigationHeaderView?.findViewById(R.id.txtAppVersion) as? TextView)?.text = version - } catch (e: Exception) { - log.error("Could not read application version") - } - } - - private fun closeDrawer() { - val drawerLayout = activity.findViewById(R.id.drawer_layout) - drawerLayout.closeDrawer(GravityCompat.START) - } - - - private fun getVectorDrawable(@DrawableRes drawableResId: Int, @ColorRes tintColorResId: Int? = null): Drawable? { - val drawable = AppCompatResources.getDrawable(activity, drawableResId) - - if (tintColorResId != null && drawable != null) { - DrawableCompat.setTint(drawable, activity.getColorFromResource(tintColorResId)) - } - - return drawable - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FloatingActionMenuButton.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FloatingActionMenuButton.kt deleted file mode 100644 index a80f5a86..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FloatingActionMenuButton.kt +++ /dev/null @@ -1,78 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.os.Bundle -import android.view.MotionEvent -import com.github.clans.fab.FloatingActionMenu -import net.dankito.utils.android.extensions.isTouchInsideView - - -open class FloatingActionMenuButton(protected val floatingActionMenu: FloatingActionMenu) { - - companion object { - private const val IS_OPENED_EXTRA_NAME = "IS_OPENED" - } - - - private var isClosingMenu = false - - - init { - setup() - } - - - protected open fun setup() { - floatingActionMenu.setClosedOnTouchOutside(true) - floatingActionMenu.setOnMenuToggleListener { isClosingMenu = false } - } - - - protected open fun executeAndCloseMenu(action: () -> Unit) { - action() // first execute action and then close menu as when action sets menu items visibility closeMenu() would otherwise overwrite this value - closeMenu() - } - - protected open fun closeMenu() { - isClosingMenu = true // as closing is animated it takes till animation end till floatingActionMenu.isOpened is set to true - floatingActionMenu.close(true) - } - - - open fun handlesBackButtonPress(): Boolean { - if(floatingActionMenu.isOpened) { - closeMenu() - return true - } - - return false - } - - - open fun handlesTouch(event: MotionEvent): Boolean { - if(floatingActionMenu.isOpened) { // if menu is opened and user clicked somewhere else in the view, close menu - if(floatingActionMenu.isTouchInsideView(event) == false) { - closeMenu() - - return true - } - } - - return false - } - - - open fun saveInstanceState(outState: Bundle?) { - outState?.let { - outState.putBoolean(IS_OPENED_EXTRA_NAME, floatingActionMenu.isOpened && isClosingMenu == false) - } - } - - open fun restoreInstanceState(savedInstanceState: Bundle?) { - savedInstanceState?.let { - if(savedInstanceState.getBoolean(IS_OPENED_EXTRA_NAME, false)) { - floatingActionMenu.open(false) - } - } - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormEditText.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormEditText.kt deleted file mode 100644 index 9431dd4b..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormEditText.kt +++ /dev/null @@ -1,62 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.view.inputmethod.EditorInfo -import android.widget.EditText -import android.widget.LinearLayout -import com.google.android.material.textfield.TextInputLayout -import kotlinx.android.synthetic.main.view_form_edit_text.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.extensions.textString - - -open class FormEditText @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr) { - - - init { - setupUi(context, attrs) - } - - private fun setupUi(context: Context, attrs: AttributeSet?) { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rootView = inflater.inflate(R.layout.view_form_edit_text, this, true) - - rootView.apply { - - context.theme.obtainStyledAttributes( - attrs, - R.styleable.FormEditText, - 0, 0).apply { - - try { - textInputLayout.hint = getString(R.styleable.FormEditText_android_hint) - if (getBoolean(R.styleable.FormEditText_showPasswordToggle, false)) { - textInputLayout.endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE - } - - textInputEditText.setText(getString(R.styleable.FormEditText_android_text)) - textInputEditText.inputType = getInt(R.styleable.FormEditText_android_inputType, EditorInfo.TYPE_TEXT_VARIATION_NORMAL) - textInputEditText.setSelectAllOnFocus(getBoolean(R.styleable.FormEditText_android_selectAllOnFocus, false)) - } finally { - recycle() - } - } - } - } - - - open var text: String - get() = textInputEditText.textString - set(value) = textInputEditText.setText(value) - - open val chars: CharArray - get() = actualEditText.text.toList().toCharArray() - - open val actualEditText: EditText - get() = textInputEditText - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormLabelledValue.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormLabelledValue.kt deleted file mode 100644 index c50568e5..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormLabelledValue.kt +++ /dev/null @@ -1,76 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.view.View -import android.widget.LinearLayout -import android.widget.TextView -import kotlinx.android.synthetic.main.view_form_labelled_value.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.extensions.setTextColorForAmount -import net.dankito.utils.android.extensions.setVisibility -import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.utils.multiplatform.BigDecimal - - -open class FormLabelledValue @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr) { - - protected lateinit var txtLabel: TextView - - protected lateinit var txtValue: TextView - - - init { - setupUi(context, attrs) - } - - private fun setupUi(context: Context, attrs: AttributeSet?) { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rootView = inflater.inflate(R.layout.view_form_labelled_value, this, true) - - rootView.apply { - txtLabel = findViewById(R.id.txtLabel) - txtValue = findViewById(R.id.txtValue) - - context.theme.obtainStyledAttributes( - attrs, - R.styleable.FormLabelledValue, - 0, 0).apply { - - try { - txtLabel.text = getString(R.styleable.FormLabelledValue_android_label) - txtValue.text = getString(R.styleable.FormLabelledValue_android_value) - } finally { - recycle() - } - } - } - } - - - open var label: CharSequence - get() = txtLabel.text - set(value) { - txtLabel.text = value - } - - open var value: CharSequence - get() = txtValue.text - set(value) { - txtValue.text = value - } - - open fun setValueAndVisibilityIfValueIsSet(value: CharSequence?) { - this.setVisibility(value != null) - this.value = value ?: "" - } - - open fun showAmount(presenter: BankingPresenter, amount: BigDecimal, currencyIsoCode: String? = null) { - value = presenter.formatAmount(amount, currencyIsoCode) - txtValue.setTextColorForAmount(amount) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormSectionTitle.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormSectionTitle.kt deleted file mode 100644 index 6cc0eb3d..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormSectionTitle.kt +++ /dev/null @@ -1,50 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.LinearLayout -import androidx.annotation.StringRes -import kotlinx.android.synthetic.main.view_form_section_title.view.* -import net.dankito.banking.ui.android.R - - -open class FormSectionTitle @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : LinearLayout(context, attrs, defStyleAttr) { - - - init { - setupUi(context, attrs) - } - - private fun setupUi(context: Context, attrs: AttributeSet?) { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rootView = inflater.inflate(R.layout.view_form_section_title, this, true) - - rootView.apply { - - context.theme.obtainStyledAttributes( - attrs, - R.styleable.FormEditText, - 0, 0).apply { - - try { - txtvwSectionTitle.text = getString(R.styleable.FormEditText_android_text) - } finally { - recycle() - } - } - } - } - - - open var title: CharSequence - get() = txtvwSectionTitle.text - set(value) = txtvwSectionTitle.setText(value) - - open fun setTitle(@StringRes titleResId: Int) { - this.title = context.getString(titleResId) - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormSelectPeriod.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormSelectPeriod.kt deleted file mode 100644 index 1dfc37bf..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/FormSelectPeriod.kt +++ /dev/null @@ -1,102 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.content.Context -import android.os.Build -import android.util.AttributeSet -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.widget.RelativeLayout -import android.widget.TextView -import net.dankito.banking.ui.android.R - - -open class FormSelectPeriod @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : RelativeLayout(context, attrs, defStyleAttr) { - - protected lateinit var txtLabel: TextView - - protected lateinit var txtValue: TextView - - - init { - setupUi(context, attrs) - } - - private fun setupUi(context: Context, attrs: AttributeSet?) { - val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - val rootView = inflater.inflate(R.layout.view_form_select_period, this, true) - - rootView.apply { - txtLabel = findViewById(R.id.txtLabel) - txtValue = findViewById(R.id.txtValue) - - txtLabel.gravity = Gravity.CENTER_VERTICAL - txtValue.gravity = Gravity.CENTER_VERTICAL - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - txtLabel.textAlignment = View.TEXT_ALIGNMENT_GRAVITY - txtValue.textAlignment = View.TEXT_ALIGNMENT_GRAVITY - } - - this.isEnabled = false // TODO: undo as soon as selecting periods is implemented - - context.theme.obtainStyledAttributes( - attrs, - R.styleable.FormLabelledValue, - 0, 0).apply { - - try { - txtLabel.text = getString(R.styleable.FormSelectPeriod_android_label) - - val defaultValue = Int.MIN_VALUE - val configuredPeriod = getInteger(R.styleable.FormSelectPeriod_periodInMinutes, defaultValue) - periodInMinutes = if (configuredPeriod == defaultValue) null else configuredPeriod - displaySelectedPeriod() - } finally { - recycle() - } - } - } - } - - - protected open fun displaySelectedPeriod() { - txtValue.text = getDisplayTextForSelectedPeriod() - } - - protected open fun getDisplayTextForSelectedPeriod(): String { - periodInMinutes?.let { periodInMinutes -> - if (periodInMinutes > 0) { - if (periodInMinutes < 60) { - return context.getString(R.string.minutes, periodInMinutes) - } - - return context.getString(R.string.hours, (periodInMinutes / 60)) - } - } - - return context.getString(R.string.never) - } - - - open var label: CharSequence - get() = txtLabel.text - set(value) { - txtLabel.text = value - } - - open var periodInMinutes: Int? = null - set(value) { - field = value - displaySelectedPeriod() - } - - override fun setEnabled(enabled: Boolean) { - super.setEnabled(enabled) - - alpha = if (enabled) 1f else 0.5f - } - -} \ No newline at end of file diff --git a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/InfoPopupWindow.kt b/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/InfoPopupWindow.kt deleted file mode 100644 index cdab7f36..00000000 --- a/ui/BankingAndroidApp/src/main/java/net/dankito/banking/ui/android/views/InfoPopupWindow.kt +++ /dev/null @@ -1,38 +0,0 @@ -package net.dankito.banking.ui.android.views - -import android.app.Activity -import android.view.Gravity -import android.view.View -import android.view.ViewGroup -import android.widget.Button -import android.widget.PopupWindow -import androidx.annotation.StringRes -import kotlinx.android.synthetic.main.view_info_popup.view.* -import net.dankito.banking.ui.android.R -import net.dankito.banking.ui.android.extensions.hideKeyboard - - -open class InfoPopupWindow(open val activity: Activity, open val info: String) { - - constructor(activity: Activity, @StringRes infoStringResId: Int) : this(activity, activity.getString(infoStringResId)) - - - open fun show(atLocationOf: View, gravity: Int = Gravity.TOP) { - activity.layoutInflater.inflate(R.layout.view_info_popup, null)?.let { contentView -> - activity.hideKeyboard(atLocationOf) - - contentView.txtInfo.text = info - - val popupWindow = PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) - - popupWindow.isFocusable = true - popupWindow.isOutsideTouchable = true - - contentView.findViewById