diff --git a/app/src/main/java/se/ajpanton/notificationlog/export/LogExporter.kt b/app/src/main/java/se/ajpanton/notificationlog/export/LogExporter.kt new file mode 100644 index 0000000..30e65b2 --- /dev/null +++ b/app/src/main/java/se/ajpanton/notificationlog/export/LogExporter.kt @@ -0,0 +1,43 @@ +package se.ajpanton.notificationlog.export + +import se.ajpanton.notificationlog.model.NotificationLogEntry +import se.ajpanton.notificationlog.settings.LogField +import se.ajpanton.notificationlog.settings.LogViewSettings +import se.ajpanton.notificationlog.settings.TimestampZone +import java.text.DateFormat +import java.util.Date +import java.util.TimeZone + +object LogExporter { + fun csv(entries: List, settings: LogViewSettings): String = + rows(entries, settings).joinToString("\n") { row -> row.joinToString(",") { csvValue(it) } } + + fun formatted(entries: List, settings: LogViewSettings): String { + val rows = rows(entries, settings) + val widths = rows.fold(emptyList()) { current, row -> row.mapIndexed { i, value -> maxOf(current.getOrElse(i) { 0 }, value.length) } } + return rows.joinToString("\n") { row -> row.mapIndexed { i, value -> value.padEnd(widths[i]) }.joinToString(" ") } + } + + fun html(entries: List, settings: LogViewSettings): String = buildString { + append("") + settings.order.filter { it in settings.visibleFields }.forEach { append("") } + append("") + rows(entries, settings).forEach { row -> append(""); row.forEach { append("") }; append("") } + append("
${escape(header(it))}
${escape(it)}
") + } + + private fun rows(entries: List, settings: LogViewSettings) = listOf( + settings.order.filter { it in settings.visibleFields }.map(::header), + ) + entries.sortedByDescending { it.recordedAtEpochMillis }.map { entry -> + settings.order.filter { it in settings.visibleFields }.map { field -> when (field) { + LogField.TIMESTAMP -> timestamp(entry.recordedAtEpochMillis, settings.timestampZone) + LogField.APP_NAME -> entry.appName; LogField.PACKAGE_NAME -> entry.packageName + LogField.ACTION -> entry.action.name.lowercase().replace('_', ' ') + LogField.CONTENTS -> entry.contents ?: "" + } } + } + private fun header(field: LogField) = field.name.lowercase().replace('_', ' ') + private fun timestamp(value: Long, zone: TimestampZone): String = DateFormat.getDateTimeInstance().apply { if (zone == TimestampZone.UTC) timeZone = TimeZone.getTimeZone("UTC") }.format(Date(value)) + private fun csvValue(value: String) = "\"${value.replace("\"", "\"\"")}\"" + private fun escape(value: String) = value.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """) +}