From fbb24e7732c071044a0046eeb7d44d1b5906de43 Mon Sep 17 00:00:00 2001 From: dankl Date: Tue, 15 Oct 2019 18:27:06 +0200 Subject: [PATCH] Started Android app --- build.gradle | 5 +- fints4javaAndroidApp/build.gradle | 49 +++++ fints4javaAndroidApp/proguard-rules.pro | 21 +++ .../src/main/AndroidManifest.xml | 28 +++ .../android/Base64ServiceAndroid.kt | 22 +++ .../fints4java/android/MainActivity.kt | 67 +++++++ .../android/ui/MainWindowPresenter.kt | 85 +++++++++ .../ui/adapter/AccountTransactionAdapter.kt | 43 +++++ .../AccountTransactionViewHolder.kt | 23 +++ .../android/ui/dialogs/AddAccountDialog.kt | 143 +++++++++++++++ .../android/ui/home/HomeFragment.kt | 85 +++++++++ .../android/ui/home/HomeViewModel.kt | 13 ++ .../drawable-v24/ic_launcher_foreground.xml | 34 ++++ .../res/drawable/ic_launcher_background.xml | 170 ++++++++++++++++++ .../src/main/res/drawable/side_nav_bar.xml | 9 + .../src/main/res/layout/activity_main.xml | 25 +++ .../src/main/res/layout/app_bar_main.xml | 33 ++++ .../src/main/res/layout/content_main.xml | 20 +++ .../main/res/layout/dialog_add_account.xml | 80 +++++++++ .../src/main/res/layout/fragment_home.xml | 19 ++ .../layout/list_item_account_transaction.xml | 84 +++++++++ .../src/main/res/layout/nav_header_main.xml | 36 ++++ .../main/res/menu/activity_main_drawer.xml | 6 + .../src/main/res/menu/main.xml | 6 + .../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 0 -> 2963 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4905 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2060 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2783 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4490 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6895 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6387 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10413 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9128 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15132 bytes .../main/res/navigation/mobile_navigation.xml | 14 ++ .../src/main/res/values-v21/styles.xml | 8 + .../src/main/res/values/colors.xml | 7 + .../src/main/res/values/dimens.xml | 22 +++ .../src/main/res/values/drawables.xml | 3 + .../src/main/res/values/strings.xml | 19 ++ .../src/main/res/values/styles.xml | 20 +++ settings.gradle | 2 + 44 files changed, 1210 insertions(+), 1 deletion(-) create mode 100644 fints4javaAndroidApp/build.gradle create mode 100644 fints4javaAndroidApp/proguard-rules.pro create mode 100644 fints4javaAndroidApp/src/main/AndroidManifest.xml create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/Base64ServiceAndroid.kt create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/MainWindowPresenter.kt create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/AccountTransactionAdapter.kt create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/viewholder/AccountTransactionViewHolder.kt create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeViewModel.kt create mode 100644 fints4javaAndroidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 fints4javaAndroidApp/src/main/res/drawable/ic_launcher_background.xml create mode 100644 fints4javaAndroidApp/src/main/res/drawable/side_nav_bar.xml create mode 100644 fints4javaAndroidApp/src/main/res/layout/activity_main.xml create mode 100644 fints4javaAndroidApp/src/main/res/layout/app_bar_main.xml create mode 100644 fints4javaAndroidApp/src/main/res/layout/content_main.xml create mode 100644 fints4javaAndroidApp/src/main/res/layout/dialog_add_account.xml create mode 100644 fints4javaAndroidApp/src/main/res/layout/fragment_home.xml create mode 100644 fints4javaAndroidApp/src/main/res/layout/list_item_account_transaction.xml create mode 100644 fints4javaAndroidApp/src/main/res/layout/nav_header_main.xml create mode 100644 fints4javaAndroidApp/src/main/res/menu/activity_main_drawer.xml create mode 100644 fints4javaAndroidApp/src/main/res/menu/main.xml create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 fints4javaAndroidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 fints4javaAndroidApp/src/main/res/navigation/mobile_navigation.xml create mode 100644 fints4javaAndroidApp/src/main/res/values-v21/styles.xml create mode 100644 fints4javaAndroidApp/src/main/res/values/colors.xml create mode 100644 fints4javaAndroidApp/src/main/res/values/dimens.xml create mode 100644 fints4javaAndroidApp/src/main/res/values/drawables.xml create mode 100644 fints4javaAndroidApp/src/main/res/values/strings.xml create mode 100644 fints4javaAndroidApp/src/main/res/values/styles.xml diff --git a/build.gradle b/build.gradle index 96361f4a..5a7a56ba 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,9 @@ ext { appVersionName = '1.0.0-SNAPSHOT' kotlinVersion = '1.3.41' + javaUtilsVersion = '1.0.8' + androidUtilsVersion = '1.1.0' junitVersion = '4.12' assertJVersion = '3.12.2' @@ -12,6 +14,7 @@ ext { mockitoVersion = '2.22.0' mockitoKotlinVersion = '1.6.0' + slf4JVersion = '1.7.26' logbackVersion = '1.2.3' } @@ -23,7 +26,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // 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 diff --git a/fints4javaAndroidApp/build.gradle b/fints4javaAndroidApp/build.gradle new file mode 100644 index 00000000..c4a7b978 --- /dev/null +++ b/fints4javaAndroidApp/build.gradle @@ -0,0 +1,49 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + + + defaultConfig { + applicationId "net.dankito.banking.fints4java.android" + minSdkVersion 15 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation project(':fints4javaLib') +// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + api "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" + + api "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' + } + + api "org.slf4j:slf4j-android:$slf4JVersion" + + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support:design:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'android.arch.navigation:navigation-fragment:1.0.0' + implementation 'android.arch.navigation:navigation-ui:1.0.0' + implementation 'android.arch.lifecycle:extensions:1.1.1' + implementation 'android.arch.navigation:navigation-fragment-ktx:1.0.0' + implementation 'android.arch.navigation:navigation-ui-ktx:1.0.0' +} diff --git a/fints4javaAndroidApp/proguard-rules.pro b/fints4javaAndroidApp/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/fints4javaAndroidApp/proguard-rules.pro @@ -0,0 +1,21 @@ +# 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 diff --git a/fints4javaAndroidApp/src/main/AndroidManifest.xml b/fints4javaAndroidApp/src/main/AndroidManifest.xml new file mode 100644 index 00000000..3bf7c4f2 --- /dev/null +++ b/fints4javaAndroidApp/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/Base64ServiceAndroid.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/Base64ServiceAndroid.kt new file mode 100644 index 00000000..271cbd89 --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/Base64ServiceAndroid.kt @@ -0,0 +1,22 @@ +package net.dankito.banking.fints4java.android + +import android.util.Base64 +import net.dankito.fints.util.IBase64Service +import java.nio.charset.Charset + + +open class Base64ServiceAndroid : IBase64Service { + + override fun encode(text: String, charset: Charset): String { + val bytes = text.toByteArray(charset) + + return Base64.encodeToString(bytes, Base64.NO_WRAP) + } + + override fun decode(base64: String, charset: Charset): String { + val decoded = Base64.decode(base64, Base64.NO_WRAP) + + return String(decoded, charset) + } + +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt new file mode 100644 index 00000000..b37a5b21 --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt @@ -0,0 +1,67 @@ +package net.dankito.banking.fints4java.android + +import android.os.Bundle +import android.support.design.widget.FloatingActionButton +import android.support.design.widget.NavigationView +import android.support.v4.widget.DrawerLayout +import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.Toolbar +import android.view.Menu +import androidx.navigation.findNavController +import net.dankito.banking.fints4java.android.ui.MainWindowPresenter +import net.dankito.banking.fints4java.android.ui.dialogs.AddAccountDialog + +class MainActivity : AppCompatActivity() { + +// private lateinit var appBarConfiguration: AppBarConfiguration + + val presenter = MainWindowPresenter() + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + initUi() + } + + private fun initUi() { + setContentView(R.layout.activity_main) + + val toolbar: Toolbar = findViewById(R.id.toolbar) + setSupportActionBar(toolbar) + + val fab: FloatingActionButton = findViewById(R.id.fab) + fab.setOnClickListener { view -> + AddAccountDialog().show(this, presenter) + } + + val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout) + val navView: NavigationView = findViewById(R.id.nav_view) + val navController = findNavController(R.id.nav_host_fragment) + +// // Passing each menu ID as a set of Ids because each +// // menu should be considered as top level destinations. +// appBarConfiguration = AppBarConfiguration( +// setOf( +// R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow, +// R.id.nav_tools, R.id.nav_share, R.id.nav_send +// ), drawerLayout +// ) +// +// setupActionBarWithNavController(navController, appBarConfiguration) +// navView.setupWithNavController(navController) + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + // Inflate the menu; this adds items to the action bar if it is present. + menuInflater.inflate(R.menu.main, menu) + + return true + } + +// override fun onSupportNavigateUp(): Boolean { +// val navController = findNavController(R.id.nav_host_fragment) +// return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() +// } + +} diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/MainWindowPresenter.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/MainWindowPresenter.kt new file mode 100644 index 00000000..b69f193e --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/MainWindowPresenter.kt @@ -0,0 +1,85 @@ +package net.dankito.banking.fints4java.android.ui + +import net.dankito.banking.fints4java.android.Base64ServiceAndroid +import net.dankito.fints.FinTsClient +import net.dankito.fints.FinTsClientCallback +import net.dankito.fints.banks.BankFinder +import net.dankito.fints.model.BankData +import net.dankito.fints.model.BankInfo +import net.dankito.fints.model.CustomerData +import net.dankito.fints.model.TanProcedure +import net.dankito.fints.model.mapper.BankDataMapper +import net.dankito.fints.response.client.FinTsClientResponse +import net.dankito.fints.response.client.GetTransactionsResponse +import net.dankito.utils.IThreadPool +import net.dankito.utils.ThreadPool + + +open class MainWindowPresenter { + + protected val callback = object : FinTsClientCallback { + + override fun askUserForTanProcedure(supportedTanProcedures: List): TanProcedure? { + // TODO: show dialog and ask user + return supportedTanProcedures.first() + } + + } + + protected val finTsClient = FinTsClient(callback, Base64ServiceAndroid()) + + protected val bankFinder: BankFinder = BankFinder() + + protected val threadPool: IThreadPool = ThreadPool() + + protected val bankDataMapper = BankDataMapper() + + + protected val accountAddedListeners = mutableListOf<(BankData, CustomerData) -> Unit>() + + + open fun checkIfAccountExists(bankInfo: BankInfo, customerId: String, pin: String, + callback: (FinTsClientResponse) -> Unit) { + + val bank = bankDataMapper.mapFromBankInfo(bankInfo) + val customer = CustomerData(customerId, pin) + + finTsClient.checkIfAccountExistsAsync(bank, customer) { response -> + if (response.isSuccessful) { + callAccountAddedListeners(bank, customer) + } + + callback(response) + } + } + + + open fun getAccountTransactionsAsync(bank: BankData, customer: CustomerData, + callback: (GetTransactionsResponse) -> Unit) { + + finTsClient.tryGetTransactionsOfLast90DaysWithoutTanAsync(bank, customer, callback) + } + + + open fun searchForBankAsync(enteredBankCode: String, callback: (List) -> Unit) { + threadPool.runAsync { + callback(searchForBank(enteredBankCode)) + } + } + + open fun searchForBank(enteredBankCode: String): List { + return bankFinder.findBankByBankCode(enteredBankCode) + } + + + open fun addAccountAddedListener(listener: (BankData, CustomerData) -> Unit) { + accountAddedListeners.add(listener) + } + + protected open fun callAccountAddedListeners(bank: BankData, customer: CustomerData) { + ArrayList(accountAddedListeners).forEach { + it(bank, customer) // TODO: use RxJava for this + } + } + +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/AccountTransactionAdapter.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/AccountTransactionAdapter.kt new file mode 100644 index 00000000..b05970aa --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/AccountTransactionAdapter.kt @@ -0,0 +1,43 @@ +package net.dankito.banking.fints4java.android.ui.adapter + +import android.view.View +import net.dankito.banking.fints4java.android.R +import net.dankito.banking.fints4java.android.ui.adapter.viewholder.AccountTransactionViewHolder +import net.dankito.fints.model.AccountTransaction +import net.dankito.utils.android.extensions.setTextColorToColorResource +import net.dankito.utils.android.ui.adapter.ListRecyclerAdapter +import java.math.BigDecimal +import java.text.DateFormat + + +open class AccountTransactionAdapter + : ListRecyclerAdapter() { + + companion object { + val BookingDateFormat = DateFormat.getDateInstance(DateFormat.SHORT) + } + + + override fun getListItemLayoutId() = R.layout.list_item_account_transaction + + override fun createViewHolder(itemView: View): AccountTransactionViewHolder { + return AccountTransactionViewHolder(itemView) + } + + override fun bindItemToView(viewHolder: AccountTransactionViewHolder, item: AccountTransaction) { + viewHolder.txtvwBookingDate.text = BookingDateFormat.format(item.bookingDate) + + viewHolder.txtvwBookingText.text = item.bookingText ?: "" + + viewHolder.txtvwOtherPartyName.text = item.otherPartyName ?: "" + + viewHolder.txtvwUsage1.text = item.usage + + viewHolder.txtvwUsage2.visibility = View.GONE // TODO + viewHolder.txtvwUsage2.text = "" // TODO + + viewHolder.txtvwAmount.text = item.amount.toString() + viewHolder.txtvwAmount.setTextColorToColorResource(if (item.amount >= BigDecimal.ZERO) R.color.positiveAmount else R.color.negativeAmount) + } + +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/viewholder/AccountTransactionViewHolder.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/viewholder/AccountTransactionViewHolder.kt new file mode 100644 index 00000000..b0169615 --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/adapter/viewholder/AccountTransactionViewHolder.kt @@ -0,0 +1,23 @@ +package net.dankito.banking.fints4java.android.ui.adapter.viewholder + +import android.support.v7.widget.RecyclerView +import android.view.View +import android.widget.TextView +import kotlinx.android.synthetic.main.list_item_account_transaction.view.* + + +class AccountTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + + val txtvwBookingDate: TextView = itemView.txtvwBookingDate + + val txtvwBookingText: TextView = itemView.txtvwBookingText + + val txtvwOtherPartyName: TextView = itemView.txtvwOtherPartyName + + val txtvwUsage1: TextView = itemView.txtvwUsage1 + + val txtvwUsage2: TextView = itemView.txtvwUsage2 + + val txtvwAmount: TextView = itemView.txtvwAmount + +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt new file mode 100644 index 00000000..50a3b103 --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt @@ -0,0 +1,143 @@ +package net.dankito.banking.fints4java.android.ui.dialogs + +import android.os.Bundle +import android.support.v4.app.DialogFragment +import android.support.v7.app.AlertDialog +import android.support.v7.app.AppCompatActivity +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import kotlinx.android.synthetic.main.dialog_add_account.* +import kotlinx.android.synthetic.main.dialog_add_account.view.* +import net.dankito.banking.fints4java.android.R +import net.dankito.banking.fints4java.android.ui.MainWindowPresenter +import net.dankito.fints.model.BankInfo +import net.dankito.fints.response.client.FinTsClientResponse +import net.dankito.utils.android.extensions.asActivity + + +class AddAccountDialog : DialogFragment() { + + companion object { + const val DialogTag = "AddAccountDialog" + } + + + private lateinit var presenter: MainWindowPresenter + + private var selectedBank: BankInfo? = null + + + fun show(activity: AppCompatActivity, presenter: MainWindowPresenter, fullscreen: Boolean = false) { + this.presenter = presenter + + val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.Dialog + 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 + } + + private fun setupUI(rootView: View) { + rootView.edtxtBankCode.addTextChangedListener(bankCodeChangedWatcher) + + rootView.edtxtCustomerId.addTextChangedListener(otherEditTextChangedWatcher) + rootView.edtxtPin.addTextChangedListener(otherEditTextChangedWatcher) + + rootView.btnSelect.setOnClickListener { addAccount() } + rootView.btnCancel.setOnClickListener { dismiss() } + } + + private fun addAccount() { + selectedBank?.let { selectedBank -> // should always be non-null at this stage + val customerId = edtxtCustomerId.text.toString() + val pin = edtxtPin.text.toString() + + presenter.checkIfAccountExists(selectedBank, customerId, pin) { response -> + context?.asActivity()?.runOnUiThread { + handleAccountCheckResponseOnUiThread(response) + } + } + } + } + + private fun handleAccountCheckResponseOnUiThread(response: FinTsClientResponse) { + context?.let { context -> + if (response.isSuccessful) { + AlertDialog.Builder(context) + .setMessage("Successfully added account") + .setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() } + .show() + this.dismiss() + } + else { + AlertDialog.Builder(context).setMessage("Could not add account: ${response.exception ?: response.errorsToShowToUser.joinToString("\n")}").show() + } + } + } + + + val bankCodeChangedWatcher = object : TextWatcher { + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } + + override fun onTextChanged(enteredText: CharSequence?, start: Int, before: Int, count: Int) { + enteredText?.let { searchForBankAsync(enteredText) } + } + + override fun afterTextChanged(s: Editable?) { } + + } + + 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?) { } + + } + + private fun searchForBankAsync(enteredBankCode: CharSequence) { + presenter.searchForBankAsync(enteredBankCode.toString()) { foundBanks -> + context?.asActivity()?.runOnUiThread { + showFoundBanksOnUiThread(foundBanks) + } + } + } + + private fun showFoundBanksOnUiThread(foundBanks: List) { + if (foundBanks.isNotEmpty()) { + selectedBank = foundBanks.first() + } + else { + selectedBank = null + } + + checkIfRequiredDataEnteredOnUiThread() + } + + private fun checkIfRequiredDataEnteredOnUiThread() { + val requiredDataEntered = selectedBank != null + && edtxtCustomerId.text.toString().isNotEmpty() // TODO: check if it is of length 10? + && edtxtPin.text.toString().isNotEmpty() // TODO: check if it is of length 5? + + btnSelect.isEnabled = requiredDataEntered + } + +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt new file mode 100644 index 00000000..e3e88bb9 --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt @@ -0,0 +1,85 @@ +package net.dankito.banking.fints4java.android.ui.home + +import android.arch.lifecycle.ViewModelProviders +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import net.dankito.banking.fints4java.android.MainActivity +import net.dankito.banking.fints4java.android.R +import net.dankito.banking.fints4java.android.ui.MainWindowPresenter +import net.dankito.banking.fints4java.android.ui.adapter.AccountTransactionAdapter +import net.dankito.fints.model.BankData +import net.dankito.fints.model.CustomerData +import net.dankito.utils.android.extensions.asActivity +import org.slf4j.LoggerFactory + + +class HomeFragment : Fragment() { + + companion object { + private val log = LoggerFactory.getLogger(HomeFragment::class.java) + } + + + private lateinit var homeViewModel: HomeViewModel + + private val transactionAdapter = AccountTransactionAdapter() + + + private lateinit var presenter: MainWindowPresenter + + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + homeViewModel = + ViewModelProviders.of(this).get(HomeViewModel::class.java) + val root = inflater.inflate(R.layout.fragment_home, container, false) +// val textView: TextView = root.findViewById(R.id.text_home) +// homeViewModel.text.observe(this, Observer { +// textView.text = it +// }) + + + val rcyvwAccountTransactions: RecyclerView = root.findViewById(R.id.rcyvwAccountTransactions) + rcyvwAccountTransactions.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + rcyvwAccountTransactions.adapter = transactionAdapter + + initLogic() + + return root + } + + + private fun initLogic() { + + // TODO: this is such a bad code style + (context as? MainActivity)?.presenter?.let { presenter -> + this.presenter = presenter + + presenter.addAccountAddedListener { bank, customer -> + retrieveAccountTransactions(bank, customer) + } + } + } + + private fun retrieveAccountTransactions(bank: BankData, customer: CustomerData) { + presenter.getAccountTransactionsAsync(bank, customer) { response -> + context?.asActivity()?.runOnUiThread { + if (response.isSuccessful) { + transactionAdapter.items = response.bookedTransactions + } + else { + // TODO: show error + } + } + } + } + +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeViewModel.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeViewModel.kt new file mode 100644 index 00000000..e801d897 --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeViewModel.kt @@ -0,0 +1,13 @@ +package net.dankito.banking.fints4java.android.ui.home + +import android.arch.lifecycle.LiveData +import android.arch.lifecycle.MutableLiveData +import android.arch.lifecycle.ViewModel + +class HomeViewModel : ViewModel() { + + private val _text = MutableLiveData().apply { + value = "This is home Fragment" + } + val text: LiveData = _text +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml b/fints4javaAndroidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000..e86fe0a9 --- /dev/null +++ b/fints4javaAndroidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/fints4javaAndroidApp/src/main/res/drawable/ic_launcher_background.xml b/fints4javaAndroidApp/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..e2561079 --- /dev/null +++ b/fints4javaAndroidApp/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fints4javaAndroidApp/src/main/res/drawable/side_nav_bar.xml b/fints4javaAndroidApp/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 00000000..f9628c21 --- /dev/null +++ b/fints4javaAndroidApp/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/res/layout/activity_main.xml b/fints4javaAndroidApp/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..f4df16d8 --- /dev/null +++ b/fints4javaAndroidApp/src/main/res/layout/activity_main.xml @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/fints4javaAndroidApp/src/main/res/layout/app_bar_main.xml b/fints4javaAndroidApp/src/main/res/layout/app_bar_main.xml new file mode 100644 index 00000000..61e654a7 --- /dev/null +++ b/fints4javaAndroidApp/src/main/res/layout/app_bar_main.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/res/layout/content_main.xml b/fints4javaAndroidApp/src/main/res/layout/content_main.xml new file mode 100644 index 00000000..b7cf46c2 --- /dev/null +++ b/fints4javaAndroidApp/src/main/res/layout/content_main.xml @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/res/layout/dialog_add_account.xml b/fints4javaAndroidApp/src/main/res/layout/dialog_add_account.xml new file mode 100644 index 00000000..17698d04 --- /dev/null +++ b/fints4javaAndroidApp/src/main/res/layout/dialog_add_account.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + +