gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant-terminal-android] branch master updated (d1b7474 -> cac7


From: gnunet
Subject: [taler-merchant-terminal-android] branch master updated (d1b7474 -> cac721a)
Date: Mon, 02 Mar 2020 21:24:28 +0100

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a change to branch master
in repository merchant-terminal-android.

    from d1b7474  Change product definition format to support i18n
     new 08295b0  Add link to config format docs
     new 05c2d35  Improve nightly repo
     new cac721a  Use new i18n JSOn format

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitlab-ci.yml                                     |  7 ++
 app/build.gradle                                   |  1 -
 .../merchantpos/config/MerchantConfigFragment.kt   |  2 +
 .../net/taler/merchantpos/order/Definitions.kt     | 93 +++++++++++++++-------
 .../net/taler/merchantpos/order/OrderManager.kt    |  8 --
 .../taler/merchantpos/payment/PaymentManager.kt    |  8 ++
 .../main/res/layout/fragment_merchant_config.xml   | 10 +++
 app/src/main/res/values/strings.xml                |  1 +
 build.gradle                                       |  2 +-
 nightly-stats.patch                                | 38 +++++++++
 10 files changed, 130 insertions(+), 40 deletions(-)
 create mode 100644 nightly-stats.patch

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 05106b6..9ad38f2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,10 +27,17 @@ deploy_nightly:
     # Set time-based version code
     - export versionCode=$(date '+%s')
     - sed -i "s,^\(\s*versionCode\) *[0-9].*,\1 $versionCode," app/build.gradle
+    # Add commit to version name
+    - export versionName=$(git rev-parse --short=7 HEAD)
+    - sed -i "s,^\(\s*versionName\ *\"[0-9].*\)\",\1 ($versionName)\"," 
app/build.gradle
     # Set nightly application ID
     - sed -i "s,^\(\s*applicationId\) \"*[a-z\.].*\",\1 
\"net.taler.merchantpos.nightly\"," app/build.gradle
     # Build the APK
     - ./gradlew assembleDebug
+    # START only needed while patch not accepted/released upstream
+    - apt update && apt install patch
+    - patch /usr/lib/python3/dist-packages/fdroidserver/nightly.py 
nightly-stats.patch
+    # END
     - CI_PROJECT_URL="https://gitlab.com/gnu-taler/fdroid-repo"; 
CI_PROJECT_PATH="gnu-taler/fdroid-repo" fdroid nightly -v
 
 after_script:
diff --git a/app/build.gradle b/app/build.gradle
index 4512af3..e196397 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,6 +1,5 @@
 apply plugin: 'com.android.application'
 apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-kapt'
 apply plugin: 'kotlin-android-extensions'
 apply plugin: "androidx.navigation.safeargs.kotlin"
 
diff --git 
a/app/src/main/java/net/taler/merchantpos/config/MerchantConfigFragment.kt 
b/app/src/main/java/net/taler/merchantpos/config/MerchantConfigFragment.kt
index f89962f..2bca677 100644
--- a/app/src/main/java/net/taler/merchantpos/config/MerchantConfigFragment.kt
+++ b/app/src/main/java/net/taler/merchantpos/config/MerchantConfigFragment.kt
@@ -1,6 +1,7 @@
 package net.taler.merchantpos.config
 
 import android.os.Bundle
+import android.text.method.LinkMovementMethod
 import android.view.LayoutInflater
 import android.view.View
 import android.view.View.GONE
@@ -60,6 +61,7 @@ class MerchantConfigFragment : Fragment() {
             passwordView.editText!!.text = null
             forgetPasswordButton.visibility = GONE
         }
+        configDocsView.movementMethod = LinkMovementMethod.getInstance()
         updateView(savedInstanceState == null)
     }
 
diff --git a/app/src/main/java/net/taler/merchantpos/order/Definitions.kt 
b/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
index 065f2d2..1e6e37b 100644
--- a/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/Definitions.kt
@@ -2,6 +2,8 @@ package net.taler.merchantpos.order
 
 import androidx.core.os.LocaleListCompat
 import com.fasterxml.jackson.annotation.JsonIgnore
+import com.fasterxml.jackson.annotation.JsonInclude
+import com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL
 import com.fasterxml.jackson.annotation.JsonProperty
 import net.taler.merchantpos.Amount
 import java.util.*
@@ -11,30 +13,31 @@ import kotlin.collections.HashMap
 
 data class Category(
     val id: Int,
-    val name: Map<String, String>
+    val name: String,
+    @JsonProperty("name_i18n")
+    val nameI18n: Map<String, String>?
 ) {
-    val defaultName: String? get() = name["_"]
     var selected: Boolean = false
-    val localizedName: String get() = getLocalizedString(name, defaultName!!)
+    val localizedName: String get() = getLocalizedString(nameI18n, name)
 }
 
 abstract class Product {
     abstract val id: String
-    abstract val description: Map<String, String>
+    abstract val description: String
+    abstract val descriptionI18n: Map<String, String>?
     abstract val price: String
     abstract val location: String?
     @get:JsonIgnore
-    val defaultDescription: String?
-        get() = description["_"]
-    @get:JsonIgnore
     val localizedDescription: String
-        get() = getLocalizedString(description, defaultDescription!!)
+        get() = getLocalizedString(descriptionI18n, description)
 }
 
 data class ConfigProduct(
     @JsonProperty("product_id")
     override val id: String,
-    override val description: Map<String, String>,
+    override val description: String,
+    @JsonProperty("description_i18n")
+    override val descriptionI18n: Map<String, String>?,
     override val price: String,
     @JsonProperty("delivery_location")
     override val location: String?,
@@ -61,8 +64,10 @@ data class ConfigProduct(
 data class ContractProduct(
     @JsonProperty("product_id")
     override val id: String,
-    @get:JsonIgnore
-    override val description: Map<String, String>,
+    override val description: String,
+    @JsonInclude(NON_NULL)
+    @JsonProperty("description_i18n")
+    override val descriptionI18n: Map<String, String>?,
     override val price: String,
     @JsonProperty("delivery_location")
     override val location: String?,
@@ -71,20 +76,16 @@ data class ContractProduct(
     constructor(product: ConfigProduct) : this(
         product.id,
         product.description,
+        product.descriptionI18n,
         product.price,
         product.location,
         product.quantity
     )
-
-    // TODO remove once backend supports i18n
-    @get:JsonProperty("description")
-    val tmpDescription: String
-        get() = localizedDescription
 }
 
-private fun getLocalizedString(map: Map<String, String>, default: String): 
String {
+private fun getLocalizedString(map: Map<String, String>?, default: String): 
String {
     // just return the default, if it is the only element
-    if (map.size == 1) return default
+    if (map == null) return default
     // create a priority list of language ranges from system locales
     val locales = LocaleListCompat.getDefault()
     val priorityList = ArrayList<LanguageRange>(locales.size())
@@ -109,19 +110,10 @@ private fun getLocalizedString(map: Map<String, String>, 
default: String): Strin
 data class Order(val id: Int, val availableCategories: Map<Int, Category>) {
     val products = ArrayList<ConfigProduct>()
     val title: String = id.toString()
-    val summary: String  // TODO also support i18n map here?
-        get() {
-            val categories = HashMap<Category, Int>()
-            products.forEach { product ->
-                val categoryId = product.categories[0]
-                val category = availableCategories.getValue(categoryId)
-                val oldQuantity = categories[category] ?: 0
-                categories[category] = oldQuantity + product.quantity
-            }
-            return categories.map { (category, quantity) ->
+    val summary: String
+        get() = getCategoryQuantities().map { (category: Category, quantity: 
Int) ->
                 "$quantity x ${category.localizedName}"
-            }.joinToString()
-        }
+        }.joinToString()
     val total: Double
         get() {
             var total = 0.0
@@ -156,4 +148,45 @@ data class Order(val id: Int, val availableCategories: 
Map<Int, Category>) {
         }
         return this
     }
+
+    private fun getCategoryQuantities(): HashMap<Category, Int> {
+        val categories = HashMap<Category, Int>()
+        products.forEach { product ->
+            val categoryId = product.categories[0]
+            val category = availableCategories.getValue(categoryId)
+            val oldQuantity = categories[category] ?: 0
+            categories[category] = oldQuantity + product.quantity
+        }
+        return categories
+    }
+
+    /**
+     * Returns a map of i18n summaries for each locale present in *all* given 
[Category]s
+     * or null if there's no locale that fulfills this criteria.
+     */
+    val summaryI18n: Map<String, String>?
+        get() {
+            val categoryQuantities = getCategoryQuantities()
+            // get all available locales
+            val availableLocales = categoryQuantities.mapNotNull { (category, 
_) ->
+                val nameI18n = category.nameI18n
+                // if one category doesn't have locales, we can return null 
here already
+                nameI18n?.keys ?: return null
+            }.flatten().toHashSet()
+            // remove all locales not supported by all categories
+            categoryQuantities.forEach { (category, _) ->
+                // category.nameI18n should be non-null now
+                availableLocales.retainAll(category.nameI18n!!.keys)
+                if (availableLocales.isEmpty()) return null
+            }
+            return availableLocales.map { locale ->
+                Pair(
+                    locale, categoryQuantities.map { (category, quantity) ->
+                        // category.nameI18n should be non-null now
+                        "$quantity x ${category.nameI18n!![locale]}"
+                    }.joinToString()
+                )
+            }.toMap()
+        }
+
 }
diff --git a/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt 
b/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
index 7fdefbb..21738bb 100644
--- a/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
+++ b/app/src/main/java/net/taler/merchantpos/order/OrderManager.kt
@@ -54,10 +54,6 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
         productsByCategory.clear()
         val seenIds = ArrayList<String>()
         products.forEach { product ->
-            if (product.defaultDescription == null) {
-                Log.e(TAG, "Product $product has no default description \"_\"")
-                return false
-            }
             val productCurrency = fromString(product.price).currency
             if (productCurrency != currency) {
                 Log.e(TAG, "Product $product has currency $productCurrency, 
$currency expected")
@@ -77,10 +73,6 @@ class OrderManager(private val mapper: ObjectMapper) : 
ConfigurationReceiver {
                 if (productsByCategory.containsKey(category)) {
                     productsByCategory[category]?.add(product)
                 } else {
-                    if (category.defaultName == null) {
-                        Log.e(TAG, "Category $category has no default 
description \"_\"")
-                        return false
-                    }
                     productsByCategory[category] = 
ArrayList<ConfigProduct>().apply { add(product) }
                 }
             }
diff --git a/app/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt 
b/app/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
index 8167f86..c5ea6ec 100644
--- a/app/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
+++ b/app/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
@@ -32,6 +32,10 @@ class PaymentManager(
     private val mapper: ObjectMapper
 ) {
 
+    companion object {
+        val TAG = PaymentManager::class.java.simpleName
+    }
+
     private val mPayment = MutableLiveData<Payment>()
     val payment: LiveData<Payment> = mPayment
 
@@ -54,6 +58,7 @@ class PaymentManager(
         val currency = merchantConfig.currency!!
         val amount = "$currency:${order.totalAsString}"
         val summary = order.summary
+        val summaryI18n = order.summaryI18n
 
         mPayment.value = Payment(order, summary, currency)
 
@@ -64,6 +69,7 @@ class PaymentManager(
             put("order", JSONObject().apply {
                 put("amount", amount)
                 put("summary", summary)
+                if (summaryI18n != null) put("summary_i18n", order.summaryI18n)
                 // fulfillment_url needs to be unique per order
                 put("fulfillment_url", fulfillmentUrl)
                 put("instance", "default")
@@ -71,6 +77,8 @@ class PaymentManager(
             })
         }
 
+        Log.d(TAG, body.toString(4))
+
         val req = MerchantRequest(POST, merchantConfig, "order", null, body,
             Listener { onOrderCreated(it) },
             ErrorListener { onNetworkError(it) }
diff --git a/app/src/main/res/layout/fragment_merchant_config.xml 
b/app/src/main/res/layout/fragment_merchant_config.xml
index 0f0b96f..759073a 100644
--- a/app/src/main/res/layout/fragment_merchant_config.xml
+++ b/app/src/main/res/layout/fragment_merchant_config.xml
@@ -121,6 +121,16 @@
                 app:layout_constraintTop_toTopOf="@+id/okButton"
                 tools:visibility="visible" />
 
+        <TextView
+                android:id="@+id/configDocsView"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_margin="16dp"
+                android:text="@string/config_docs"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@+id/okButton" />
+
     </androidx.constraintlayout.widget.ConstraintLayout>
 
 </ScrollView>
diff --git a/app/src/main/res/values/strings.xml 
b/app/src/main/res/values/strings.xml
index 149df6e..7ce1ecb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -29,6 +29,7 @@
     <string name="config_forget_password">Forget</string>
     <string name="config_changed">Changed to new merchant using %s</string>
     <string name="config_fetching_label">Fetching Configuration</string>
+    <string name="config_docs">Please refer to <a 
href="https://docs.taler.net/taler-merchant-pos-terminal.html#apis-and-data-formats";>the
 documentation</a> for the configuration format.</string>
 
     <string name="payment_intro_nfc">Please scan QR Code or use NFC to 
pay</string>
     <string name="payment_intro">Please scan QR Code to pay</string>
diff --git a/build.gradle b/build.gradle
index e252cd1..d0a284a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,7 @@ buildscript {
         
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.6.0'
+        classpath 'com.android.tools.build:gradle:3.6.1'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
         classpath 
"androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
     }
diff --git a/nightly-stats.patch b/nightly-stats.patch
new file mode 100644
index 0000000..689f46a
--- /dev/null
+++ b/nightly-stats.patch
@@ -0,0 +1,38 @@
+diff --git a/fdroidserver/nightly.py b/fdroidserver/nightly.py
+index 0a3a8012..ae3aa0e3 100644
+--- a/fdroidserver/nightly.py
++++ b/fdroidserver/nightly.py
+@@ -170,6 +170,7 @@ def main():
+         git_mirror_path = os.path.join(repo_basedir, 'git-mirror')
+         git_mirror_repodir = os.path.join(git_mirror_path, 'fdroid', 'repo')
+         git_mirror_metadatadir = os.path.join(git_mirror_path, 'fdroid', 
'metadata')
++        git_mirror_statsdir = os.path.join(git_mirror_path, 'fdroid', 'stats')
+         if not os.path.isdir(git_mirror_repodir):
+             logging.debug(_('cloning {url}').format(url=clone_url))
+             try:
+@@ -217,6 +218,8 @@ Last updated: {date}'''.format(repo_git_base=repo_git_base,
+             common.local_rsync(options, git_mirror_repodir + '/', 'repo/')
+         if os.path.isdir(git_mirror_metadatadir):
+             common.local_rsync(options, git_mirror_metadatadir + '/', 
'metadata/')
++        if os.path.isdir(git_mirror_statsdir):
++            common.local_rsync(options, git_mirror_statsdir + '/', 'stats/')
+ 
+         ssh_private_key_file = _ssh_key_from_debug_keystore()
+         # this is needed for GitPython to find the SSH key
+@@ -246,7 +249,7 @@ Last updated: {date}'''.format(repo_git_base=repo_git_base,
+         config += "keydname = '%s'\n" % DISTINGUISHED_NAME
+         config += "make_current_version_link = False\n"
+         config += "accepted_formats = ('txt', 'yml')\n"
+-        # TODO add update_stats = True
++        config += "update_stats = True\n"
+         with open('config.py', 'w') as fp:
+             fp.write(config)
+         os.chmod('config.py', 0o600)
+@@ -293,6 +296,7 @@ Last updated: {date}'''.format(repo_git_base=repo_git_base,
+         subprocess.check_call(['fdroid', 'update', '--rename-apks', 
'--create-metadata', '--verbose'],
+                               cwd=repo_basedir)
+         common.local_rsync(options, repo_basedir + '/metadata/', 
git_mirror_metadatadir + '/')
++        common.local_rsync(options, repo_basedir + '/stats/', 
git_mirror_statsdir + '/')
+         mirror_git_repo.git.add(all=True)
+         mirror_git_repo.index.commit("update app metadata")
+ 

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]