Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.fsck.k9.ui.messageview

import android.content.Context
import android.print.PrintAttributes
import android.print.PrintManager
import com.fsck.k9.mail.Address
import com.fsck.k9.mail.Message
import com.fsck.k9.mailstore.MessageViewInfo
import com.fsck.k9.view.MessageWebView
import java.text.SimpleDateFormat
import java.util.Locale

class MessagePrinter(
private val context: Context,
private val appName: String,
private val noSubjectText: String,
) {
fun print(messageViewInfo: MessageViewInfo) {
val printManager = context.getSystemService(Context.PRINT_SERVICE) as? PrintManager ?: return

val subject = messageViewInfo.message.subject ?: noSubjectText
val headerHtml = buildHeaderHtml(messageViewInfo)
val cleanBodyHtml = (messageViewInfo.text ?: "")
.replace(Regex("(?i)<a\\b[^>]*>"), "")
.replace(Regex("(?i)</a>"), "")
val fullHtml = buildFullHtml(headerHtml, cleanBodyHtml)

val printWebView = MessageWebView(context)
printWebView.displayHtmlContentWithInlineAttachments(
htmlText = fullHtml,
attachmentResolver = null,
onPageFinishedListener = {
val jobName = "$appName: $subject"
val printAdapter = printWebView.createPrintDocumentAdapter(jobName)
printManager.print(jobName, printAdapter, PrintAttributes.Builder().build())
},
)
}

private fun buildFullHtml(headerHtml: String, bodyHtml: String): String = """
<html>
<head>
<style>
@page {
margin: 24px;
}
.page-wrapper {
padding: 24px;
font-family: Arial, sans-serif;
color: #000;
}
.page-wrapper > div p {
margin: 4px 0;
}
</style>
</head>
<body>
<div class="page-wrapper">
$headerHtml
$bodyHtml
</div>
</body>
</html>
""".trimIndent()

private fun buildHeaderHtml(messageViewInfo: MessageViewInfo): String {
val message = messageViewInfo.message

val subject = (message.subject ?: noSubjectText)
.replace("<", "&lt;")
.replace(">", "&gt;")

val from = message.from
?.joinToString(", ") { it.toDisplayString() }
?: ""

val to = message.getRecipients(Message.RecipientType.TO)
?.joinToString(", ") { it.toDisplayString() }
?: ""

val date = message.sentDate?.let {
SimpleDateFormat("M/d/yyyy, h:mm a", Locale.getDefault()).format(it)
} ?: ""

return """
<div style="font-size:15px; margin-bottom:16px;">
<p><b>Subject:</b> $subject</p>
<p><b>From:</b> $from</p>
<p><b>Date:</b> $date</p>
<p><b>To:</b> $to</p>
</div>
<hr style="border:none; border-top:1px solid #ccc; margin:12px 0;">
""".trimIndent()
}

private fun Address.toDisplayString(): String {
val name = personal ?: ""
return if (name.isNotBlank() && address.isNotBlank()) {
"$name &lt;$address&gt;"
} else {
address ?: ""
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
import android.os.SystemClock
import android.print.PrintAttributes
import android.print.PrintManager
import android.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.Menu
Expand All @@ -20,7 +18,6 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.webkit.WebView
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.compose.runtime.collectAsState
Expand Down Expand Up @@ -477,20 +474,12 @@ class MessageViewFragment :
}

private fun printMessage() {
val context = context
val webView = view?.findViewById<WebView>(R.id.message_content)
val printManager = context?.getSystemService(Context.PRINT_SERVICE) as? PrintManager
if (context == null || webView == null || printManager == null) return

val subject = mMessageViewInfo?.subject ?: getString(R.string.general_no_subject)
val jobName = appNameProvider.appName + ": " + subject
val printAdapter = webView.createPrintDocumentAdapter(jobName)

printManager.print(
jobName,
printAdapter,
PrintAttributes.Builder().build(),
)
val messageViewInfo = mMessageViewInfo ?: return
MessagePrinter(
context = requireContext(),
appName = appNameProvider.appName,
noSubjectText = getString(R.string.general_no_subject),
).print(messageViewInfo)
}

private fun onShowHeaders() {
Expand Down
Loading