Skip to content

Commit 52f6ac3

Browse files
FernandoFernando
authored andcommitted
Updated :: Logging Module - UI Font & Sharable Logs
1 parent f5d10f1 commit 52f6ac3

1 file changed

Lines changed: 123 additions & 8 deletions

File tree

debugMenu/src/main/java/com/tapadoo/debugmenu/logs/LoggingModule.kt

Lines changed: 123 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
11
package com.tapadoo.debugmenu.logs
22

3+
import android.content.Context
4+
import android.content.Intent
35
import androidx.compose.foundation.ExperimentalFoundationApi
46
import androidx.compose.foundation.background
57
import androidx.compose.foundation.basicMarquee
8+
import androidx.compose.foundation.combinedClickable
69
import androidx.compose.foundation.layout.*
710
import androidx.compose.foundation.lazy.LazyColumn
811
import androidx.compose.foundation.lazy.items
912
import androidx.compose.foundation.shape.RoundedCornerShape
1013
import androidx.compose.material.icons.Icons
1114
import androidx.compose.material.icons.automirrored.filled.List
15+
import androidx.compose.material.icons.filled.Share
1216
import androidx.compose.material.icons.outlined.Delete
17+
import androidx.compose.material.icons.outlined.Clear
1318
import androidx.compose.material3.Icon
1419
import androidx.compose.material3.IconButton
1520
import androidx.compose.material3.MaterialTheme
1621
import androidx.compose.material3.Text
1722
import androidx.compose.runtime.*
23+
import androidx.compose.ui.Alignment
1824
import androidx.compose.ui.Modifier
1925
import androidx.compose.ui.draw.clip
26+
import androidx.compose.ui.platform.LocalContext
2027
import androidx.compose.ui.text.font.FontFamily
28+
import androidx.compose.ui.text.style.TextOverflow
2129
import androidx.compose.ui.unit.dp
30+
import androidx.compose.ui.unit.sp
2231
import com.tapadoo.debugmenu.module.DebugMenuModule
2332

2433
class LoggingModule: DebugMenuModule {
@@ -28,6 +37,9 @@ class LoggingModule: DebugMenuModule {
2837
@Composable
2938
override fun Content() {
3039
var invertSort by remember { mutableStateOf(false) }
40+
var selectedLogs by remember { mutableStateOf(setOf<LogItem>()) }
41+
var expandedLogs by remember { mutableStateOf(setOf<LogItem>()) }
42+
val context = LocalContext.current
3143

3244
val logs by remember {
3345
derivedStateOf {
@@ -52,27 +64,85 @@ class LoggingModule: DebugMenuModule {
5264
.background(MaterialTheme.colorScheme.surface)
5365
.padding(4.dp)
5466
.fillMaxWidth(),
55-
horizontalArrangement = Arrangement.End
67+
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End)
5668
) {
69+
if (selectedLogs.isNotEmpty()) {
70+
IconButton({ shareSelectedLogs(context, selectedLogs.toList()) }) {
71+
Row(
72+
horizontalArrangement = Arrangement.spacedBy(6.dp),
73+
modifier = Modifier.padding(horizontal = 8.dp)
74+
) {
75+
Icon(
76+
Icons.Filled.Share,
77+
contentDescription = "Share"
78+
)
79+
Text(
80+
text = "${selectedLogs.size}",
81+
style = MaterialTheme.typography.labelLarge
82+
)
83+
}
84+
}
85+
86+
IconButton({ selectedLogs = setOf() }) {
87+
Icon(
88+
Icons.Outlined.Clear,
89+
contentDescription = "Deselect All"
90+
)
91+
}
92+
}
5793
IconButton({ DebugLogs.clear() }) {
5894
Icon(
59-
Icons.Outlined.Delete, null
95+
Icons.Outlined.Delete,
96+
contentDescription = "Clear All"
6097
)
6198
}
6299
IconButton({ invertSort = !invertSort }) {
63100
Icon(
64-
Icons.AutoMirrored.Filled.List, null
101+
Icons.AutoMirrored.Filled.List,
102+
contentDescription = "Toggle Sort"
65103
)
66104
}
67105
}
68106
}
69107
items(logs) { item ->
108+
val isExpanded = expandedLogs.contains(item)
109+
val isSelected = selectedLogs.contains(item)
110+
70111
Column(
71112
modifier = Modifier
72113
.padding(horizontal = 12.dp)
73114
.fillMaxWidth()
74115
.clip(RoundedCornerShape(8.dp))
75-
.background(MaterialTheme.colorScheme.surfaceContainerLowest)
116+
.background(
117+
if (isSelected) MaterialTheme.colorScheme.primaryContainer
118+
else MaterialTheme.colorScheme.surfaceContainerLowest
119+
)
120+
.combinedClickable(
121+
onClick = {
122+
if (selectedLogs.isNotEmpty()) {
123+
// If in selection mode, toggle selection on click
124+
selectedLogs = if (isSelected) {
125+
selectedLogs - item
126+
} else {
127+
selectedLogs + item
128+
}
129+
} else {
130+
// Otherwise toggle expansion
131+
expandedLogs = if (isExpanded) {
132+
expandedLogs - item
133+
} else {
134+
expandedLogs + item
135+
}
136+
}
137+
},
138+
onLongClick = {
139+
selectedLogs = if (isSelected) {
140+
selectedLogs - item
141+
} else {
142+
selectedLogs + item
143+
}
144+
}
145+
)
76146
.padding(12.dp)
77147
) {
78148
Row {
@@ -81,26 +151,42 @@ class LoggingModule: DebugMenuModule {
81151
text = "[${item.tag}] ",
82152
maxLines = 1,
83153
modifier = Modifier.basicMarquee(),
84-
style = MaterialTheme.typography.titleMedium.copy(fontFamily = FontFamily.Monospace),
154+
style = MaterialTheme.typography.titleSmall.copy(
155+
fontFamily = FontFamily.Monospace,
156+
fontSize = 11.sp
157+
),
85158
color = MaterialTheme.colorScheme.primary
86159
)
87160
}
88161
Text(
89162
text = getPriorityLabel(item.priority),
90163
maxLines = 1,
91-
style = MaterialTheme.typography.titleMedium.copy(fontFamily = FontFamily.Monospace),
164+
style = MaterialTheme.typography.titleSmall.copy(
165+
fontFamily = FontFamily.Monospace,
166+
fontSize = 11.sp
167+
),
92168
color = getPriorityColor(item.priority)
93169
)
94170
}
95171
Text(
96172
text = item.message,
97-
style = MaterialTheme.typography.bodyMedium.copy(fontFamily = FontFamily.Monospace),
173+
maxLines = if (isExpanded) Int.MAX_VALUE else 3,
174+
overflow = TextOverflow.Ellipsis,
175+
style = MaterialTheme.typography.bodySmall.copy(
176+
fontFamily = FontFamily.Monospace,
177+
fontSize = 10.sp
178+
),
98179
color = MaterialTheme.colorScheme.onSurface
99180
)
100181
if (item.throwable != null) {
101182
Text(
102183
text = item.throwable.stackTraceToString(),
103-
style = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace),
184+
maxLines = if (isExpanded) Int.MAX_VALUE else 5,
185+
overflow = TextOverflow.Ellipsis,
186+
style = MaterialTheme.typography.bodySmall.copy(
187+
fontFamily = FontFamily.Monospace,
188+
fontSize = 9.sp
189+
),
104190
color = MaterialTheme.colorScheme.error
105191
)
106192
}
@@ -129,4 +215,33 @@ class LoggingModule: DebugMenuModule {
129215
7 -> "ASSERT"
130216
else -> "UNKNOWN"
131217
}
218+
219+
private fun shareSelectedLogs(context: Context, selectedLogs: List<LogItem>) {
220+
if (selectedLogs.isEmpty()) return
221+
222+
val logsText = selectedLogs.joinToString("\n\n") { logItem ->
223+
buildString {
224+
append("[${getPriorityLabel(logItem.priority)}]")
225+
if (logItem.tag != null) {
226+
append(" [${logItem.tag}]")
227+
}
228+
append("\n")
229+
append(logItem.message)
230+
if (logItem.throwable != null) {
231+
append("\n")
232+
append(logItem.throwable.stackTraceToString())
233+
}
234+
append("\nTimestamp: ${logItem.timestampMs}")
235+
}
236+
}
237+
238+
val shareIntent = Intent().apply {
239+
action = Intent.ACTION_SEND
240+
type = "text/plain"
241+
putExtra(Intent.EXTRA_TEXT, logsText)
242+
putExtra(Intent.EXTRA_SUBJECT, "Debug Logs (${selectedLogs.size} items)")
243+
}
244+
245+
context.startActivity(Intent.createChooser(shareIntent, "Share Logs"))
246+
}
132247
}

0 commit comments

Comments
 (0)