forked from omni/OmniCards
feat: added QrScript support for templates
This commit is contained in:
@@ -47,6 +47,7 @@ android {
|
|||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
|
buildConfig = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package ru.omni_devel.cards
|
|||||||
|
|
||||||
const val REPO_BASE_URL = "https://gitea.omni-devel.ru/omni/OmniCardsRepo/raw/branch/main"
|
const val REPO_BASE_URL = "https://gitea.omni-devel.ru/omni/OmniCardsRepo/raw/branch/main"
|
||||||
|
|
||||||
const val TEMPLATES_REPO_FILE = "templates.json"
|
val TEMPLATES_REPO_FILE = if (BuildConfig.DEBUG)
|
||||||
|
"templates.debug.json"
|
||||||
|
else
|
||||||
|
"templates.json"
|
||||||
|
|
||||||
const val ICONS_REPO_FILE = "icons.json"
|
const val ICONS_REPO_FILE = "icons.json"
|
||||||
const val ICONS_REPO_FOLDER = "icons"
|
const val ICONS_REPO_FOLDER = "icons"
|
||||||
|
|||||||
@@ -125,9 +125,11 @@ fun CardEditable(
|
|||||||
contract = ActivityResultContracts.StartActivityForResult()
|
contract = ActivityResultContracts.StartActivityForResult()
|
||||||
) { result ->
|
) { result ->
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
val codeValue = result.data?.getStringExtra("codeValue") ?: ""
|
val codeValue = result.data?.getStringExtra("codeValue")!!
|
||||||
|
val codeType = BarcodeFormat.valueOf(result.data?.getStringExtra("codeType")!!)
|
||||||
|
|
||||||
onCodeValueChange(codeValue)
|
onCodeValueChange(codeValue)
|
||||||
|
onCodeTypeChange(codeType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,15 +87,18 @@ fun FillTemplatePage(template: Template, innerPadding: PaddingValues) {
|
|||||||
return@AdaptiveButton
|
return@AdaptiveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = template.template
|
val result = try {
|
||||||
|
processQrScript(template.template, filledFields)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show()
|
||||||
|
|
||||||
for ((id, value) in filledFields) {
|
return@AdaptiveButton
|
||||||
result = result.replace("$$id$", value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val resultIntent = Intent()
|
val resultIntent = Intent()
|
||||||
|
|
||||||
resultIntent.putExtra("codeValue", result)
|
resultIntent.putExtra("codeValue", result)
|
||||||
|
resultIntent.putExtra("codeType", template.codeType.name)
|
||||||
|
|
||||||
activityContext!!.setResult(Activity.RESULT_OK, resultIntent)
|
activityContext!!.setResult(Activity.RESULT_OK, resultIntent)
|
||||||
activityContext.finish()
|
activityContext.finish()
|
||||||
|
|||||||
@@ -84,10 +84,12 @@ fun SelectTemplatePage(innerPadding: PaddingValues) {
|
|||||||
) { result ->
|
) { result ->
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
val codeValue = result.data?.getStringExtra("codeValue")
|
val codeValue = result.data?.getStringExtra("codeValue")
|
||||||
|
val codeTypeString = result.data?.getStringExtra("codeType")
|
||||||
|
|
||||||
val resultIntent = Intent()
|
val resultIntent = Intent()
|
||||||
|
|
||||||
resultIntent.putExtra("codeValue", codeValue)
|
resultIntent.putExtra("codeValue", codeValue)
|
||||||
|
resultIntent.putExtra("codeType", codeTypeString)
|
||||||
|
|
||||||
activityContext!!.setResult(Activity.RESULT_OK, resultIntent)
|
activityContext!!.setResult(Activity.RESULT_OK, resultIntent)
|
||||||
activityContext.finish()
|
activityContext.finish()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.omni_devel.cards
|
package ru.omni_devel.cards
|
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
@@ -16,7 +17,8 @@ class Field(
|
|||||||
class Template(
|
class Template(
|
||||||
val names: LinkedHashMap<String, String>,
|
val names: LinkedHashMap<String, String>,
|
||||||
val fields: List<Field>,
|
val fields: List<Field>,
|
||||||
val template: String
|
val template: String,
|
||||||
|
val codeType: BarcodeFormat = BarcodeFormat.QR_CODE
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
fun parseTemplateFromJson(json: String): Template {
|
fun parseTemplateFromJson(json: String): Template {
|
||||||
@@ -39,7 +41,8 @@ class Template(
|
|||||||
return Template(
|
return Template(
|
||||||
names = jsonObjectToMap(obj.getJSONObject("names")),
|
names = jsonObjectToMap(obj.getJSONObject("names")),
|
||||||
fields = fields,
|
fields = fields,
|
||||||
template = obj.getString("template")
|
template = obj.getString("template"),
|
||||||
|
codeType = parseCodeType(obj)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,11 +70,21 @@ class Template(
|
|||||||
templates.add(Template(
|
templates.add(Template(
|
||||||
names = jsonObjectToMap(obj.getJSONObject("names")),
|
names = jsonObjectToMap(obj.getJSONObject("names")),
|
||||||
fields = fields,
|
fields = fields,
|
||||||
template = obj.getString("template")
|
template = obj.getString("template"),
|
||||||
|
codeType = parseCodeType(obj)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
return templates
|
return templates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun parseCodeType(obj: JSONObject): BarcodeFormat {
|
||||||
|
val raw = obj.optString("codeType", "")
|
||||||
|
return if (raw.isBlank()) {
|
||||||
|
BarcodeFormat.QR_CODE
|
||||||
|
} else {
|
||||||
|
BarcodeFormat.valueOf(raw)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,3 +121,41 @@ fun base64ToImageBitmap(base64String: String): ImageBitmap {
|
|||||||
|
|
||||||
return bitmap.asImageBitmap()
|
return bitmap.asImageBitmap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun processQrScript(input: String, fills: Map<String, String>): String {
|
||||||
|
val outerRegex = Regex("""\$(\w+)((?:\([^)]*\))*)\$""")
|
||||||
|
val innerRegex = Regex("""\(([^)]*)\)""")
|
||||||
|
|
||||||
|
var result = input
|
||||||
|
|
||||||
|
outerRegex.findAll(input).forEach { match ->
|
||||||
|
val fullBlock = match.value
|
||||||
|
val name = match.groupValues[1]
|
||||||
|
val contents = innerRegex.findAll(match.groupValues[2]).map { it.groupValues[1] }.toList()
|
||||||
|
|
||||||
|
var blockResult = fills[name] ?: return@forEach
|
||||||
|
|
||||||
|
contents.forEach { content ->
|
||||||
|
val args = content.split(" ")
|
||||||
|
val action = args[0]
|
||||||
|
|
||||||
|
when (action) {
|
||||||
|
"first" -> {
|
||||||
|
val count = args[1].toInt()
|
||||||
|
|
||||||
|
blockResult = blockResult.take(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
"last" -> {
|
||||||
|
val count = args[1].toInt()
|
||||||
|
|
||||||
|
blockResult = blockResult.takeLast(count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result.replace(fullBlock, blockResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user