filter by crash buffer option

This commit is contained in:
qimiko committed 2024-01-23 01:31:38 -07:00
1 parent 1b079fa3ff
commit 590006413c
4 files changed
+83 -25

No files matched your search

@@ -24,6 +24,7 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.Divider import androidx.compose.material3.Divider
@@ -219,27 +220,25 @@ fun ApplicationLogsScreen(
}, },
actions = { actions = {
IconButton(onClick = { IconButton(onClick = {
if (!logLines.isEmpty()) { coroutineScope.launch {
coroutineScope.launch { val data = logViewModel.getLogData()
val data = logViewModel.getLogData()
val sendIntent = Intent(Intent.ACTION_SEND).apply { val sendIntent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_TEXT, data) putExtra(Intent.EXTRA_TEXT, data)
type = "text/plain" type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
context.startActivity(shareIntent)
} }
val shareIntent = Intent.createChooser(sendIntent, null)
context.startActivity(shareIntent)
} }
}) { }, enabled = !logLines.isEmpty()) {
Icon( Icon(
Icons.Filled.Share, Icons.Filled.Share,
contentDescription = stringResource(R.string.application_logs_share) contentDescription = stringResource(R.string.application_logs_share)
) )
} }
IconButton(onClick = { showMoreOptions = !showMoreOptions }) { IconButton(onClick = { showMoreOptions = !showMoreOptions },) {
Icon( Icon(
Icons.Filled.MoreVert, Icons.Filled.MoreVert,
contentDescription = stringResource(R.string.application_logs_more) contentDescription = stringResource(R.string.application_logs_more)
@@ -253,32 +252,54 @@ fun ApplicationLogsScreen(
DropdownMenuItem( DropdownMenuItem(
leadingIcon = { leadingIcon = {
Icon( Icon(
painterResource(R.drawable.icon_save), painterResource(R.drawable.icon_filter_list),
contentDescription = stringResource(R.string.application_logs_export) contentDescription = null,
) )
}, },
text = { trailingIcon = {
Text(stringResource(R.string.application_logs_export)) if (logViewModel.filterCrashes) {
}, onClick = { Icon(
if (!logLines.isEmpty()) { Icons.Filled.Check,
saveLauncher.launch(context.getString(R.string.application_logs_default_filename)) contentDescription = stringResource(R.string.application_logs_crash_only_enabled_alt)
)
} }
},
text = {
Text(stringResource(R.string.application_logs_crash_only))
}, onClick = {
logViewModel.toggleCrashBuffer()
showMoreOptions = false showMoreOptions = false
} }
) )
DropdownMenuItem(
leadingIcon = {
Icon(
painterResource(R.drawable.icon_save),
contentDescription = null,
)
},
text = {
Text(stringResource(R.string.application_logs_export))
},
onClick = {
saveLauncher.launch(context.getString(R.string.application_logs_default_filename))
showMoreOptions = false
},
enabled = !logLines.isEmpty()
)
DropdownMenuItem( DropdownMenuItem(
leadingIcon = { leadingIcon = {
Icon( Icon(
painterResource(R.drawable.icon_delete), painterResource(R.drawable.icon_delete),
contentDescription = stringResource(R.string.application_logs_delete) contentDescription = null
) )
}, },
text = { text = {
Text(stringResource(R.string.application_logs_delete)) Text(stringResource(R.string.application_logs_delete))
}, onClick = { }, onClick = {
logViewModel.clearLogs() logViewModel.clearLogs()
onBackPressedDispatcher?.onBackPressed()
showMoreOptions = false showMoreOptions = false
} }
) )
@@ -4,6 +4,7 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@@ -29,11 +30,26 @@ class LogViewModel: ViewModel() {
private var _isLoading = MutableStateFlow(false) private var _isLoading = MutableStateFlow(false)
var isLoading = _isLoading.asStateFlow() var isLoading = _isLoading.asStateFlow()
var logJob: Job? = null
var filterCrashes = false
private set
fun toggleCrashBuffer() {
filterCrashes = !filterCrashes
_lineState.clear()
loadLogs()
}
private suspend fun logOutput(): List<LogLine> { private suspend fun logOutput(): List<LogLine> {
val logLines = LinkedList<LogLine>() val logLines = LinkedList<LogLine>()
val logCommand = if (filterCrashes) "logcat -b crash -B -d"
else "logcat -B -d"
// -B = binary format, -d = dump logs // -B = binary format, -d = dump logs
val logSource = Runtime.getRuntime().exec("logcat -B -d") val logSource = Runtime.getRuntime().exec(logCommand)
.inputStream.source().buffer() .inputStream.source().buffer()
try { try {
@@ -61,6 +77,8 @@ class LogViewModel: ViewModel() {
} }
fun clearLogs() { fun clearLogs() {
logJob?.cancel()
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
// -c = clear // -c = clear
Runtime.getRuntime().exec("logcat -c") Runtime.getRuntime().exec("logcat -c")
@@ -74,13 +92,20 @@ class LogViewModel: ViewModel() {
return _lineState.joinToString("\n") { it.asSimpleString } return _lineState.joinToString("\n") { it.asSimpleString }
} }
init { private fun loadLogs() {
_isLoading.value = true _isLoading.value = true
viewModelScope.launch(Dispatchers.IO) { logJob?.cancel()
logJob = viewModelScope.launch(Dispatchers.IO) {
val lines = logOutput() val lines = logOutput()
_lineState.addAll(lines) _lineState.addAll(lines)
_isLoading.value = false _isLoading.value = false
logJob = null
} }
} }
init {
loadLogs()
}
} }
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M400,720L400,640L560,640L560,720L400,720ZM240,520L240,440L720,440L720,520L240,520ZM120,320L120,240L840,240L840,320L120,320Z"/>
</vector>
+2
View File
@@ -94,4 +94,6 @@
<string name="application_logs_export">Save To</string> <string name="application_logs_export">Save To</string>
<string name="application_logs_export_completed">Log export complete.</string> <string name="application_logs_export_completed">Log export complete.</string>
<string name="application_logs_default_filename" translatable="false">launcher_logcat.txt</string> <string name="application_logs_default_filename" translatable="false">launcher_logcat.txt</string>
<string name="application_logs_crash_only">Show Crash Buffer</string>
<string name="application_logs_crash_only_enabled_alt">Enabled</string>
</resources> </resources>