diff options
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/MainActivity.kt')
-rw-r--r-- | wallet/src/main/java/net/taler/wallet/MainActivity.kt | 199 |
1 files changed, 40 insertions, 159 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/MainActivity.kt b/wallet/src/main/java/net/taler/wallet/MainActivity.kt index bf95475..00fd2d3 100644 --- a/wallet/src/main/java/net/taler/wallet/MainActivity.kt +++ b/wallet/src/main/java/net/taler/wallet/MainActivity.kt @@ -22,9 +22,9 @@ import android.content.Context import android.content.Intent import android.content.Intent.ACTION_VIEW import android.content.IntentFilter -import android.net.Uri import android.os.Bundle import android.util.Log +import android.view.Menu import android.view.MenuItem import android.view.View.GONE import android.view.View.INVISIBLE @@ -34,9 +34,6 @@ import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.os.bundleOf import androidx.core.view.GravityCompat.START -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Observer -import androidx.lifecycle.viewModelScope import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.AppBarConfiguration @@ -45,18 +42,12 @@ import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback import com.google.android.material.navigation.NavigationView.OnNavigationItemSelectedListener -import com.google.android.material.snackbar.BaseTransientBottomBar.LENGTH_LONG -import com.google.android.material.snackbar.Snackbar import com.google.zxing.client.android.Intents.Scan.MIXED_SCAN import com.google.zxing.client.android.Intents.Scan.SCAN_TYPE import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanOptions import com.journeyapps.barcodescanner.ScanOptions.QR_CODE -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import net.taler.common.EventObserver -import net.taler.common.isOnline -import net.taler.common.showError import net.taler.wallet.BuildConfig.VERSION_CODE import net.taler.wallet.BuildConfig.VERSION_NAME import net.taler.wallet.HostCardEmulatorService.Companion.HTTP_TUNNEL_RESPONSE @@ -64,11 +55,7 @@ import net.taler.wallet.HostCardEmulatorService.Companion.MERCHANT_NFC_CONNECTED import net.taler.wallet.HostCardEmulatorService.Companion.MERCHANT_NFC_DISCONNECTED import net.taler.wallet.HostCardEmulatorService.Companion.TRIGGER_PAYMENT_ACTION import net.taler.wallet.databinding.ActivityMainBinding -import net.taler.wallet.refund.RefundStatus -import java.net.HttpURLConnection -import java.net.URL -import java.util.Locale.ROOT -import javax.net.ssl.HttpsURLConnection +import net.taler.wallet.events.ObservabilityDialog class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener, OnPreferenceStartFragmentCallback { @@ -99,7 +86,7 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener, setSupportActionBar(ui.content.toolbar) val appBarConfiguration = AppBarConfiguration( - setOf(R.id.nav_main, R.id.nav_settings, R.id.nav_pending_operations), + setOf(R.id.nav_main, R.id.nav_settings), ui.drawerLayout ) ui.content.toolbar.setupWithNavController(nav, appBarConfiguration) @@ -109,14 +96,13 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener, } val versionView: TextView = ui.navView.getHeaderView(0).findViewById(R.id.versionView) - model.devMode.observe(this) { enabled -> - ui.navView.menu.findItem(R.id.nav_dev).isVisible = enabled - if (enabled) { - @SuppressLint("SetTextI18n") - versionView.text = "$VERSION_NAME ($VERSION_CODE)" - versionView.visibility = VISIBLE - } else versionView.visibility = GONE - } + @SuppressLint("SetTextI18n") + versionView.text = "$VERSION_NAME ($VERSION_CODE)" + + // Uncomment if any dev options are added in the future + // model.devMode.observe(this) { enabled -> + // ui.navView.menu.findItem(R.id.nav_dev).isVisible = enabled + // } if (intent.action == ACTION_VIEW) intent.dataString?.let { uri -> handleTalerUri(uri, "intent") @@ -139,6 +125,14 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener, } if (it) barcodeLauncher.launch(scanOptions) }) + + model.networkManager.networkStatus.observe(this) { online -> + ui.content.offlineBanner.visibility = if (online) GONE else VISIBLE + } + + model.devMode.observe(this) { + invalidateMenu() + } } @Deprecated("Deprecated in Java") @@ -154,156 +148,43 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener, } } + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + if (model.devMode.value == true) { + menuInflater.inflate(R.menu.global_dev, menu) + } + + return super.onCreateOptionsMenu(menu) + } + override fun onNavigationItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.nav_home -> nav.navigate(R.id.nav_main) R.id.nav_settings -> nav.navigate(R.id.nav_settings) - R.id.nav_pending_operations -> nav.navigate(R.id.nav_pending_operations) } ui.drawerLayout.closeDrawer(START) return true } - override fun onDestroy() { - unregisterReceiver(triggerPaymentReceiver) - unregisterReceiver(nfcConnectedReceiver) - unregisterReceiver(nfcDisconnectedReceiver) - unregisterReceiver(tunnelResponseReceiver) - super.onDestroy() - } - - private fun getTalerAction( - uri: Uri, - maxRedirects: Int, - actionFound: MutableLiveData<String>, - ): MutableLiveData<String> { - val scheme = uri.scheme ?: return actionFound - - if (scheme == "http" || scheme == "https") { - model.viewModelScope.launch(Dispatchers.IO) { - val conn: HttpsURLConnection = - URL(uri.toString()).openConnection() as HttpsURLConnection - Log.v(TAG, "prepare query: $uri") - conn.setRequestProperty("Accept", "text/html") - conn.connectTimeout = 5000 - conn.requestMethod = "HEAD" - conn.connect() - val status = conn.responseCode - - if (status == HttpURLConnection.HTTP_OK || status == HttpURLConnection.HTTP_PAYMENT_REQUIRED) { - val talerHeader = conn.headerFields["Taler"] - if (talerHeader != null && talerHeader[0] != null) { - Log.v(TAG, "taler header: ${talerHeader[0]}") - val talerHeaderUri = Uri.parse(talerHeader[0]) - getTalerAction(talerHeaderUri, 0, actionFound) - } - } - if (status == HttpURLConnection.HTTP_MOVED_TEMP - || status == HttpURLConnection.HTTP_MOVED_PERM - || status == HttpURLConnection.HTTP_SEE_OTHER - ) { - val location = conn.headerFields["Location"] - if (location != null && location[0] != null) { - Log.v(TAG, "location redirect: ${location[0]}") - val locUri = Uri.parse(location[0]) - getTalerAction(locUri, maxRedirects - 1, actionFound) - } - } + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.action_show_logs -> { + ObservabilityDialog().show(supportFragmentManager, "OBSERVABILITY") } - } else { - actionFound.postValue(uri.toString()) } - - return actionFound + return super.onOptionsItemSelected(item) } - private fun handleTalerUri(url: String, from: String) { - val uri = Uri.parse(url) - if (uri.fragment != null && !isOnline()) { - connectToWifi(this, uri.fragment!!) - } - - getTalerAction(uri, 3, MutableLiveData<String>()).observe(this) { u -> - Log.v(TAG, "found action $u") - - if (u.startsWith("payto://", ignoreCase = true)) { - Log.v(TAG, "navigating with paytoUri!") - val bundle = bundleOf("uri" to u) - nav.navigate(R.id.action_nav_payto_uri, bundle) - return@observe - } - - val normalizedURL = u.lowercase(ROOT) - var ext = false - val action = normalizedURL.substring( - if (normalizedURL.startsWith("taler://", ignoreCase = true)) { - "taler://".length - } else if (normalizedURL.startsWith("ext+taler://", ignoreCase = true)) { - ext = true - "ext+taler://".length - } else if (normalizedURL.startsWith("taler+http://", ignoreCase = true) && - model.devMode.value == true - ) { - "taler+http://".length - } else { - normalizedURL.length - } - ) - - // Remove ext+ scheme prefix if present - val u2 = if (ext) { - "taler://" + u.substring("ext+taler://".length) - } else u - - when { - action.startsWith("pay/", ignoreCase = true) -> { - Log.v(TAG, "navigating!") - nav.navigate(R.id.action_global_promptPayment) - model.paymentManager.preparePay(u2) - } - action.startsWith("tip/", ignoreCase = true) -> { - Log.v(TAG, "navigating!") - nav.navigate(R.id.action_global_promptTip) - model.tipManager.prepareTip(u2) - } - action.startsWith("withdraw/", ignoreCase = true) -> { - Log.v(TAG, "navigating!") - // there's more than one entry point, so use global action - nav.navigate(R.id.action_global_promptWithdraw) - model.withdrawManager.getWithdrawalDetails(u2) - } - action.startsWith("refund/", ignoreCase = true) -> { - model.showProgressBar.value = true - model.refundManager.refund(u2).observe(this, Observer(::onRefundResponse)) - } - action.startsWith("pay-pull/", ignoreCase = true) -> { - nav.navigate(R.id.action_global_prompt_pull_payment) - model.peerManager.preparePeerPullDebit(u2) - } - action.startsWith("pay-push/", ignoreCase = true) -> { - nav.navigate(R.id.action_global_prompt_push_payment) - model.peerManager.preparePeerPushCredit(u2) - } - else -> { - showError(R.string.error_unsupported_uri, "From: $from\nURI: $u2") - } - } - } + private fun handleTalerUri(uri: String, from: String) { + val args = bundleOf("uri" to uri, "from" to from) + nav.navigate(R.id.action_global_handle_uri, args) } - private fun onRefundResponse(status: RefundStatus) { - model.showProgressBar.value = false - when (status) { - is RefundStatus.Error -> { - showError(R.string.refund_error, status.msg) - } - is RefundStatus.Success -> { - val amount = status.response.amountRefundGranted - model.showTransactions(amount.currency) - val str = getString(R.string.refund_success, amount.amountStr) - Snackbar.make(ui.navView, str, LENGTH_LONG).show() - } - } + override fun onDestroy() { + unregisterReceiver(triggerPaymentReceiver) + unregisterReceiver(nfcConnectedReceiver) + unregisterReceiver(nfcDisconnectedReceiver) + unregisterReceiver(tunnelResponseReceiver) + super.onDestroy() } private val triggerPaymentReceiver = object : BroadcastReceiver() { |