commit 2e88af80e385e8bda32a685b126f88c7d32d9c67
parent fc5195c17b2ed5ada68fb1159db7ea568d960d61
Author: Bohdan Potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date: Sun, 27 Apr 2025 21:48:18 +0200
support taler-pos intent
Diffstat:
2 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/merchant-terminal/src/main/AndroidManifest.xml b/merchant-terminal/src/main/AndroidManifest.xml
@@ -48,6 +48,13 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
+
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="taler-pos" />
+ </intent-filter>
</activity>
<service
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/MainActivity.kt
@@ -20,6 +20,7 @@ import android.content.Intent
import android.content.Intent.ACTION_MAIN
import android.content.Intent.CATEGORY_HOME
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
+import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.view.MenuItem
@@ -34,6 +35,7 @@ import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.navigation.NavigationView.OnNavigationItemSelectedListener
import net.taler.lib.android.TalerNfcService
+import net.taler.merchantpos.config.Config
import net.taler.merchantpos.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener {
@@ -72,6 +74,8 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener {
setSupportActionBar(ui.main.toolbar)
val appBarConfiguration = AppBarConfiguration(nav.graph, ui.drawerLayout)
ui.main.toolbar.setupWithNavController(nav, appBarConfiguration)
+
+ handleSetupIntent(intent)
}
override fun onStart() {
@@ -103,6 +107,11 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener {
return true
}
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ handleSetupIntent(intent)
+ }
+
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
val currentDestination = nav.currentDestination?.id
@@ -126,4 +135,52 @@ class MainActivity : AppCompatActivity(), OnNavigationItemSelectedListener {
} else super.onBackPressed()
}
+ /**
+ * Handle the setup intent from the URL scheme. E.g. scanned the QR code from the camera
+ *
+ * This is the URL format:
+ * taler-pos://backend.demo.taler.net/#/username=<username>&password=<password>
+ */
+ private fun handleSetupIntent(intent: Intent) {
+ if (intent.action != Intent.ACTION_VIEW) return
+ val data = intent.data ?: return
+ if (data.scheme != "taler-pos") return
+
+ val host = data.host ?: return
+
+ val params = data.fragment
+ ?.removePrefix("/")
+ ?.split('&')
+ ?.associate { part ->
+ part.split('=', limit = 2).let { it[0] to Uri.decode(it.getOrElse(1) { "" }) }
+ } ?: return
+
+ val instance = params["username"] ?: return
+ val token = params["password"] ?: return
+
+ // Build a regular Merchant-API URL: https://<host>/instances/<instance>
+ val merchantUrl = Uri.Builder()
+ .scheme("https")
+ .encodedAuthority(host)
+ .appendPath("instances")
+ .appendPath(instance)
+ .build()
+ .toString()
+
+ // Re-use the existing “new config” class
+ val newConfig = Config.New(
+ merchantUrl = merchantUrl,
+ accessToken = token,
+ savePassword = true
+ )
+
+ // Kick off the exact same pipeline the Settings screen would start
+ model.configManager.fetchConfig(newConfig, /*save =*/ true)
+
+ // Take the user to the fetcher fragment so they see the spinner / error handling
+ if (nav.currentDestination?.id != R.id.configFetcher) {
+ nav.navigate(R.id.action_global_configFetcher)
+ }
+ }
+
}