Stream notification log exports
This commit is contained in:
@@ -99,34 +99,80 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
val format = pendingExport ?: return
|
||||
val context = requireContext().applicationContext
|
||||
Thread {
|
||||
val entries = EncryptedNotificationLogStore(context).readAll()
|
||||
val logStore = EncryptedNotificationLogStore(context)
|
||||
val settings = LogViewSettingsStore(context).load()
|
||||
context.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
when (format) {
|
||||
ExportFormat.CSV -> output.write(LogExporter.csv(entries, settings).encodeToByteArray())
|
||||
ExportFormat.FORMATTED -> output.write(LogExporter.formatted(entries, settings).encodeToByteArray())
|
||||
ExportFormat.HTML_ZIP -> ZipOutputStream(output).use { zip ->
|
||||
zip.putNextEntry(java.util.zip.ZipEntry("notification-log.html"))
|
||||
val imageStore = EncryptedImageStore(context)
|
||||
val imageEntries = entries.filter { it.imageId != null && LogField.CONTENTS in settings.visibleFields }
|
||||
val exportedImages = imageEntries.mapNotNull { entry ->
|
||||
imageStore.read(entry.imageId!!)?.let { entry.imageId to it }
|
||||
}.toMap()
|
||||
zip.write(LogExporter.html(entries, settings) { entry ->
|
||||
entry.imageId?.takeIf(exportedImages::containsKey)?.let { "images/$it.png" }
|
||||
}.encodeToByteArray())
|
||||
zip.closeEntry()
|
||||
exportedImages.forEach { (imageId, image) ->
|
||||
zip.putNextEntry(java.util.zip.ZipEntry("images/$imageId.png"))
|
||||
zip.write(image)
|
||||
zip.closeEntry()
|
||||
}
|
||||
}
|
||||
ExportFormat.CSV -> writeCsv(output.bufferedWriter(Charsets.UTF_8), logStore, settings)
|
||||
ExportFormat.FORMATTED -> writeFormatted(output.bufferedWriter(Charsets.UTF_8), logStore, settings)
|
||||
ExportFormat.HTML_ZIP -> writeHtmlZip(ZipOutputStream(output), logStore, settings, context)
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun writeCsv(
|
||||
writer: java.io.BufferedWriter,
|
||||
logStore: EncryptedNotificationLogStore,
|
||||
settings: se.ajpanton.notificationlog.settings.LogViewSettings,
|
||||
) = writer.use {
|
||||
it.write(LogExporter.csvHeader(settings))
|
||||
logStore.forEachNewest { entry ->
|
||||
it.newLine()
|
||||
it.write(LogExporter.csvRow(entry, settings))
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeFormatted(
|
||||
writer: java.io.BufferedWriter,
|
||||
logStore: EncryptedNotificationLogStore,
|
||||
settings: se.ajpanton.notificationlog.settings.LogViewSettings,
|
||||
) = writer.use {
|
||||
val headers = LogExporter.headers(settings)
|
||||
val widths = headers.map { header -> header.length }.toMutableList()
|
||||
logStore.forEachNewest { entry ->
|
||||
LogExporter.values(entry, settings).forEachIndexed { index, value ->
|
||||
widths[index] = maxOf(widths[index], value.length)
|
||||
}
|
||||
}
|
||||
it.write(LogExporter.formattedRow(headers, widths))
|
||||
logStore.forEachNewest { entry ->
|
||||
it.newLine()
|
||||
it.write(LogExporter.formattedRow(LogExporter.values(entry, settings), widths))
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeHtmlZip(
|
||||
zip: ZipOutputStream,
|
||||
logStore: EncryptedNotificationLogStore,
|
||||
settings: se.ajpanton.notificationlog.settings.LogViewSettings,
|
||||
context: android.content.Context,
|
||||
) = zip.use { zipOutput ->
|
||||
val imageStore = EncryptedImageStore(context)
|
||||
zipOutput.putNextEntry(java.util.zip.ZipEntry("notification-log.html"))
|
||||
zipOutput.write(LogExporter.htmlStart(settings).encodeToByteArray())
|
||||
logStore.forEachNewest { entry ->
|
||||
val imagePath = entry.imageId
|
||||
?.takeIf { LogField.CONTENTS in settings.visibleFields && imageStore.exists(it) }
|
||||
?.let { imageId -> "images/$imageId.png" }
|
||||
zipOutput.write(LogExporter.htmlRow(entry, settings, imagePath).encodeToByteArray())
|
||||
}
|
||||
zipOutput.write(LogExporter.htmlEnd().encodeToByteArray())
|
||||
zipOutput.closeEntry()
|
||||
|
||||
if (LogField.CONTENTS in settings.visibleFields) {
|
||||
logStore.forEachNewest { entry ->
|
||||
entry.imageId?.let { imageId ->
|
||||
imageStore.read(imageId)?.let { image ->
|
||||
zipOutput.putNextEntry(java.util.zip.ZipEntry("images/$imageId.png"))
|
||||
zipOutput.write(image)
|
||||
zipOutput.closeEntry()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum class ExportFormat(val extension: String) { CSV("csv"), FORMATTED("txt"), HTML_ZIP("zip") }
|
||||
|
||||
private companion object {
|
||||
|
||||
Reference in New Issue
Block a user