@@ -102,7 +102,6 @@ class DialogLogFragment : DialogFragment() {
102102 binding.btnCopy.setOnClickListener {
103103 try {
104104 val clipboard = requireContext().getSystemService(Context .CLIPBOARD_SERVICE ) as ClipboardManager
105- // Lấy toàn bộ log từ Builder (không giới hạn 5000 dòng)
106105 val fullLog = currentHandler?.getAllLogText() ? : " "
107106 val clip = ClipData .newPlainText(" shell_log" , fullLog)
108107 clipboard.setPrimaryClip(clip)
@@ -173,11 +172,10 @@ class DialogLogFragment : DialogFragment() {
173172
174173 private val listViewRef = WeakReference (listView)
175174 private val progressRef = WeakReference (shellProgress)
176- private val logData = mutableListOf<SpannableString >()
175+ private val logData = mutableListOf<CharSequence >() // Dùng CharSequence để giữ nguyên Span
177176 private val fullLogBuilder = StringBuilder ()
178177
179- // Sử dụng log_item.xml bạn đã tạo
180- private val adapter = ArrayAdapter <SpannableString >(
178+ private val adapter = ArrayAdapter <CharSequence >(
181179 context,
182180 R .layout.log_item,
183181 android.R .id.text1,
@@ -261,38 +259,20 @@ class DialogLogFragment : DialogFragment() {
261259 override fun updateLog (msg : SpannableString ? ) {
262260 val listView = listViewRef.get() ? : return
263261 msg?.let { origin ->
264- // Lưu vào builder để Copy (giữ nguyên gốc kèm xuống dòng)
262+ // Lưu text gốc vào builder để copy không giới hạn
265263 fullLogBuilder.append(origin.toString()).append(" \n " )
266264
267- // Xử lý hiển thị
268- val rawStr = origin.toString()
269- val cleanStr = rawStr.trim(' \n ' , ' \r ' )
270- if (cleanStr.isEmpty()) return @let
271-
272- // Tạo Spannable mới để hiển thị khít dòng
273- val cleanSpannable = SpannableString (cleanStr)
274-
275- // SAO CHÉP MÀU SẮC: Chuyển các Span từ msg gốc sang bản hiển thị
276- val spans = origin.getSpans(0 , origin.length, Any ::class .java)
277- for (span in spans) {
278- val start = origin.getSpanStart(span)
279- val end = origin.getSpanEnd(span)
280-
281- if (start < cleanSpannable.length) {
282- val newEnd = if (end > cleanSpannable.length) cleanSpannable.length else end
283- try {
284- cleanSpannable.setSpan(span, start, newEnd, origin.getSpanFlags(span))
285- } catch (e: Exception ) {}
286- }
287- }
288-
289265 listView.post {
290- logData.add(cleanSpannable)
291- // Giới hạn 5000 dòng cuối trên giao diện
266+ // Đưa trực tiếp đối tượng SpannableString vào list để giữ màu
267+ logData.add(origin)
268+
269+ // Giới hạn 5000 dòng cuối để đảm bảo hiệu năng UI
292270 if (logData.size > 5000 ) {
293271 logData.subList(0 , logData.size - 5000 ).clear()
294272 }
273+
295274 adapter.notifyDataSetChanged()
275+ // Luôn cuộn tới dòng mới nhất ở dưới cùng
296276 listView.setSelection(logData.size - 1 )
297277 }
298278 }
0 commit comments