Skip to content

Commit e89829d

Browse files
committed
Update
1 parent 743a760 commit e89829d

4 files changed

Lines changed: 68 additions & 101 deletions

File tree

-32 Bytes
Loading

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

Lines changed: 56 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.app.Dialog
44
import android.content.ClipData
55
import android.content.ClipboardManager
66
import android.content.Context
7+
import android.content.DialogInterface
78
import android.os.Build
89
import android.os.Bundle
910
import android.os.Message
@@ -12,19 +13,15 @@ import android.view.KeyEvent
1213
import android.view.LayoutInflater
1314
import android.view.View
1415
import android.view.ViewGroup
15-
import android.widget.ProgressBar
16-
import android.widget.ScrollView
17-
import android.widget.TextView
18-
import android.widget.Toast
1916
import android.view.WindowManager
17+
import android.widget.*
2018
import androidx.fragment.app.DialogFragment
2119
import com.omarea.common.ui.DialogHelper
22-
import com.tool.tree.databinding.KrDialogLogBinding
2320
import com.omarea.krscript.executor.ShellExecutor
2421
import com.omarea.krscript.model.RunnableNode
2522
import com.omarea.krscript.model.ShellHandlerBase
26-
import android.content.DialogInterface
2723
import com.tool.tree.R
24+
import com.tool.tree.databinding.KrDialogLogBinding
2825
import java.lang.ref.WeakReference
2926

3027
class DialogLogFragment : DialogFragment() {
@@ -41,14 +38,9 @@ class DialogLogFragment : DialogFragment() {
4138
private var themeResId: Int = 0
4239
private var onDismissRunnable: Runnable? = null
4340

44-
// Lưu tham chiếu Handler để giải phóng khi hủy View
4541
private var currentHandler: MyShellHandler? = null
4642

47-
override fun onCreateView(
48-
inflater: LayoutInflater,
49-
container: ViewGroup?,
50-
savedInstanceState: Bundle?
51-
): View {
43+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
5244
_binding = KrDialogLogBinding.inflate(inflater, container, false)
5345
return binding.root
5446
}
@@ -110,7 +102,9 @@ class DialogLogFragment : DialogFragment() {
110102
binding.btnCopy.setOnClickListener {
111103
try {
112104
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
113-
val clip = ClipData.newPlainText("text", binding.shellOutput.text.toString())
105+
// Lấy toàn bộ text từ StringBuilder của handler (không bị giới hạn bởi ListView)
106+
val fullLog = currentHandler?.getAllLogText() ?: ""
107+
val clip = ClipData.newPlainText("shell_log", fullLog)
114108
clipboard.setPrimaryClip(clip)
115109
Toast.makeText(requireContext(), getString(R.string.copy_success), Toast.LENGTH_SHORT).show()
116110
} catch (e: Exception) {
@@ -126,20 +120,12 @@ class DialogLogFragment : DialogFragment() {
126120
binding.btnCancel.visibility = View.GONE
127121
}
128122

129-
if (nodeInfo.title.isNotEmpty()) {
130-
binding.title.text = nodeInfo.title
131-
} else {
132-
binding.title.visibility = View.GONE
133-
}
134-
135-
if (nodeInfo.desc.isNotEmpty()) {
136-
binding.desc.text = nodeInfo.desc
137-
} else {
138-
binding.desc.visibility = View.GONE
139-
}
123+
binding.title.text = if (nodeInfo.title.isNotEmpty()) nodeInfo.title else { binding.title.visibility = View.GONE; "" }
124+
binding.desc.text = if (nodeInfo.desc.isNotEmpty()) nodeInfo.desc else { binding.desc.visibility = View.GONE; "" }
140125

141126
binding.actionProgress.isIndeterminate = true
142127

128+
// Khởi tạo Handler với ListView
143129
val handler = MyShellHandler(requireContext().applicationContext, object : IActionEventHandler {
144130
override fun onCompleted() {
145131
running = false
@@ -162,18 +148,11 @@ class DialogLogFragment : DialogFragment() {
162148
running = true
163149
canceled = false
164150
forceStopRunnable = forceStop
165-
166151
dialog?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
167-
168-
if (nodeInfo.interruptable && forceStop != null) {
169-
binding.btnCancel.visibility = View.VISIBLE
170-
binding.btnExit.visibility = View.GONE
171-
} else {
172-
binding.btnExit.visibility = View.GONE
173-
binding.btnCancel.visibility = View.GONE
174-
}
152+
binding.btnExit.visibility = View.GONE
153+
binding.btnCancel.visibility = if (nodeInfo.interruptable && forceStop != null) View.VISIBLE else View.GONE
175154
}
176-
}, binding.shellOutput, binding.actionProgress)
155+
}, binding.shellOutputList, binding.actionProgress)
177156

178157
this.currentHandler = handler
179158
return handler
@@ -189,33 +168,42 @@ class DialogLogFragment : DialogFragment() {
189168
class MyShellHandler(
190169
context: Context,
191170
private var actionEventHandler: IActionEventHandler?,
192-
logView: TextView?,
171+
listView: ListView?,
193172
shellProgress: ProgressBar?
194173
) : ShellHandlerBase(context) {
195174

196-
private val logViewRef = WeakReference(logView)
175+
private val listViewRef = WeakReference(listView)
197176
private val progressRef = WeakReference(shellProgress)
198177

178+
// Dữ liệu cho hiển thị (Giới hạn 5k dòng)
179+
private val logData = mutableListOf<SpannableString>()
180+
private val adapter = ArrayAdapter<SpannableString>(context, android.R.layout.simple_list_item_1, logData)
181+
182+
// Dữ liệu cho Copy (Không giới hạn)
183+
private val fullLogBuilder = StringBuilder()
184+
199185
private val errorColor = getColor(R.color.kr_shell_log_error)
200186
private val basicColor = getColor(R.color.kr_shell_log_basic)
201187
private val scriptColor = getColor(R.color.kr_shell_log_script)
202188
private val endColor = getColor(R.color.kr_shell_log_end)
203189
private var hasError = false
204190

191+
init {
192+
listView?.adapter = adapter
193+
}
194+
205195
private fun getColor(resId: Int): Int {
206-
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
207-
context.getColor(resId)
208-
} else {
209-
context.resources.getColor(resId)
210-
}
196+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) context.getColor(resId) else context.resources.getColor(resId)
211197
}
212198

213199
fun release() {
214-
logViewRef.clear()
200+
listViewRef.clear()
215201
progressRef.clear()
216202
actionEventHandler = null
217203
}
218204

205+
fun getAllLogText(): String = fullLogBuilder.toString()
206+
219207
override fun handleMessage(msg: Message) {
220208
when (msg.what) {
221209
EVENT_EXIT -> onExit(msg.obj)
@@ -241,45 +229,45 @@ class DialogLogFragment : DialogFragment() {
241229
val shellProgress = progressRef.get() ?: return
242230
shellProgress.post {
243231
when {
244-
current < 0 -> shellProgress.apply {
245-
visibility = View.VISIBLE
246-
isIndeterminate = true
247-
}
232+
current < 0 -> { shellProgress.visibility = View.VISIBLE; shellProgress.isIndeterminate = true }
248233
current >= total -> shellProgress.visibility = View.GONE
249-
else -> shellProgress.apply {
250-
visibility = View.VISIBLE
251-
isIndeterminate = false
252-
max = total
253-
progress = current
254-
(layoutParams as? ViewGroup.MarginLayoutParams)?.let { params ->
255-
params.height = 4
256-
params.topMargin = 44
257-
layoutParams = params
258-
}
234+
else -> {
235+
shellProgress.visibility = View.VISIBLE
236+
shellProgress.isIndeterminate = false
237+
shellProgress.max = total
238+
shellProgress.progress = current
259239
}
260240
}
261241
}
262242
}
263243

264244
override fun onStart(msg: Any?) {
265-
logViewRef.get()?.text = ""
245+
logData.clear()
246+
fullLogBuilder.setLength(0)
247+
adapter.notifyDataSetChanged()
266248
}
267249

268250
override fun onExit(msg: Any?) {
269251
val code = (msg as? Int) ?: -1
270-
if (!hasError && code == 0) {
271-
actionEventHandler?.onSuccess()
272-
}
252+
if (!hasError && code == 0) actionEventHandler?.onSuccess()
273253
updateLog(context.getString(R.string.kr_shell_completed), endColor)
274254
actionEventHandler?.onCompleted()
275255
}
276256

277257
override fun updateLog(msg: SpannableString?) {
278-
val logView = logViewRef.get() ?: return
258+
val listView = listViewRef.get() ?: return
279259
msg?.let {
280-
logView.post {
281-
logView.append(it)
282-
(logView.parent as? ScrollView)?.fullScroll(ScrollView.FOCUS_DOWN)
260+
// Thêm vào Builder cho việc Copy (Không giới hạn)
261+
fullLogBuilder.append(it.toString()).append("\n")
262+
263+
// Cập nhật giao diện (Giới hạn 5000 dòng cuối)
264+
listView.post {
265+
logData.add(it)
266+
if (logData.size > 5000) {
267+
logData.subList(0, logData.size - 5000).clear()
268+
}
269+
adapter.notifyDataSetChanged()
270+
listView.setSelection(logData.size - 1)
283271
}
284272
}
285273
}
@@ -289,25 +277,17 @@ class DialogLogFragment : DialogFragment() {
289277
super.onResume()
290278
dialog?.setOnKeyListener { _, keyCode, event ->
291279
if (!uiVisible || !running) return@setOnKeyListener false
292-
event.action == KeyEvent.ACTION_DOWN &&
293-
(keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
280+
event.action == KeyEvent.ACTION_DOWN && (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
294281
}
295282
}
296283

297-
private fun offScreen() {
298-
dialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
299-
}
284+
private fun offScreen() = dialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
300285

301-
private fun closeView() {
302-
try {
303-
dismissAllowingStateLoss()
304-
} catch (ex: Exception) {}
305-
}
286+
private fun closeView() { try { dismissAllowingStateLoss() } catch (ex: Exception) {} }
306287

307288
override fun onDismiss(dialog: DialogInterface) {
308289
super.onDismiss(dialog)
309290
onDismissRunnable?.run()
310-
onDismissRunnable = null
311291
}
312292

313293
override fun onDestroyView() {
@@ -323,14 +303,7 @@ class DialogLogFragment : DialogFragment() {
323303
}
324304

325305
companion object {
326-
fun create(
327-
nodeInfo: RunnableNode,
328-
onExit: Runnable,
329-
onDismiss: Runnable,
330-
script: String,
331-
params: HashMap<String, String>?,
332-
darkMode: Boolean = false
333-
): DialogLogFragment {
306+
fun create(nodeInfo: RunnableNode, onExit: Runnable, onDismiss: Runnable, script: String, params: HashMap<String, String>?, darkMode: Boolean = false): DialogLogFragment {
334307
val fragment = DialogLogFragment()
335308
fragment.nodeInfo = nodeInfo
336309
fragment.onExit = onExit

app/src/main/res/layout/kr_dialog_log.xml

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,20 @@
3939

4040
</LinearLayout>
4141

42-
<ScrollView
43-
android:layout_marginTop="16dp"
44-
android:background="@drawable/krscript_item_ripple_kon"
42+
<ListView
43+
android:id="@+id/shell_output_list"
4544
android:layout_width="match_parent"
4645
android:layout_height="match_parent"
47-
android:overScrollMode="never"
4846
android:layout_above="@id/bottom_actions"
49-
android:layout_below="@+id/top_bar">
50-
51-
<TextView
52-
android:id="@+id/shell_output"
53-
android:breakStrategy="simple"
54-
android:textIsSelectable="true"
55-
android:layout_width="match_parent"
56-
android:layout_height="wrap_content"
57-
android:fontFamily="monospace"
58-
android:textSize="12sp"
59-
android:padding="12dp" />
60-
61-
</ScrollView>
47+
android:layout_below="@+id/top_bar"
48+
android:layout_marginTop="16dp"
49+
android:background="@drawable/krscript_item_ripple_kon"
50+
android:divider="@null"
51+
android:dividerHeight="0dp"
52+
android:stackFromBottom="true"
53+
android:transcriptMode="alwaysScroll"
54+
android:padding="8dp"
55+
android:overScrollMode="never" />
6256

6357
<LinearLayout
6458
android:id="@+id/bottom_actions"

app/src/main/res/layout/kr_switch_list_item.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
android:id="@id/kr_shortcut_icon"
1919
android:layout_width="10dp"
2020
android:layout_height="10dp"
21-
android:padding="5dp"
2221
android:layout_marginStart="6dp"
2322
android:layout_marginTop="6dp"
2423
android:src="@drawable/kr_shortcut_icon"
@@ -47,6 +46,7 @@
4746
android:layout_gravity="center_vertical"
4847
android:clickable="false"
4948
android:elevation="5dp"
49+
android:padding="5dp"
5050
android:enabled="false"
5151
android:focusable="false" />
5252

0 commit comments

Comments
 (0)