Skip to content

Commit f894e12

Browse files
committed
Update
1 parent b3dae30 commit f894e12

3 files changed

Lines changed: 79 additions & 32 deletions

File tree

app/src/main/assets/home/etc/boot

-544 Bytes
Binary file not shown.

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,24 @@ class PageConfigReader {
357357
"depend-logic", "depend-priority" -> {
358358
actionParamInfo.dependLogic = attrValue
359359
}
360+
"depend-default" -> {
361+
actionParamInfo.dependDefault = attrValue
362+
}
363+
"depend-initial", "depend-initial-state" -> {
364+
actionParamInfo.dependInitialState = attrValue
365+
}
366+
"depend-negate" -> {
367+
actionParamInfo.dependNegate = attrValue == "true" || attrValue == "1" || attrValue == "negate"
368+
}
369+
"depend-threshold" -> {
370+
actionParamInfo.dependThreshold = attrValue.toIntOrNull() ?: -1
371+
}
372+
"depend-include-hidden" -> {
373+
actionParamInfo.dependIncludeHidden = attrValue == "true" || attrValue == "1"
374+
}
375+
"depend-onchange", "depend-on-change", "depend-callback" -> {
376+
actionParamInfo.dependOnChangeCallback = attrValue
377+
}
360378
}
361379
}
362380
if (actionParamInfo.supported && actionParamInfo.name != null && actionParamInfo.name!!.isNotEmpty()) {

app/src/main/java/com/omarea/krscript/ui/DialogLogFragment.kt

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import com.omarea.krscript.model.RunnableNode
3030
import com.omarea.krscript.model.ShellHandlerBase
3131
import java.lang.ref.WeakReference
3232
import com.tool.tree.AnsiColorParser
33+
import java.util.concurrent.atomic.AtomicBoolean
3334

3435
class DialogLogFragment : DialogFragment() {
3536

@@ -229,6 +230,15 @@ class DialogLogFragment : DialogFragment() {
229230
private var lineStart = 0
230231
private var pendingOverwrite = false
231232

233+
// Độ dài logBuffer đã được đẩy lên UI (chỉ đọc/ghi trong synchronized(logBuffer))
234+
private var uiAppliedLength = 0
235+
// true nếu lần vẽ UI tiếp theo cần set lại toàn bộ text (do \r ghi đè hoặc log bị cắt tỉa)
236+
private var needFullRefresh = false
237+
// Đảm bảo nhiều lần cập nhật log liên tiếp chỉ gộp lại thành 1 lần vẽ UI / 1 lần cuộn,
238+
// tránh spam Runnable + fullScroll() lên Main thread khi shell xả log dồn dập -> đây là
239+
// nguyên nhân chính gây giật/lag khi log in ra nhanh.
240+
private val pendingUiUpdate = AtomicBoolean(false)
241+
232242
init {
233243
// Không set trực tiếp editable ban đầu nữa, quản lý qua append tĩnh cho mượt
234244
logView?.text = ""
@@ -293,6 +303,8 @@ class DialogLogFragment : DialogFragment() {
293303
lineCount = 0
294304
lineStart = 0
295305
pendingOverwrite = false
306+
uiAppliedLength = 0
307+
needFullRefresh = false
296308
logBuffer.clear()
297309
}
298310
logViewRef.get()?.post {
@@ -375,10 +387,6 @@ class DialogLogFragment : DialogFragment() {
375387
*/
376388
private fun dispatchLogUpdate(formattedText: CharSequence) {
377389
val logView = logViewRef.get() ?: return
378-
379-
// Biến cục bộ để xác định xem dòng này có yêu cầu ghi đè hay không (\r)
380-
var isOverwriteAction = false
381-
val snapshotToDisplay: CharSequence
382390

383391
synchronized(logBuffer) {
384392
var i = 0
@@ -395,7 +403,7 @@ class DialogLogFragment : DialogFragment() {
395403
logBuffer.delete(lineStart, logBuffer.length)
396404
}
397405
pendingOverwrite = false
398-
isOverwriteAction = true
406+
needFullRefresh = true
399407
}
400408
logBuffer.append(segment)
401409
}
@@ -412,7 +420,7 @@ class DialogLogFragment : DialogFragment() {
412420
if (pendingOverwrite && lineStart in 0..logBuffer.length) {
413421
logBuffer.delete(lineStart, logBuffer.length)
414422
pendingOverwrite = false
415-
isOverwriteAction = true
423+
needFullRefresh = true
416424
}
417425
logBuffer.append('\n')
418426
lineCount++
@@ -443,39 +451,60 @@ class DialogLogFragment : DialogFragment() {
443451
logBuffer.delete(0, deleteEndIndex)
444452
lineCount = 5000
445453
lineStart = (lineStart - deleteEndIndex).coerceAtLeast(0)
446-
isOverwriteAction = true // Cần reload toàn bộ vì cấu trúc buffer đã dịch chuyển
454+
uiAppliedLength = (uiAppliedLength - deleteEndIndex).coerceAtLeast(0)
455+
needFullRefresh = true // Cần reload toàn bộ vì cấu trúc buffer đã dịch chuyển
447456
}
448457
}
458+
}
449459

450-
// Chụp lại trạng thái text hiện tại để ném lên UI hiển thị
451-
snapshotToDisplay = SpannableStringBuilder(logBuffer)
460+
// GỘP CẬP NHẬT UI: nếu đã có 1 lần vẽ đang chờ chạy trên Main thread thì không post thêm.
461+
// Khi Main thread rảnh và chạy tới, flushToUi() sẽ tự đọc trạng thái MỚI NHẤT của logBuffer,
462+
// nên nhiều dòng log đến dồn dập chỉ gây ra 1 lần setText/append + 1 lần cuộn, thay vì
463+
// một Runnable + một fullScroll() cho từng dòng -> đây là nguyên nhân chính gây giật.
464+
if (pendingUiUpdate.compareAndSet(false, true)) {
465+
logView.post {
466+
pendingUiUpdate.set(false)
467+
flushToUi(logView)
468+
}
452469
}
470+
}
453471

454-
// ĐẨY LÊN UI THREAD ĐỂ HIỂN THỊ
455-
logView.post {
456-
if (isOverwriteAction) {
457-
// Nếu có lệnh xóa dòng cũ đè dòng mới (\r) hoặc vừa bị cắt tỉa log > 5000 dòng, bắt buộc phải đặt lại text
458-
logView.text = snapshotToDisplay
459-
} else {
460-
// NẾU LÀ GHI TIẾP (APPEND): Đây là chìa khóa giúp log mượt!
461-
// Thay vì nạp lại toàn bộ 5000 dòng, chỉ truyền phần text mới tinh vào.
462-
val oldLen = logView.text.length
463-
if (snapshotToDisplay.length > oldLen) {
464-
val newChunk = snapshotToDisplay.subSequence(oldLen, snapshotToDisplay.length)
465-
logView.append(newChunk)
466-
}
472+
/**
473+
* Vẽ lên UI. Bình thường chỉ append phần text MỚI (không copy lại toàn bộ buffer),
474+
* chỉ khi có \r ghi đè dòng hoặc log vừa bị cắt tỉa (>5000 dòng) mới cần set lại toàn bộ.
475+
*/
476+
private fun flushToUi(logView: TextView) {
477+
val chunk: CharSequence?
478+
val doFullRefresh: Boolean
479+
480+
synchronized(logBuffer) {
481+
doFullRefresh = needFullRefresh
482+
needFullRefresh = false
483+
chunk = when {
484+
doFullRefresh -> SpannableStringBuilder(logBuffer)
485+
logBuffer.length > uiAppliedLength -> logBuffer.subSequence(uiAppliedLength, logBuffer.length)
486+
else -> null
467487
}
488+
uiAppliedLength = logBuffer.length
489+
}
468490

469-
// Tối ưu cuộn ScrollView xuống cuối
470-
(logView.parent as? ScrollView)?.let { scrollView ->
471-
scrollView.fullScroll(ScrollView.FOCUS_DOWN)
472-
473-
// Giữ focus thông minh không cần lồng post{} nhiều tầng
474-
val inputRow = inputRowRef.get()
475-
val input = shellInputRef.get()
476-
if (inputRow != null && inputRow.visibility == View.VISIBLE && input != null) {
477-
if (!input.isFocused) input.requestFocus()
478-
}
491+
if (chunk == null) return
492+
493+
if (doFullRefresh) {
494+
logView.text = chunk
495+
} else {
496+
logView.append(chunk)
497+
}
498+
499+
// Tối ưu cuộn ScrollView xuống cuối
500+
(logView.parent as? ScrollView)?.let { scrollView ->
501+
scrollView.fullScroll(ScrollView.FOCUS_DOWN)
502+
503+
// Giữ focus thông minh không cần lồng post{} nhiều tầng
504+
val inputRow = inputRowRef.get()
505+
val input = shellInputRef.get()
506+
if (inputRow != null && inputRow.visibility == View.VISIBLE && input != null) {
507+
if (!input.isFocused) input.requestFocus()
479508
}
480509
}
481510
}

0 commit comments

Comments
 (0)