Skip to content

Commit 246d3a2

Browse files
committed
Update
1 parent 2d3ad97 commit 246d3a2

6 files changed

Lines changed: 116 additions & 128 deletions

File tree

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,23 @@
11
package com.omarea.common.shell
22

33
import android.content.Context
4-
import com.tool.tree.LanguageManager
4+
import com.omarea.krscript.config.StringResRef
55

6-
// 从Resource解析字符串,实现输出内容多语言
6+
// Từ Resource解析字符串,实现输出内容多语言
77
class ShellTranslation(private val context: Context) {
88

9-
// 示例:
10-
// @string:home_shell_01
11-
private val resRegex =
12-
Regex("@(string|dimen)[:/][_a-z][_0-9a-z]*", RegexOption.IGNORE_CASE)
13-
14-
fun resolveRow(originRow: String): String? {
15-
var result = originRow
16-
val res = LanguageManager.resources(context)
17-
18-
resRegex.findAll(originRow).forEach { match ->
19-
val row = match.value
20-
val separator = if (row.contains(":")) ':' else '/'
21-
val type = row.substring(1, row.indexOf(separator))
22-
val name = row.substring(row.indexOf(separator) + 1)
23-
24-
val id = res.getIdentifier(name, type, context.packageName)
25-
if (id != 0) {
26-
val value = when (type) {
27-
"string" -> res.getString(id)
28-
"dimen" -> res.getDimensionPixelSize(id).toString()
29-
else -> null
30-
}
31-
if (value != null) {
32-
result = result.replace(row, value)
33-
}
34-
}
35-
}
36-
return result
9+
fun resolveRow(originRow: String): String {
10+
return StringResRef.resolve(context, originRow)
3711
}
3812

3913
fun resolveRows(rows: List<String>): String {
40-
val builder = StringBuilder()
41-
var first = true
42-
43-
for (row in rows) {
44-
val resolved = resolveRow(row) ?: continue
45-
46-
if (!first) {
47-
builder.append('\n')
48-
}
49-
builder.append(resolved)
50-
first = false
14+
return rows.joinToString("\n") {
15+
resolveRow(it)
5116
}
52-
return builder.toString()
5317
}
5418

5519
fun getTranslatedResult(shellCommand: String, executor: KeepShell?): String {
5620
val shell = executor ?: KeepShellPublic.getDefaultInstance()
57-
val rows = shell.doCmdSync(shellCommand).split("\n")
58-
return if (rows.isNotEmpty()) {
59-
resolveRows(rows)
60-
} else {
61-
""
62-
}
21+
return resolveRows(shell.doCmdSync(shellCommand).split('\n'))
6322
}
6423
}

app/src/main/java/com/omarea/krscript/config/PageConfigReader.kt

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import java.io.ByteArrayInputStream
1717
import java.io.InputStream
1818
import java.util.Locale.getDefault
1919
import androidx.core.graphics.toColorInt
20-
import com.tool.tree.LanguageManager
2120

2221
/**
2322
* Created by Hello on 2018/04/01.
@@ -32,41 +31,6 @@ class PageConfigReader {
3231
private var parentDir: String = ""
3332

3433
companion object {
35-
// Ví dụ: @string/update_text hoặc @string:update_text
36-
private val STRING_REF_REGEX = Regex("@string[:/][_a-zA-Z][_a-zA-Z0-9]*")
37-
}
38-
39-
/**
40-
* Thay thế các tham chiếu dạng @string/ten_resource (hoặc @string:ten_resource) xuất hiện
41-
* trong văn bản đọc từ XML bằng giá trị thật lấy từ strings.xml của ứng dụng.
42-
* Nếu không tìm thấy resource tương ứng thì giữ nguyên văn bản gốc.
43-
*/
44-
private fun resolveStringRes(raw: String?): String {
45-
val text = raw ?: return ""
46-
if (!text.contains("@string")) {
47-
return text
48-
}
49-
50-
val res = LanguageManager.resources(context)
51-
52-
var result = text
53-
STRING_REF_REGEX.findAll(text).forEach { match ->
54-
val token = match.value
55-
val separator = if (token.contains(":")) ':' else '/'
56-
val name = token.substring(token.indexOf(separator) + 1)
57-
58-
try {
59-
val id = res.getIdentifier(name, "string", context.packageName)
60-
if (id != 0) {
61-
result = result.replace(token, res.getString(id))
62-
}
63-
} catch (_: Exception) {
64-
}
65-
}
66-
67-
return result
68-
}
69-
7034
private fun sanitizeXmlContent(raw: String): String {
7135
var result = raw
7236

@@ -296,7 +260,7 @@ class PageConfigReader {
296260
var actionParamInfo: ActionParamInfo? = null
297261
private fun tagStartInAction(action: ActionNode, parser: XmlPullParser) {
298262
if ("title" == parser.name) {
299-
action.title = resolveStringRes(parser.nextText())
263+
action.title = StringResRef.resolve(context, parser.nextText())
300264
} else if ("desc" == parser.name) {
301265
descNode(action, parser)
302266
} else if ("summary" == parser.name) {
@@ -381,7 +345,7 @@ class PageConfigReader {
381345
option.value = parser.getAttributeValue(i)
382346
}
383347
}
384-
option.title = resolveStringRes(parser.nextText())
348+
option.title = StringResRef.resolve(context, parser.nextText())
385349
if (option.value == null)
386350
option.value = option.title
387351
actionParamInfo.options!!.add(option)
@@ -405,7 +369,7 @@ class PageConfigReader {
405369

406370
private fun tagStartInPage(node: PageNode, parser: XmlPullParser) {
407371
when (parser.name) {
408-
"title" -> node.title = resolveStringRes(parser.nextText())
372+
"title" -> node.title = StringResRef.resolve(context, parser.nextText())
409373
"desc" -> descNode(node, parser)
410374
"summary" -> summaryNode(node, parser)
411375
"resource" -> resourceNode(parser)
@@ -454,7 +418,7 @@ class PageConfigReader {
454418
"config-sh" -> option.pageConfigSh = parser.getAttributeValue(i)
455419
}
456420
}
457-
option.title = resolveStringRes(parser.nextText())
421+
option.title = StringResRef.resolve(context, parser.nextText())
458422
if (option.key.isEmpty()) {
459423
option.key = option.title
460424
}
@@ -470,7 +434,7 @@ class PageConfigReader {
470434

471435
private fun tagStartInSwitch(switchNode: SwitchNode, parser: XmlPullParser) {
472436
when (parser.name) {
473-
"title" -> switchNode.title = resolveStringRes(parser.nextText())
437+
"title" -> switchNode.title = StringResRef.resolve(context, parser.nextText())
474438
"desc" -> descNode(switchNode, parser)
475439
"summary" -> summaryNode(switchNode, parser)
476440
"get", "getstate" -> switchNode.getState = parser.nextText()
@@ -487,7 +451,7 @@ class PageConfigReader {
487451
val attrValue = parser.getAttributeValue(i)
488452
when (attrName) {
489453
"key", "index", "id" -> groupInfo.key = attrValue.trim()
490-
"title" -> groupInfo.title = resolveStringRes(attrValue)
454+
"title" -> groupInfo.title = StringResRef.resolve(context, attrValue)
491455
"support", "visible" -> groupInfo.supported = executeResultRoot(context, attrValue) == "1"
492456
}
493457
}
@@ -643,7 +607,7 @@ class PageConfigReader {
643607
}
644608
}
645609
if (nodeInfoBase.desc.isEmpty())
646-
nodeInfoBase.desc = resolveStringRes(parser.nextText())
610+
nodeInfoBase.desc = StringResRef.resolve(context, parser.nextText())
647611
}
648612

649613
private fun summaryNode(nodeInfoBase: NodeInfoBase, parser: XmlPullParser) {
@@ -655,7 +619,7 @@ class PageConfigReader {
655619
}
656620
}
657621
if (nodeInfoBase.summary.isEmpty())
658-
nodeInfoBase.summary = resolveStringRes(parser.nextText())
622+
nodeInfoBase.summary = StringResRef.resolve(context, parser.nextText())
659623
}
660624

661625
private fun resourceNode(parser: XmlPullParser) {
@@ -685,7 +649,7 @@ class PageConfigReader {
685649
private fun tagStartInText(textNode: TextNode, parser: XmlPullParser) {
686650
when (parser.name) {
687651
"title" -> {
688-
textNode.title = resolveStringRes(parser.nextText())
652+
textNode.title = StringResRef.resolve(context, parser.nextText())
689653
}
690654
"desc" -> {
691655
descNode(textNode, parser)
@@ -739,14 +703,14 @@ class PageConfigReader {
739703
} catch (ex: Exception) {
740704
}
741705
}
742-
textRow.text = resolveStringRes("" + parser.nextText())
706+
textRow.text = StringResRef.resolve(context, parser.nextText())
743707
textNode.rows.add(textRow)
744708
}
745709

746710
private fun tagStartInPicker(pickerNode: PickerNode, parser: XmlPullParser) {
747711
when (parser.name) {
748712
"title" -> {
749-
pickerNode.title = resolveStringRes(parser.nextText())
713+
pickerNode.title = StringResRef.resolve(context, parser.nextText())
750714
}
751715
"desc" -> {
752716
descNode(pickerNode, parser)
@@ -765,7 +729,7 @@ class PageConfigReader {
765729
option.value = parser.getAttributeValue(i)
766730
}
767731
}
768-
option.title = resolveStringRes(parser.nextText())
732+
option.title = StringResRef.resolve(context, parser.nextText())
769733
if (option.value == null)
770734
option.value = option.title
771735
pickerNode.options!!.add(option)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.omarea.krscript.config
2+
3+
import android.content.Context
4+
import com.tool.tree.LanguageManager
5+
6+
object StringResRef {
7+
private val STRING_REF_REGEX =
8+
Regex("""@string[:/]([_a-zA-Z][_a-zA-Z0-9]*)""")
9+
10+
fun resolve(context: Context, raw: String?): String {
11+
if (raw.isNullOrEmpty() || !raw.contains("@string")) {
12+
return raw ?: ""
13+
}
14+
15+
val res = LanguageManager.resources(context)
16+
17+
return STRING_REF_REGEX.replace(raw) { match ->
18+
val name = match.groupValues[1]
19+
try {
20+
val id = res.getIdentifier(name, "string", context.packageName)
21+
if (id != 0) res.getString(id) else match.value
22+
} catch (_: Exception) {
23+
match.value
24+
}
25+
}
26+
}
27+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.omarea.krscript.model
2+
3+
import android.content.Context
4+
import android.text.SpannableString
5+
6+
/**
7+
* Lớp "câm" (không log, không progress bar, không hộp nhập liệu) chỉ để tái sử dụng đúng
8+
* cơ chế phân tích output đặc biệt (am:[...] / progress:[...] / input:[...]) đã có sẵn ở
9+
* ShellHandlerBase - dùng cho các nơi chạy shell KHÔNG có dialog/log UI riêng (vd: chạy ẩn ở
10+
* menu, log khởi động ở SplashActivity...) nhưng vẫn cần hỗ trợ directive "am:[...]" (mở activity).
11+
*
12+
* Mặc định các dòng log thông thường (không phải am:[...]/progress:[...]/input:[...]) sẽ bị bỏ
13+
* qua (không hiển thị gì). Muốn hiển thị lại, hãy tạo class con và override onReader(msg).
14+
*/
15+
open class SilentShellOutputHandler(context: Context) : ShellHandlerBase(context) {
16+
override fun onProgress(current: Int, total: Int) {
17+
// Không có UI để hiển thị tiến trình -> bỏ qua có chủ đích.
18+
}
19+
20+
override fun onStart(msg: Any?) {}
21+
override fun onStart(forceStop: Runnable?) {}
22+
override fun onExit(msg: Any?) {}
23+
24+
override fun updateLog(msg: SpannableString?) {
25+
// Không có log view -> bỏ qua có chủ đích.
26+
}
27+
28+
/**
29+
* Đưa từng dòng output (đã tách theo \n) qua bộ phân tích của ShellHandlerBase.
30+
* Dòng nào khớp am:[...] sẽ tự động mở activity tương ứng; các directive khác
31+
* (progress:[...]/input:[...]) bị bỏ qua vì không có UI hiển thị.
32+
*/
33+
fun processOutput(output: String) {
34+
output.lineSequence().forEach { line ->
35+
if (line.isNotBlank()) {
36+
onReaderMsg(line)
37+
}
38+
}
39+
}
40+
}

app/src/main/java/com/tool/tree/ActionPage.kt

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import android.net.Uri
66
import android.os.Bundle
77
import android.os.Handler
88
import android.os.Looper
9-
import android.text.SpannableString
109
import android.view.Menu
1110
import android.view.MenuItem
1211
import android.view.View
@@ -33,7 +32,6 @@ import kotlinx.coroutines.Dispatchers
3332
import kotlinx.coroutines.Job
3433
import kotlinx.coroutines.async
3534
import kotlinx.coroutines.awaitAll
36-
import kotlinx.coroutines.coroutineScope
3735
import kotlinx.coroutines.isActive
3836
import kotlinx.coroutines.launch
3937
import kotlinx.coroutines.withContext
@@ -372,27 +370,6 @@ class ActionPage : AppCompatActivity() {
372370
}
373371
}
374372

375-
private class SilentShellOutputHandler(context: android.content.Context) : ShellHandlerBase(context) {
376-
override fun onProgress(current: Int, total: Int) {
377-
// Chạy ẩn không có UI để hiển thị tiến trình -> bỏ qua có chủ đích.
378-
}
379-
380-
override fun onStart(msg: Any?) {}
381-
override fun onStart(forceStop: Runnable?) {}
382-
override fun onExit(msg: Any?) {}
383-
override fun updateLog(msg: SpannableString?) {
384-
// Chạy ẩn không có log view -> bỏ qua có chủ đích.
385-
}
386-
387-
fun processOutput(output: String) {
388-
output.lineSequence().forEach { line ->
389-
if (line.isNotBlank()) {
390-
onReaderMsg(line)
391-
}
392-
}
393-
}
394-
}
395-
396373
private fun loadPageConfig(showLoading: Boolean = true) {
397374
val config = currentPageConfig ?: return
398375

0 commit comments

Comments
 (0)