Browse Source

Merge pull request #2299 from element-hq/feature/bma/logViewerImprovement

FileViewer: fix coloration issue for logs files.
pull/2284/head
Benoit Marty 8 months ago committed by GitHub
parent
commit
0bcd3ba93a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFilePresenter.kt
  2. 7
      features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileState.kt
  3. 21
      features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileStateProvider.kt
  4. 45
      features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileView.kt
  5. 26
      features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/test/file/ViewFilePresenterTest.kt
  6. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Day-0_1_null_4,NEXUS_5,1.0,en].png
  7. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Day-0_1_null_5,NEXUS_5,1.0,en].png
  8. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Night-0_2_null_4,NEXUS_5,1.0,en].png
  9. BIN
      tests/uitests/src/test/snapshots/images/ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Night-0_2_null_5,NEXUS_5,1.0,en].png

10
features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFilePresenter.kt

@ -49,6 +49,7 @@ class ViewFilePresenter @AssistedInject constructor( @@ -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) {
@ -67,6 +68,7 @@ class ViewFilePresenter @AssistedInject constructor( @@ -67,6 +68,7 @@ class ViewFilePresenter @AssistedInject constructor(
return ViewFileState(
name = name,
lines = lines,
colorationMode = colorationMode,
eventSink = ::handleEvent,
)
}
@ -79,3 +81,11 @@ class ViewFilePresenter @AssistedInject constructor( @@ -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
}
}

7
features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileState.kt

@ -21,5 +21,12 @@ import io.element.android.libraries.architecture.AsyncData @@ -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,
}

21
features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileStateProvider.kt

@ -27,6 +27,7 @@ open class ViewFileStateProvider : PreviewParameterProvider<ViewFileState> { @@ -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",
@ -40,7 +41,25 @@ open class ViewFileStateProvider : PreviewParameterProvider<ViewFileState> { @@ -40,7 +41,25 @@ 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,
)
)
}
@ -48,8 +67,10 @@ open class ViewFileStateProvider : PreviewParameterProvider<ViewFileState> { @@ -48,8 +67,10 @@ open class ViewFileStateProvider : PreviewParameterProvider<ViewFileState> {
fun aViewFileState(
name: String = "aName",
lines: AsyncData<List<String>> = AsyncData.Uninitialized,
colorationMode: ColorationMode = ColorationMode.None,
) = ViewFileState(
name = name,
lines = lines,
colorationMode = colorationMode,
eventSink = {},
)

45
features/viewfolder/impl/src/main/kotlin/io/element/android/features/viewfolder/impl/file/ViewFileView.kt

@ -114,6 +114,7 @@ fun ViewFileView( @@ -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)
}
@ -125,6 +126,7 @@ fun ViewFileView( @@ -125,6 +126,7 @@ fun ViewFileView(
@Composable
private fun FileContent(
lines: ImmutableList<String>,
colorationMode: ColorationMode,
modifier: Modifier = Modifier,
) {
LazyColumn(
@ -147,6 +149,7 @@ private fun FileContent( @@ -147,6 +149,7 @@ private fun FileContent(
LineRow(
lineNumber = index + 1,
line = line,
colorationMode = colorationMode,
)
}
}
@ -157,6 +160,7 @@ private fun FileContent( @@ -157,6 +160,7 @@ private fun FileContent(
private fun LineRow(
lineNumber: Int,
line: String,
colorationMode: ColorationMode,
) {
val context = LocalContext.current
Row(
@ -195,28 +199,49 @@ private fun LineRow( @@ -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)
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 {

26
features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/test/file/ViewFilePresenterTest.kt

@ -20,6 +20,7 @@ import app.cash.molecule.RecompositionMode @@ -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
@ -48,6 +49,7 @@ class ViewFilePresenterTest { @@ -48,6 +49,7 @@ 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)
@ -55,6 +57,30 @@ class ViewFilePresenterTest { @@ -55,6 +57,30 @@ class ViewFilePresenterTest {
}
}
@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 {

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Day-0_1_null_4,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Day-0_1_null_5,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Night-0_2_null_4,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.

BIN
tests/uitests/src/test/snapshots/images/ui_S_t[f.viewfolder.impl.file_ViewFileView_null_ViewFileView-Night-0_2_null_5,NEXUS_5,1.0,en].png (Stored with Git LFS)

Binary file not shown.
Loading…
Cancel
Save