ui: add log items in buffered batches

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2023-03-28 17:47:36 +02:00
parent 2da80e8dee
commit d7ccbd92e5

View File

@ -185,36 +185,47 @@ class LogViewerActivity : AppCompatActivity() {
return@withContext return@withContext
} }
val stdout = BufferedReader(InputStreamReader(process!!.inputStream, StandardCharsets.UTF_8)) val stdout = BufferedReader(InputStreamReader(process!!.inputStream, StandardCharsets.UTF_8))
var haveScrolled = false
val start = System.nanoTime() var posStart = 0
var startPeriod = start var timeLastNotify = System.nanoTime()
var priorModified = false
val bufferedLogLines = arrayListOf<LogLine>()
var timeout = 1000000000L / 2 // The timeout is initially small so that the view gets populated immediately.
while (true) { while (true) {
val line = stdout.readLine() ?: break val line = stdout.readLine() ?: break
rawLogLines.append(line) rawLogLines.append(line)
rawLogLines.append('\n') rawLogLines.append('\n')
val logLine = parseLine(line) val logLine = parseLine(line)
withContext(Dispatchers.Main.immediate) { if (logLine != null) {
if (logLine != null) { bufferedLogLines.add(logLine)
recyclerView?.let { } else {
val shouldScroll = haveScrolled && !it.canScrollVertically(1) if (bufferedLogLines.isNotEmpty()) {
logLines.add(logLine) bufferedLogLines.last().msg += "\n$line"
if (haveScrolled) logAdapter.notifyDataSetChanged() } else if (logLines.isNotEmpty()) {
if (shouldScroll) logLines.last().msg += "\n$line"
it.scrollToPosition(logLines.size - 1) priorModified = true
}
} else {
logLines.lastOrNull()?.msg += "\n$line"
if (haveScrolled) logAdapter.notifyDataSetChanged()
} }
if (!haveScrolled) { }
val end = System.nanoTime() val timeNow = System.nanoTime()
val scroll = (end - start) > 1000000000L * 2.5 || !stdout.ready() if ((timeNow - timeLastNotify) < timeout && stdout.ready())
if (logLines.isNotEmpty() && (scroll || (end - startPeriod) > 1000000000L / 4)) { continue
logAdapter.notifyDataSetChanged() timeout = 1000000000L * 5 / 2 // Increase the timeout after the initial view has something in it.
recyclerView?.scrollToPosition(logLines.size - 1) timeLastNotify = timeNow
startPeriod = end
} withContext(Dispatchers.Main.immediate) {
if (scroll) haveScrolled = true val isScrolledToBottomAlready = recyclerView?.canScrollVertically(1) == false
if (priorModified) {
logAdapter.notifyItemChanged(posStart - 1)
priorModified = false
}
logLines.addAll(bufferedLogLines)
bufferedLogLines.clear()
logAdapter.notifyItemRangeInserted(posStart, logLines.size - posStart)
posStart = logLines.size
if (isScrolledToBottomAlready) {
recyclerView?.scrollToPosition(logLines.size - 1)
} }
} }
} }