[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.
- [taler-merchant-terminal-android] branch master updated (d1b7474 -> cac721a),
gnunet <=