Skip to content

Commit

Permalink
Merge pull request #2299 from element-hq/feature/bma/logViewerImprove…
Browse files Browse the repository at this point in the history
…ment

FileViewer: fix coloration issue for logs files.
  • Loading branch information
bmarty authored Jan 26, 2024
2 parents 80270d1 + 6194f2c commit 0bcd3ba
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ViewFilePresenter @AssistedInject constructor(
@Composable
override fun present(): ViewFileState {
val coroutineScope = rememberCoroutineScope()
val colorationMode = remember { name.toColorationMode() }

fun handleEvent(event: ViewFileEvents) {
when (event) {
Expand All @@ -67,6 +68,7 @@ class ViewFilePresenter @AssistedInject constructor(
return ViewFileState(
name = name,
lines = lines,
colorationMode = colorationMode,
eventSink = ::handleEvent,
)
}
Expand All @@ -79,3 +81,11 @@ class ViewFilePresenter @AssistedInject constructor(
fileSave.save(path)
}
}

private fun String.toColorationMode(): ColorationMode {
return when {
equals("logcat.log") -> ColorationMode.Logcat
startsWith("logs.") -> ColorationMode.RustLogs
else -> ColorationMode.None
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,12 @@ import io.element.android.libraries.architecture.AsyncData
data class ViewFileState(
val name: String,
val lines: AsyncData<List<String>>,
val colorationMode: ColorationMode,
val eventSink: (ViewFileEvents) -> Unit,
)

enum class ColorationMode {
Logcat,
RustLogs,
None,
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ open class ViewFileStateProvider : PreviewParameterProvider<ViewFileState> {
aViewFileState(lines = AsyncData.Failure(Exception("A failure"))),
aViewFileState(lines = AsyncData.Success(emptyList())),
aViewFileState(
name = "logcat.log",
lines = AsyncData.Success(
listOf(
"Line 1",
Expand All @@ -40,16 +41,36 @@ open class ViewFileStateProvider : PreviewParameterProvider<ViewFileState> {
"01-23 13:14:50.740 25818 25818 E error",
"01-23 13:14:50.740 25818 25818 A assertion",
)
)
),
colorationMode = ColorationMode.Logcat,
),
aViewFileState(
name = "logs.2024-01-26",
lines = AsyncData.Success(
listOf(
"Line 1",
"Line 2",
"Line 3 lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" +
" incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,",
"2024-01-26T10:22:26.947416Z TRACE trace",
"2024-01-26T10:22:26.947416Z DEBUG debug",
"2024-01-26T10:22:26.947416Z INFO info",
"2024-01-26T10:22:26.947416Z WARN warn",
"2024-01-26T10:22:26.947416Z ERROR error",
)
),
colorationMode = ColorationMode.RustLogs,
)
)
}

fun aViewFileState(
name: String = "aName",
lines: AsyncData<List<String>> = AsyncData.Uninitialized,
colorationMode: ColorationMode = ColorationMode.None,
) = ViewFileState(
name = name,
lines = lines,
colorationMode = colorationMode,
eventSink = {},
)
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ fun ViewFileView(
is AsyncData.Success -> FileContent(
modifier = Modifier.weight(1f),
lines = state.lines.data.toImmutableList(),
colorationMode = state.colorationMode,
)
is AsyncData.Failure -> AsyncFailure(throwable = state.lines.error, onRetry = null)
}
Expand All @@ -125,6 +126,7 @@ fun ViewFileView(
@Composable
private fun FileContent(
lines: ImmutableList<String>,
colorationMode: ColorationMode,
modifier: Modifier = Modifier,
) {
LazyColumn(
Expand All @@ -147,6 +149,7 @@ private fun FileContent(
LineRow(
lineNumber = index + 1,
line = line,
colorationMode = colorationMode,
)
}
}
Expand All @@ -157,6 +160,7 @@ private fun FileContent(
private fun LineRow(
lineNumber: Int,
line: String,
colorationMode: ColorationMode,
) {
val context = LocalContext.current
Row(
Expand Down Expand Up @@ -195,28 +199,49 @@ private fun LineRow(
}
.padding(horizontal = 4.dp),
text = line,
color = line.toColor(),
color = line.toColor(colorationMode),
style = ElementTheme.typography.fontBodyMdRegular
)
}
}

/**
* Convert a logcat line to a color.
* Ex: `01-23 13:14:50.740 25818 25818 D org.matrix.rust.sdk: elementx: SyncIndicator = Hide | RustRoomListService.kt:81`
* Convert a line to a color.
* Ex for logcat:
* `01-23 13:14:50.740 25818 25818 D org.matrix.rust.sdk: elementx: SyncIndicator = Hide | RustRoomListService.kt:81`
* ^ use this char to determine the color
* Ex for Rust logs:
* `2024-01-26T10:22:26.947416Z WARN elementx: Restore with non-empty map | MatrixClientsHolder.kt:68`
* ^ use this char to determine the color, see [LogLevel]
*/
@Composable
private fun String.toColor(): Color {
return when (getOrNull(31)) {
'D' -> Color(0xFF299999)
'I' -> Color(0xFFABC023)
'W' -> Color(0xFFBBB529)
'E' -> Color(0xFFFF6B68)
'A' -> Color(0xFFFF6B68)
else -> ElementTheme.colors.textPrimary
private fun String.toColor(colorationMode: ColorationMode): Color {
return when (colorationMode) {
ColorationMode.Logcat -> when (getOrNull(31)) {
'D' -> colorDebug
'I' -> colorInfo
'W' -> colorWarning
'E' -> colorError
'A' -> colorError
else -> ElementTheme.colors.textPrimary
}
ColorationMode.RustLogs -> when (getOrNull(32)) {
'E' -> ElementTheme.colors.textPrimary
'G' -> colorDebug
'O' -> colorInfo
'N' -> colorWarning
'R' -> colorError
else -> ElementTheme.colors.textPrimary
}
ColorationMode.None -> ElementTheme.colors.textPrimary
}
}

private val colorDebug = Color(0xFF299999)
private val colorInfo = Color(0xFFABC023)
private val colorWarning = Color(0xFFBBB529)
private val colorError = Color(0xFFFF6B68)

@PreviewsDayNight
@Composable
internal fun ViewFileViewPreview(@PreviewParameter(ViewFileStateProvider::class) state: ViewFileState) = ElementPreview {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.viewfolder.impl.file.ColorationMode
import io.element.android.features.viewfolder.impl.file.FileContentReader
import io.element.android.features.viewfolder.impl.file.FileSave
import io.element.android.features.viewfolder.impl.file.FileShare
Expand Down Expand Up @@ -48,13 +49,38 @@ class ViewFilePresenterTest {
val initialState = awaitItem()
assertThat(initialState.name).isEqualTo("aName")
assertThat(initialState.lines).isInstanceOf(AsyncData.Loading::class.java)
assertThat(initialState.colorationMode).isEqualTo(ColorationMode.None)
val loadedState = awaitItem()
val lines = (loadedState.lines as AsyncData.Success).data
assertThat(lines.size).isEqualTo(1)
assertThat(lines.first()).isEqualTo("aLine")
}
}

@Test
fun `present - coloration mode for logcat`() = runTest {
val presenter = createPresenter(name = "logcat.log")
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.colorationMode).isEqualTo(ColorationMode.Logcat)
cancelAndConsumeRemainingEvents()
}
}

@Test
fun `present - coloration mode for logs`() = runTest {
val presenter = createPresenter(name = "logs.date")
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.colorationMode).isEqualTo(ColorationMode.RustLogs)
cancelAndConsumeRemainingEvents()
}
}

@Test
fun `present - share should not have any side effect`() = runTest {
val fileContentReader = FakeFileContentReader().apply {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0bcd3ba

Please sign in to comment.