Implemented reading QR coding and if it is a EPC QR code navigating to TransferMoneyDialog
This commit is contained in:
parent
4ef8e7330f
commit
64cb4ca9e2
|
@ -55,6 +55,8 @@ ext {
|
||||||
|
|
||||||
autocompleteVersion = "1.1.0"
|
autocompleteVersion = "1.1.0"
|
||||||
|
|
||||||
|
zxingVersion = "3.3.0"
|
||||||
|
|
||||||
multiDexVersion = "2.0.1"
|
multiDexVersion = "2.0.1"
|
||||||
|
|
||||||
appCompatVersion = "1.1.0"
|
appCompatVersion = "1.1.0"
|
||||||
|
@ -149,6 +151,7 @@ task jarAll {
|
||||||
"fints4k:jvm6Jar",
|
"fints4k:jvm6Jar",
|
||||||
"fints4k-jvm:jar",
|
"fints4k-jvm:jar",
|
||||||
"BankFinder:jvmJar",
|
"BankFinder:jvmJar",
|
||||||
|
"EpcQrCodeParser:jvmJar",
|
||||||
"BankingUiCommon:jvmJar",
|
"BankingUiCommon:jvmJar",
|
||||||
"fints4kBankingClient:jvmJar",
|
"fints4kBankingClient:jvmJar",
|
||||||
"BankingUiCommon:jvmJar",
|
"BankingUiCommon:jvmJar",
|
||||||
|
@ -162,6 +165,7 @@ task packAllForXcode {
|
||||||
"common:packForXcode",
|
"common:packForXcode",
|
||||||
"fints4k:packForXcode",
|
"fints4k:packForXcode",
|
||||||
"BankFinder:packForXcode",
|
"BankFinder:packForXcode",
|
||||||
|
"EpcQrCodeParser:packForXcode",
|
||||||
"BankingUiCommon:packForXcode",
|
"BankingUiCommon:packForXcode",
|
||||||
"fints4kBankingClient:packForXcode",
|
"fints4kBankingClient:packForXcode",
|
||||||
"BankingUiNativeIntegration:packForXcode"
|
"BankingUiNativeIntegration:packForXcode"
|
||||||
|
|
|
@ -106,6 +106,9 @@ dependencies {
|
||||||
|
|
||||||
implementation "com.otaliastudios:autocomplete:$autocompleteVersion"
|
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 "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion"
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest
|
||||||
package="net.dankito.banking.ui.android">
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="net.dankito.banking.ui.android"
|
||||||
|
>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||||
|
|
||||||
|
<!-- Both are required for ZXing -->
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
|
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
|
||||||
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name="net.dankito.banking.ui.android.BankingApp"
|
android:name="net.dankito.banking.ui.android.BankingApp"
|
||||||
|
@ -15,7 +23,9 @@
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:hardwareAccelerated="true"
|
||||||
|
android:theme="@style/AppTheme"
|
||||||
|
>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.LandingActivity"
|
android:name=".activities.LandingActivity"
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
package net.dankito.banking.ui.android
|
package net.dankito.banking.ui.android
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.core.os.postDelayed
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
import com.github.clans.fab.FloatingActionMenu
|
import com.github.clans.fab.FloatingActionMenu
|
||||||
|
import com.google.zxing.integration.android.IntentIntegrator
|
||||||
|
import com.google.zxing.integration.android.IntentResult
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
|
import net.codinux.banking.tools.epcqrcode.ParseEpcQrCodeResult
|
||||||
|
import net.dankito.banking.ui.android.activities.BaseActivity
|
||||||
import net.dankito.banking.ui.android.di.BankingComponent
|
import net.dankito.banking.ui.android.di.BankingComponent
|
||||||
import net.dankito.banking.ui.android.di.BankingModule
|
import net.dankito.banking.ui.android.di.BankingModule
|
||||||
import net.dankito.banking.ui.android.activities.BaseActivity
|
|
||||||
import net.dankito.banking.ui.android.views.DrawerView
|
import net.dankito.banking.ui.android.views.DrawerView
|
||||||
import net.dankito.banking.ui.android.views.MainActivityFloatingActionMenuButton
|
import net.dankito.banking.ui.android.views.MainActivityFloatingActionMenuButton
|
||||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||||
|
@ -87,6 +98,48 @@ class MainActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, 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 {
|
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
||||||
if(floatingActionMenuButton.handlesTouch(event)) { // close menu when menu is opened and touch is outside floatingActionMenuButton
|
if(floatingActionMenuButton.handlesTouch(event)) { // close menu when menu is opened and touch is outside floatingActionMenuButton
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package net.dankito.banking.ui.android.views
|
package net.dankito.banking.ui.android.views
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import com.github.clans.fab.FloatingActionButton
|
import com.github.clans.fab.FloatingActionButton
|
||||||
import com.github.clans.fab.FloatingActionMenu
|
import com.github.clans.fab.FloatingActionMenu
|
||||||
|
import com.google.zxing.integration.android.IntentIntegrator
|
||||||
import kotlinx.android.synthetic.main.view_floating_action_button_main.view.*
|
import kotlinx.android.synthetic.main.view_floating_action_button_main.view.*
|
||||||
import net.dankito.utils.multiplatform.toFile
|
import net.dankito.utils.multiplatform.toFile
|
||||||
import net.dankito.banking.ui.android.R
|
import net.dankito.banking.ui.android.R
|
||||||
|
@ -27,6 +29,8 @@ open class MainActivityFloatingActionMenuButton(
|
||||||
|
|
||||||
protected lateinit var fabTransferMoney: FloatingActionButton
|
protected lateinit var fabTransferMoney: FloatingActionButton
|
||||||
|
|
||||||
|
protected lateinit var fabMoneyTransferFromScanningQrCode: FloatingActionButton
|
||||||
|
|
||||||
protected lateinit var fabTransferMoneyFromPdf: FloatingActionButton
|
protected lateinit var fabTransferMoneyFromPdf: FloatingActionButton
|
||||||
|
|
||||||
protected var lastSelectedFolder: File? = null
|
protected var lastSelectedFolder: File? = null
|
||||||
|
@ -51,14 +55,19 @@ open class MainActivityFloatingActionMenuButton(
|
||||||
}
|
}
|
||||||
|
|
||||||
fabTransferMoney = floatingActionMenu.fabTransferMoney
|
fabTransferMoney = floatingActionMenu.fabTransferMoney
|
||||||
|
fabMoneyTransferFromScanningQrCode = floatingActionMenu.fabMoneyTransferFromScanningQrCode
|
||||||
fabTransferMoneyFromPdf = floatingActionMenu.fabTransferMoneyFromPdf
|
fabTransferMoneyFromPdf = floatingActionMenu.fabTransferMoneyFromPdf
|
||||||
|
|
||||||
fabTransferMoney.setOnClickListener {
|
fabTransferMoney.setOnClickListener {
|
||||||
executeAndCloseMenu { presenter.showTransferMoneyDialog() }
|
executeAndCloseMenu { presenter.showTransferMoneyDialog() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fabMoneyTransferFromScanningQrCode.setOnClickListener {
|
||||||
|
executeAndCloseMenu { scanQrCode() }
|
||||||
|
}
|
||||||
|
|
||||||
fabTransferMoneyFromPdf.setOnClickListener {
|
fabTransferMoneyFromPdf.setOnClickListener {
|
||||||
executeAndCloseMenu { transferMoneyWithDataFromPdf() }
|
executeAndCloseMenu { showTransferMoneyDialogWithDataFromPdf() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,11 +76,27 @@ open class MainActivityFloatingActionMenuButton(
|
||||||
protected open fun checkIfThereAreAccountsThatCanTransferMoney() {
|
protected open fun checkIfThereAreAccountsThatCanTransferMoney() {
|
||||||
fabTransferMoney.isEnabled = presenter.hasAccountsSupportTransferringMoney
|
fabTransferMoney.isEnabled = presenter.hasAccountsSupportTransferringMoney
|
||||||
|
|
||||||
|
fabMoneyTransferFromScanningQrCode.isEnabled = presenter.hasAccountsSupportTransferringMoney
|
||||||
|
|
||||||
fabTransferMoneyFromPdf.isEnabled = presenter.hasAccountsSupportTransferringMoney
|
fabTransferMoneyFromPdf.isEnabled = presenter.hasAccountsSupportTransferringMoney
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open fun transferMoneyWithDataFromPdf() {
|
protected open fun scanQrCode() {
|
||||||
|
permissionsService.checkPermission(Manifest.permission.CAMERA, R.string.rationale_camera_permission_to_scan_qr_code) { _, isGranted ->
|
||||||
|
if (isGranted) {
|
||||||
|
floatingActionMenu.context.asActivity()?.let { activity ->
|
||||||
|
val intentIntegrator = IntentIntegrator(activity)
|
||||||
|
intentIntegrator.setOrientationLocked(false)
|
||||||
|
intentIntegrator.initiateScan(listOf(IntentIntegrator.QR_CODE))
|
||||||
|
|
||||||
|
// parsing decoded QR-code and showing TransferMoneyDialog is done in MainActivity.handleQrCodeScanResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun showTransferMoneyDialogWithDataFromPdf() {
|
||||||
(floatingActionMenu.context.asActivity() as? FragmentActivity)?.let { activity ->
|
(floatingActionMenu.context.asActivity() as? FragmentActivity)?.let { activity ->
|
||||||
val config = FileChooserDialogConfig(listOf("*.pdf"), lastSelectedFolder)
|
val config = FileChooserDialogConfig(listOf("*.pdf"), lastSelectedFolder)
|
||||||
|
|
||||||
|
@ -79,17 +104,17 @@ open class MainActivityFloatingActionMenuButton(
|
||||||
selectedFile?.let {
|
selectedFile?.let {
|
||||||
lastSelectedFolder = selectedFile.parentFile
|
lastSelectedFolder = selectedFile.parentFile
|
||||||
|
|
||||||
val result = presenter.transferMoneyWithDataFromPdf(selectedFile.toFile())
|
val result = presenter.showTransferMoneyDialogWithDataFromPdf(selectedFile.toFile())
|
||||||
|
|
||||||
if (result.type != ExtractTransferMoneyDataFromPdfResultType.Success) {
|
if (result.type != ExtractTransferMoneyDataFromPdfResultType.Success) {
|
||||||
showTransferMoneyWithDataFromPdfError(activity, selectedFile, result)
|
showTransferMoneyDialogWithDataFromPdfError(activity, selectedFile, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun showTransferMoneyWithDataFromPdfError(context: Context, pdfFile: File, result: ExtractTransferMoneyDataFromPdfResult) {
|
protected open fun showTransferMoneyDialogWithDataFromPdfError(context: Context, pdfFile: File, result: ExtractTransferMoneyDataFromPdfResult) {
|
||||||
val errorMessage = when (result.type) {
|
val errorMessage = when (result.type) {
|
||||||
ExtractTransferMoneyDataFromPdfResultType.NotASearchablePdf ->
|
ExtractTransferMoneyDataFromPdfResultType.NotASearchablePdf ->
|
||||||
context.getString(R.string.transfer_money_from_pdf_error_message_not_a_searchable_pdf, pdfFile.absolutePath)
|
context.getString(R.string.transfer_money_from_pdf_error_message_not_a_searchable_pdf, pdfFile.absolutePath)
|
||||||
|
|
|
@ -25,6 +25,14 @@
|
||||||
fab:fab_label="@string/floating_action_menu_transfer_money_from_pdf"
|
fab:fab_label="@string/floating_action_menu_transfer_money_from_pdf"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<com.github.clans.fab.FloatingActionButton
|
||||||
|
android:id="@+id/fabMoneyTransferFromScanningQrCode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/MenuButtonsStyle"
|
||||||
|
fab:fab_label="@string/floating_action_menu_money_transfer_from_scanning_qr_code"
|
||||||
|
/>
|
||||||
|
|
||||||
<com.github.clans.fab.FloatingActionButton
|
<com.github.clans.fab.FloatingActionButton
|
||||||
android:id="@+id/fabTransferMoney"
|
android:id="@+id/fabTransferMoney"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -63,8 +63,11 @@
|
||||||
|
|
||||||
<string name="floating_action_menu_add_account">Konto</string>
|
<string name="floating_action_menu_add_account">Konto</string>
|
||||||
<string name="floating_action_menu_transfer_money">Überweisung</string>
|
<string name="floating_action_menu_transfer_money">Überweisung</string>
|
||||||
|
<string name="floating_action_menu_money_transfer_from_scanning_qr_code">Überweisung aus QR-Code</string>
|
||||||
<string name="floating_action_menu_transfer_money_from_pdf">Überweisung aus PDF</string>
|
<string name="floating_action_menu_transfer_money_from_pdf">Überweisung aus PDF</string>
|
||||||
|
|
||||||
|
<string name="rationale_camera_permission_to_scan_qr_code">Um QR-Codes scannen zu können wird der Zugriff auf die Kamera benötigt.</string>
|
||||||
|
|
||||||
<string name="menu_home">Umsätze</string>
|
<string name="menu_home">Umsätze</string>
|
||||||
|
|
||||||
<string name="menu_main_update_transactions">Umsätze aktualisieren</string>
|
<string name="menu_main_update_transactions">Umsätze aktualisieren</string>
|
||||||
|
@ -107,6 +110,8 @@
|
||||||
<string name="dialog_transfer_money_message_transfer_successful">%1$s %2$s wurden erfolgreich an %3$s überwiesen.</string>
|
<string name="dialog_transfer_money_message_transfer_successful">%1$s %2$s wurden erfolgreich an %3$s überwiesen.</string>
|
||||||
<string name="dialog_transfer_money_message_transfer_failed">Konnte nicht %1$s %2$s an %3$s überweisen.\n\nFehlermeldung Ihrer Bank:\n\n%4$s</string>
|
<string name="dialog_transfer_money_message_transfer_failed">Konnte nicht %1$s %2$s an %3$s überweisen.\n\nFehlermeldung Ihrer Bank:\n\n%4$s</string>
|
||||||
|
|
||||||
|
<string name="money_transfer_from_scanning_qr_code_error">Überweisungsdaten konnten nicht aus QR-Code gelesen werden: %1$s\n\Gelesener QR-Code ist:\n%2$s</string>
|
||||||
|
|
||||||
<string name="transfer_money_from_pdf_error_message_not_a_searchable_pdf">Konnte Text nicht aus Datei "%1$s" extrahieren. Enthält die Datei auch Text oder nur Bilder?</string>
|
<string name="transfer_money_from_pdf_error_message_not_a_searchable_pdf">Konnte Text nicht aus Datei "%1$s" extrahieren. Enthält die Datei auch Text oder nur Bilder?</string>
|
||||||
<string name="transfer_money_from_pdf_error_message_could_not_extract_text">Text konnte nicht aus Datei "%1$s" extrahiert werden:\n\n%2$s</string>
|
<string name="transfer_money_from_pdf_error_message_could_not_extract_text">Text konnte nicht aus Datei "%1$s" extrahiert werden:\n\n%2$s</string>
|
||||||
<string name="transfer_money_from_pdf_error_message_could_not_extract_invoice_data">Überweisungsdaten konnten aus der Datei "%1$s" nicht ausgelesen werden:\n\n%2$s</string>
|
<string name="transfer_money_from_pdf_error_message_could_not_extract_invoice_data">Überweisungsdaten konnten aus der Datei "%1$s" nicht ausgelesen werden:\n\n%2$s</string>
|
||||||
|
|
|
@ -63,8 +63,11 @@
|
||||||
|
|
||||||
<string name="floating_action_menu_add_account">Account</string>
|
<string name="floating_action_menu_add_account">Account</string>
|
||||||
<string name="floating_action_menu_transfer_money">Transfer money</string>
|
<string name="floating_action_menu_transfer_money">Transfer money</string>
|
||||||
|
<string name="floating_action_menu_money_transfer_from_scanning_qr_code">Money transfer from scanning QR-Code</string>
|
||||||
<string name="floating_action_menu_transfer_money_from_pdf">Transfer money from PDF</string>
|
<string name="floating_action_menu_transfer_money_from_pdf">Transfer money from PDF</string>
|
||||||
|
|
||||||
|
<string name="rationale_camera_permission_to_scan_qr_code">To scan QR-Codes permission to access camera is required.</string>
|
||||||
|
|
||||||
<string name="menu_home">Home</string>
|
<string name="menu_home">Home</string>
|
||||||
|
|
||||||
<string name="menu_main_update_transactions">Update transactions</string>
|
<string name="menu_main_update_transactions">Update transactions</string>
|
||||||
|
@ -107,6 +110,8 @@
|
||||||
<string name="dialog_transfer_money_message_transfer_successful">Successfully transferred %1$s %2$s to %3$s.</string>
|
<string name="dialog_transfer_money_message_transfer_successful">Successfully transferred %1$s %2$s to %3$s.</string>
|
||||||
<string name="dialog_transfer_money_message_transfer_failed">Could not transfer %1$s %2$s to %3$s.\n\nError message from your bank:\n\n%4$s</string>
|
<string name="dialog_transfer_money_message_transfer_failed">Could not transfer %1$s %2$s to %3$s.\n\nError message from your bank:\n\n%4$s</string>
|
||||||
|
|
||||||
|
<string name="money_transfer_from_scanning_qr_code_error">Could not extract transfer data from QR-Code: %1$s\n\nExtracted QR-Code was:\n%2$s</string>
|
||||||
|
|
||||||
<string name="transfer_money_from_pdf_error_message_not_a_searchable_pdf">File "%1$s" is not a searchable PDF. Could therefore not extract text from it.</string>
|
<string name="transfer_money_from_pdf_error_message_not_a_searchable_pdf">File "%1$s" is not a searchable PDF. Could therefore not extract text from it.</string>
|
||||||
<string name="transfer_money_from_pdf_error_message_could_not_extract_text">Could not extract text from file "%1$s":\n\n%2$s</string>
|
<string name="transfer_money_from_pdf_error_message_could_not_extract_text">Could not extract text from file "%1$s":\n\n%2$s</string>
|
||||||
<string name="transfer_money_from_pdf_error_message_could_not_extract_invoice_data">Could not extract cash transfer data from file "%1$s":\n\n%2$s</string>
|
<string name="transfer_money_from_pdf_error_message_could_not_extract_invoice_data">Could not extract cash transfer data from file "%1$s":\n\n%2$s</string>
|
||||||
|
|
|
@ -54,7 +54,7 @@ open class MainMenuBar(protected val presenter: BankingPresenter) : View() {
|
||||||
item(messages["main.window.menu.file.new.cash.transfer.from.pdf"], KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN, KeyCodeCombination.SHIFT_DOWN)) {
|
item(messages["main.window.menu.file.new.cash.transfer.from.pdf"], KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN, KeyCodeCombination.SHIFT_DOWN)) {
|
||||||
enableWhen(areAccountsThatCanTransferMoneyAdded)
|
enableWhen(areAccountsThatCanTransferMoneyAdded)
|
||||||
|
|
||||||
action { transferMoneyWithDataFromPdf() }
|
action { showTransferMoneyDialogWithDataFromPdf() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ open class MainMenuBar(protected val presenter: BankingPresenter) : View() {
|
||||||
areAccountsThatCanTransferMoneyAdded.value = presenter.hasAccountsSupportTransferringMoney
|
areAccountsThatCanTransferMoneyAdded.value = presenter.hasAccountsSupportTransferringMoney
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun transferMoneyWithDataFromPdf() {
|
protected open fun showTransferMoneyDialogWithDataFromPdf() {
|
||||||
val fileChooser = FileChooser()
|
val fileChooser = FileChooser()
|
||||||
|
|
||||||
fileChooser.initialDirectory = lastSelectedFolder
|
fileChooser.initialDirectory = lastSelectedFolder
|
||||||
|
@ -80,15 +80,15 @@ open class MainMenuBar(protected val presenter: BankingPresenter) : View() {
|
||||||
fileChooser.showOpenDialog(currentStage)?.let { pdfFile ->
|
fileChooser.showOpenDialog(currentStage)?.let { pdfFile ->
|
||||||
lastSelectedFolder = pdfFile.parentFile
|
lastSelectedFolder = pdfFile.parentFile
|
||||||
|
|
||||||
val result = presenter.transferMoneyWithDataFromPdf(pdfFile.toFile())
|
val result = presenter.showTransferMoneyDialogWithDataFromPdf(pdfFile.toFile())
|
||||||
|
|
||||||
if (result.type != ExtractTransferMoneyDataFromPdfResultType.Success) {
|
if (result.type != ExtractTransferMoneyDataFromPdfResultType.Success) {
|
||||||
showTransferMoneyWithDataFromPdfError(pdfFile, result)
|
showTransferMoneyDialogWithDataFromPdfError(pdfFile, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun showTransferMoneyWithDataFromPdfError(pdfFile: File, result: ExtractTransferMoneyDataFromPdfResult) {
|
protected open fun showTransferMoneyDialogWithDataFromPdfError(pdfFile: File, result: ExtractTransferMoneyDataFromPdfResult) {
|
||||||
val errorMessageKey = when (result.type) {
|
val errorMessageKey = when (result.type) {
|
||||||
ExtractTransferMoneyDataFromPdfResultType.NotASearchablePdf -> "transfer.money.from.pdf.error.message.not.a.searchable.pdf"
|
ExtractTransferMoneyDataFromPdfResultType.NotASearchablePdf -> "transfer.money.from.pdf.error.message.not.a.searchable.pdf"
|
||||||
ExtractTransferMoneyDataFromPdfResultType.CouldNotExtractText -> "transfer.money.from.pdf.error.message.could.not.extract.text"
|
ExtractTransferMoneyDataFromPdfResultType.CouldNotExtractText -> "transfer.money.from.pdf.error.message.could.not.extract.text"
|
||||||
|
|
|
@ -40,6 +40,8 @@ kotlin {
|
||||||
api project(":fints4k")
|
api project(":fints4k")
|
||||||
|
|
||||||
api project(":BankFinder")
|
api project(":BankFinder")
|
||||||
|
|
||||||
|
api project(":EpcQrCodeParser")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import net.dankito.banking.util.extraction.IInvoiceDataExtractor
|
||||||
import net.dankito.banking.util.extraction.ITextExtractorRegistry
|
import net.dankito.banking.util.extraction.ITextExtractorRegistry
|
||||||
import net.dankito.banking.util.extraction.NoOpInvoiceDataExtractor
|
import net.dankito.banking.util.extraction.NoOpInvoiceDataExtractor
|
||||||
import net.dankito.banking.util.extraction.NoOpTextExtractorRegistry
|
import net.dankito.banking.util.extraction.NoOpTextExtractorRegistry
|
||||||
|
import net.codinux.banking.tools.epcqrcode.*
|
||||||
import net.dankito.utils.multiplatform.*
|
import net.dankito.utils.multiplatform.*
|
||||||
import net.dankito.utils.multiplatform.log.LoggerFactory
|
import net.dankito.utils.multiplatform.log.LoggerFactory
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
@ -49,7 +50,8 @@ open class BankingPresenter(
|
||||||
protected val textExtractorRegistry: ITextExtractorRegistry = NoOpTextExtractorRegistry(),
|
protected val textExtractorRegistry: ITextExtractorRegistry = NoOpTextExtractorRegistry(),
|
||||||
protected val invoiceDataExtractor: IInvoiceDataExtractor = NoOpInvoiceDataExtractor(),
|
protected val invoiceDataExtractor: IInvoiceDataExtractor = NoOpInvoiceDataExtractor(),
|
||||||
protected val currencyInfoProvider: ICurrencyInfoProvider = CurrencyInfoProvider(),
|
protected val currencyInfoProvider: ICurrencyInfoProvider = CurrencyInfoProvider(),
|
||||||
protected val asyncRunner: IAsyncRunner = CoroutinesAsyncRunner()
|
protected val asyncRunner: IAsyncRunner = CoroutinesAsyncRunner(),
|
||||||
|
protected val qrCodeParser: EpcQrCodeParser = EpcQrCodeParser() // TODO: create interface
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -586,7 +588,28 @@ open class BankingPresenter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun transferMoneyWithDataFromPdf(pdf: File): ExtractTransferMoneyDataFromPdfResult {
|
open fun showTransferMoneyDialogWithDataFromQrCode(decodedQrCode: String): ParseEpcQrCodeResult {
|
||||||
|
val result = qrCodeParser.parseEpcQrCode(decodedQrCode)
|
||||||
|
|
||||||
|
if (result.successful) {
|
||||||
|
result.epcQrCode?.let { epcQrCode ->
|
||||||
|
// TODO: show originatorInformation to user
|
||||||
|
|
||||||
|
val transferMoneyData = TransferMoneyData(
|
||||||
|
allAccounts.first(),
|
||||||
|
epcQrCode.receiverName,
|
||||||
|
epcQrCode.iban,
|
||||||
|
epcQrCode.bic ?: "",
|
||||||
|
epcQrCode.amount?.let { BigDecimal(it) } ?: BigDecimal.Zero,
|
||||||
|
epcQrCode.remittance)
|
||||||
|
showTransferMoneyDialog(transferMoneyData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun showTransferMoneyDialogWithDataFromPdf(pdf: File): ExtractTransferMoneyDataFromPdfResult {
|
||||||
val extractionResult = textExtractorRegistry.extractTextWithBestExtractorForFile(pdf)
|
val extractionResult = textExtractorRegistry.extractTextWithBestExtractorForFile(pdf)
|
||||||
|
|
||||||
if (extractionResult.couldExtractText == false || extractionResult.text == null) {
|
if (extractionResult.couldExtractText == false || extractionResult.text == null) {
|
||||||
|
|
|
@ -6,6 +6,8 @@ plugins {
|
||||||
|
|
||||||
ext.artifactName = "banking-ui-native-integration"
|
ext.artifactName = "banking-ui-native-integration"
|
||||||
|
|
||||||
|
def frameworkName = "BankingUiSwift"
|
||||||
|
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|
||||||
|
@ -15,12 +17,13 @@ kotlin {
|
||||||
fromPreset(iOSTarget, 'ios') {
|
fromPreset(iOSTarget, 'ios') {
|
||||||
binaries {
|
binaries {
|
||||||
framework {
|
framework {
|
||||||
baseName = "BankingUiSwift"
|
baseName = frameworkName
|
||||||
|
|
||||||
// transitiveExport = true
|
// transitiveExport = true
|
||||||
export(project(":BankingUiCommon"))
|
export(project(":BankingUiCommon"))
|
||||||
export(project(":fints4kBankingClient"))
|
export(project(":fints4kBankingClient"))
|
||||||
export(project(":BankFinder"))
|
export(project(":BankFinder"))
|
||||||
|
export(project(":EpcQrCodeParser"))
|
||||||
// do not add fints4k to exports, would lead to a lot of naming conflicts. In this way fints4k classes get prefixed with 'Fints4k' which is Ok
|
// do not add fints4k to exports, would lead to a lot of naming conflicts. In this way fints4k classes get prefixed with 'Fints4k' which is Ok
|
||||||
// export(project(":fints4k"))
|
// export(project(":fints4k"))
|
||||||
// exporting common would lead to naming conflicts with Foundation classes like Date, UUID, Thread, ...
|
// exporting common would lead to naming conflicts with Foundation classes like Date, UUID, Thread, ...
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
3642F01A2502931F005186FE /* RealTimeTransferInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F0192502931F005186FE /* RealTimeTransferInfoView.swift */; };
|
3642F01A2502931F005186FE /* RealTimeTransferInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F0192502931F005186FE /* RealTimeTransferInfoView.swift */; };
|
||||||
3642F04B25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F04A25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift */; };
|
3642F04B25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3642F04A25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift */; };
|
||||||
36671255253A761500BD2301 /* BankCredentialsPasswordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36671254253A761500BD2301 /* BankCredentialsPasswordView.swift */; };
|
36671255253A761500BD2301 /* BankCredentialsPasswordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36671254253A761500BD2301 /* BankCredentialsPasswordView.swift */; };
|
||||||
|
36671290253F8D5200BD2301 /* ScanQrCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3667128F253F8D5200BD2301 /* ScanQrCodeViewController.swift */; };
|
||||||
|
36671294254045E100BD2301 /* EpcQrCodeParser.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 36671293254045E100BD2301 /* EpcQrCodeParser.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
36693A4E25280BCB00BB7AE5 /* InfoButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36693A4D25280BCB00BB7AE5 /* InfoButton.swift */; };
|
36693A4E25280BCB00BB7AE5 /* InfoButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36693A4D25280BCB00BB7AE5 /* InfoButton.swift */; };
|
||||||
366FA4DA24C472A90094F009 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4D924C472A90094F009 /* Extensions.swift */; };
|
366FA4DA24C472A90094F009 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4D924C472A90094F009 /* Extensions.swift */; };
|
||||||
366FA4DC24C479120094F009 /* BankInfoListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DB24C479120094F009 /* BankInfoListItem.swift */; };
|
366FA4DC24C479120094F009 /* BankInfoListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 366FA4DB24C479120094F009 /* BankInfoListItem.swift */; };
|
||||||
|
@ -157,6 +159,7 @@
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 10;
|
dstSubfolderSpec = 10;
|
||||||
files = (
|
files = (
|
||||||
|
36671294254045E100BD2301 /* EpcQrCodeParser.framework in Embed Frameworks */,
|
||||||
3684EB8F250B7F3C0001139E /* BankingUiCommon.framework in Embed Frameworks */,
|
3684EB8F250B7F3C0001139E /* BankingUiCommon.framework in Embed Frameworks */,
|
||||||
36BCF86A24BA550D005BEC29 /* BankFinder.framework in Embed Frameworks */,
|
36BCF86A24BA550D005BEC29 /* BankFinder.framework in Embed Frameworks */,
|
||||||
36BCF85F24BA4DA8005BEC29 /* MultiplatformUtils.framework in Embed Frameworks */,
|
36BCF85F24BA4DA8005BEC29 /* MultiplatformUtils.framework in Embed Frameworks */,
|
||||||
|
@ -199,6 +202,8 @@
|
||||||
3642F0192502931F005186FE /* RealTimeTransferInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealTimeTransferInfoView.swift; sourceTree = "<group>"; };
|
3642F0192502931F005186FE /* RealTimeTransferInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealTimeTransferInfoView.swift; sourceTree = "<group>"; };
|
||||||
3642F04A25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderWithRightAlignedEditButton.swift; sourceTree = "<group>"; };
|
3642F04A25031157005186FE /* SectionHeaderWithRightAlignedEditButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderWithRightAlignedEditButton.swift; sourceTree = "<group>"; };
|
||||||
36671254253A761500BD2301 /* BankCredentialsPasswordView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankCredentialsPasswordView.swift; sourceTree = "<group>"; };
|
36671254253A761500BD2301 /* BankCredentialsPasswordView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankCredentialsPasswordView.swift; sourceTree = "<group>"; };
|
||||||
|
3667128F253F8D5200BD2301 /* ScanQrCodeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanQrCodeViewController.swift; sourceTree = "<group>"; };
|
||||||
|
36671293254045E100BD2301 /* EpcQrCodeParser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EpcQrCodeParser.framework; path = "../../tools/EpcQrCodeParser/build/xcode-frameworks/EpcQrCodeParser.framework"; sourceTree = "<group>"; };
|
||||||
36693A4D25280BCB00BB7AE5 /* InfoButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoButton.swift; sourceTree = "<group>"; };
|
36693A4D25280BCB00BB7AE5 /* InfoButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoButton.swift; sourceTree = "<group>"; };
|
||||||
366FA4D924C472A90094F009 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
|
366FA4D924C472A90094F009 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
|
||||||
366FA4DB24C479120094F009 /* BankInfoListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankInfoListItem.swift; sourceTree = "<group>"; };
|
366FA4DB24C479120094F009 /* BankInfoListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BankInfoListItem.swift; sourceTree = "<group>"; };
|
||||||
|
@ -371,6 +376,7 @@
|
||||||
36E21ED424DC549800649DC8 /* BankSettingsDialog.swift */,
|
36E21ED424DC549800649DC8 /* BankSettingsDialog.swift */,
|
||||||
36E21ED624DC617200649DC8 /* BankAccountSettingsDialog.swift */,
|
36E21ED624DC617200649DC8 /* BankAccountSettingsDialog.swift */,
|
||||||
36B8A4472503D12100C15359 /* ProtectAppSettingsDialog.swift */,
|
36B8A4472503D12100C15359 /* ProtectAppSettingsDialog.swift */,
|
||||||
|
3667128F253F8D5200BD2301 /* ScanQrCodeViewController.swift */,
|
||||||
);
|
);
|
||||||
path = dialogs;
|
path = dialogs;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -481,6 +487,7 @@
|
||||||
36FC928F24B39A05002B12E9 = {
|
36FC928F24B39A05002B12E9 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
36671293254045E100BD2301 /* EpcQrCodeParser.framework */,
|
||||||
3684EB8E250B7F3C0001139E /* BankingUiCommon.framework */,
|
3684EB8E250B7F3C0001139E /* BankingUiCommon.framework */,
|
||||||
3684EB8C250B7F2B0001139E /* BankingUiCommon.framework.dSYM */,
|
3684EB8C250B7F2B0001139E /* BankingUiCommon.framework.dSYM */,
|
||||||
36FC929A24B39A05002B12E9 /* BankingiOSApp */,
|
36FC929A24B39A05002B12E9 /* BankingiOSApp */,
|
||||||
|
@ -992,6 +999,7 @@
|
||||||
36BE068F24CEE1BD00CBBB68 /* AllBanksListItem.swift in Sources */,
|
36BE068F24CEE1BD00CBBB68 /* AllBanksListItem.swift in Sources */,
|
||||||
360782C324E49FF70098FEFE /* ValidationLabel.swift in Sources */,
|
360782C324E49FF70098FEFE /* ValidationLabel.swift in Sources */,
|
||||||
3684EB92250FD4AF0001139E /* LabelledValue.swift in Sources */,
|
3684EB92250FD4AF0001139E /* LabelledValue.swift in Sources */,
|
||||||
|
36671290253F8D5200BD2301 /* ScanQrCodeViewController.swift in Sources */,
|
||||||
36BE069124CEF52800CBBB68 /* UpdateButton.swift in Sources */,
|
36BE069124CEF52800CBBB68 /* UpdateButton.swift in Sources */,
|
||||||
36E21ED124DC540400649DC8 /* SettingsDialog.swift in Sources */,
|
36E21ED124DC540400649DC8 /* SettingsDialog.swift in Sources */,
|
||||||
3684EB8B2508F6F00001139E /* SearchBarWithLabel.swift in Sources */,
|
3684EB8B2508F6F00001139E /* SearchBarWithLabel.swift in Sources */,
|
||||||
|
|
|
@ -130,7 +130,8 @@
|
||||||
|
|
||||||
/* New action sheet */
|
/* New action sheet */
|
||||||
|
|
||||||
"Show transfer money dialog" = "Transfer money";
|
"Show transfer money dialog" = "Money transfer";
|
||||||
|
"Money transfer from scanning QR-Code" = "Money transfer from QR-Code";
|
||||||
|
|
||||||
|
|
||||||
/* TransferMoneyDialog */
|
/* TransferMoneyDialog */
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>Used to scan QR codes to initiate money transfer</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
|
|
|
@ -62,7 +62,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
DependencyInjector.register(dependency: presenter)
|
DependencyInjector.register(dependency: presenter)
|
||||||
|
|
||||||
window.rootViewController = UINavigationController(rootViewController: TabBarController())
|
window.rootViewController = UINavigationController(rootViewController: TabBarController(presenter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,25 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import AVFoundation
|
||||||
|
import BankingUiSwift
|
||||||
|
|
||||||
|
|
||||||
class TabBarController : UITabBarController, UITabBarControllerDelegate {
|
class TabBarController : UITabBarController, UITabBarControllerDelegate {
|
||||||
|
|
||||||
@ObservedObject var data: AppData = AppData()
|
@ObservedObject var data: AppData = AppData()
|
||||||
|
|
||||||
|
private let presenter: BankingPresenterSwift
|
||||||
|
|
||||||
|
|
||||||
|
init(_ presenter: BankingPresenterSwift) {
|
||||||
|
self.presenter = presenter
|
||||||
|
|
||||||
|
super.init(nibName: nil, bundle: Bundle.main)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
@ -88,15 +103,33 @@ class TabBarController : UITabBarController, UITabBarControllerDelegate {
|
||||||
|
|
||||||
|
|
||||||
private func showNewOptionsActionSheet() {
|
private func showNewOptionsActionSheet() {
|
||||||
let transferMoneyAction = UIAlertAction.default("Show transfer money dialog".localize()) { SceneDelegate.navigateToView(TransferMoneyDialog()) }
|
let moneyTransferFromQrCodeAction = UIAlertAction.default("Money transfer from scanning QR-Code".localize()) { self.scanQrCodeIfCameraAccessGranted() }
|
||||||
|
moneyTransferFromQrCodeAction.isEnabled = data.hasAccountsThatSupportTransferringMoney
|
||||||
|
|
||||||
|
let transferMoneyAction = UIAlertAction.default("Show transfer money dialog".localize()) { self.presenter.showTransferMoneyDialog(preselectedValues: nil) }
|
||||||
transferMoneyAction.isEnabled = data.hasAccountsThatSupportTransferringMoney
|
transferMoneyAction.isEnabled = data.hasAccountsThatSupportTransferringMoney
|
||||||
|
|
||||||
ActionSheet(
|
ActionSheet(
|
||||||
nil,
|
nil,
|
||||||
|
moneyTransferFromQrCodeAction,
|
||||||
transferMoneyAction,
|
transferMoneyAction,
|
||||||
UIAlertAction.default("Add account") { SceneDelegate.navigateToView(AddAccountDialog()) },
|
UIAlertAction.default("Add account") { SceneDelegate.navigateToView(AddAccountDialog()) },
|
||||||
UIAlertAction.cancel()
|
UIAlertAction.cancel()
|
||||||
).show(self.tabBar, self.tabBar.bounds.midX, 0)
|
).show(self.tabBar, self.tabBar.bounds.midX, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func scanQrCodeIfCameraAccessGranted() {
|
||||||
|
AVCaptureDevice.requestAccess(for: .video) { granted in
|
||||||
|
if granted {
|
||||||
|
DispatchQueue.main.async { // completionHandler is called on an arbitrary dispatch queue
|
||||||
|
SceneDelegate.navigateToViewController(ScanQrCodeViewController() { decodedQrCode in
|
||||||
|
if let decodedQrCode = decodedQrCode {
|
||||||
|
self.presenter.showTransferMoneyDialogWithDataFromQrCode(decodedQrCode: decodedQrCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,6 +132,7 @@
|
||||||
/* New action sheet */
|
/* New action sheet */
|
||||||
|
|
||||||
"Show transfer money dialog" = "Überweisung";
|
"Show transfer money dialog" = "Überweisung";
|
||||||
|
"Money transfer from scanning QR-Code" = "Überweisung aus QR-Code";
|
||||||
|
|
||||||
|
|
||||||
/* TransferMoneyDialog */
|
/* TransferMoneyDialog */
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
import AVFoundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Copied from Hacking with Swift: https://www.hackingwithswift.com/example-code/media/how-to-scan-a-qr-code
|
||||||
|
*/
|
||||||
|
class ScanQrCodeViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
|
||||||
|
|
||||||
|
private let scanResult: (String?) -> Void
|
||||||
|
|
||||||
|
private var captureSession: AVCaptureSession!
|
||||||
|
|
||||||
|
private var previewLayer: AVCaptureVideoPreviewLayer!
|
||||||
|
|
||||||
|
|
||||||
|
init(_ scanResult: @escaping (String?) -> Void) {
|
||||||
|
self.scanResult = scanResult
|
||||||
|
|
||||||
|
super.init(nibName: nil, bundle: Bundle.main)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
view.backgroundColor = UIColor.black
|
||||||
|
captureSession = AVCaptureSession()
|
||||||
|
|
||||||
|
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
|
||||||
|
let videoInput: AVCaptureDeviceInput
|
||||||
|
|
||||||
|
do {
|
||||||
|
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captureSession.canAddInput(videoInput)) {
|
||||||
|
captureSession.addInput(videoInput)
|
||||||
|
} else {
|
||||||
|
failed()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let metadataOutput = AVCaptureMetadataOutput()
|
||||||
|
|
||||||
|
if (captureSession.canAddOutput(metadataOutput)) {
|
||||||
|
captureSession.addOutput(metadataOutput)
|
||||||
|
|
||||||
|
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
|
||||||
|
metadataOutput.metadataObjectTypes = [.qr]
|
||||||
|
} else {
|
||||||
|
failed()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
|
||||||
|
previewLayer.frame = view.layer.bounds
|
||||||
|
previewLayer.videoGravity = .resizeAspectFill
|
||||||
|
view.layer.addSublayer(previewLayer)
|
||||||
|
|
||||||
|
captureSession.startRunning()
|
||||||
|
}
|
||||||
|
|
||||||
|
func failed() {
|
||||||
|
self.closeDialog()
|
||||||
|
|
||||||
|
let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .alert)
|
||||||
|
ac.addAction(UIAlertAction(title: "OK", style: .default))
|
||||||
|
present(ac, animated: true)
|
||||||
|
captureSession = nil
|
||||||
|
|
||||||
|
scanResult(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
|
if (captureSession?.isRunning == false) {
|
||||||
|
captureSession.startRunning()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
super.viewWillDisappear(animated)
|
||||||
|
|
||||||
|
if (captureSession?.isRunning == true) {
|
||||||
|
captureSession.stopRunning()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
|
||||||
|
captureSession.stopRunning()
|
||||||
|
var didCloseDialog = false
|
||||||
|
|
||||||
|
if let metadataObject = metadataObjects.first {
|
||||||
|
if let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject {
|
||||||
|
if let decodedQrCode = readableObject.stringValue {
|
||||||
|
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
|
||||||
|
|
||||||
|
didCloseDialog = true
|
||||||
|
SceneDelegate.dismissCurrentView()
|
||||||
|
|
||||||
|
scanResult(decodedQrCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if didCloseDialog == false { // for all other cases where QR code could not successfully be read
|
||||||
|
closeDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func closeDialog() {
|
||||||
|
SceneDelegate.dismissCurrentView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override var prefersStatusBarHidden: Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||||
|
return .portrait
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -94,7 +94,7 @@ struct AccountTransactionListItem: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func navigateToTransferMoneyDialog(_ preselectedValues: TransferMoneyData) {
|
private func navigateToTransferMoneyDialog(_ preselectedValues: TransferMoneyData) {
|
||||||
SceneDelegate.navigateToView(TransferMoneyDialog(preselectedValues: preselectedValues))
|
SceneDelegate.navigateToView(TransferMoneyDialog(preselectedValues))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue