From 924bcb0d647b1664de83427a669f721bf5594d86 Mon Sep 17 00:00:00 2001
From: Dominik Korsa
Date: Sun, 14 Jun 2020 00:50:09 +0200
Subject: [PATCH] Message sharing and printing (#866)
---
app/src/main/assets/message-print-page.html | 94 +++++++++++++++++++
app/src/main/assets/wulkanowy-logo-black.svg | 74 +++++++++++++++
.../message/preview/MessagePreviewAdapter.kt | 2 +-
.../message/preview/MessagePreviewFragment.kt | 61 ++++++++++++
.../preview/MessagePreviewPresenter.kt | 65 ++++++++++++-
.../message/preview/MessagePreviewView.kt | 11 +++
.../wulkanowy/utils/ContextExtension.kt | 13 +++
.../res/drawable/ic_menu_message_print.xml | 13 +++
.../res/drawable/ic_menu_message_share.xml | 10 ++
.../res/menu/action_menu_message_preview.xml | 14 +++
app/src/main/res/values-pl/strings.xml | 2 +
app/src/main/res/values/strings.xml | 2 +
12 files changed, 359 insertions(+), 2 deletions(-)
create mode 100644 app/src/main/assets/message-print-page.html
create mode 100644 app/src/main/assets/wulkanowy-logo-black.svg
create mode 100644 app/src/main/res/drawable/ic_menu_message_print.xml
create mode 100644 app/src/main/res/drawable/ic_menu_message_share.xml
diff --git a/app/src/main/assets/message-print-page.html b/app/src/main/assets/message-print-page.html
new file mode 100644
index 00000000..8da7dec6
--- /dev/null
+++ b/app/src/main/assets/message-print-page.html
@@ -0,0 +1,94 @@
+
+
+
+
+ %SUBJECT% | Wulkanowy
+
+
+
+%SUBJECT%
+
+
+ %INFO%
+
+
+
+
+
Treść wiadomości
+ %CONTENT%
+
+
+
diff --git a/app/src/main/assets/wulkanowy-logo-black.svg b/app/src/main/assets/wulkanowy-logo-black.svg
new file mode 100644
index 00000000..9bfbe2c0
--- /dev/null
+++ b/app/src/main/assets/wulkanowy-logo-black.svg
@@ -0,0 +1,74 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt
index 436dee53..a94d2cfc 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewAdapter.kt
@@ -63,7 +63,7 @@ class MessagePreviewAdapter @Inject constructor() :
@SuppressLint("SetTextI18n")
private fun bindMessage(holder: MessageViewHolder, message: Message) {
with(holder.binding) {
- messagePreviewSubject.text = if (message.subject.isNotBlank()) message.subject else root.context.getString(R.string.message_no_subject)
+ messagePreviewSubject.text = message.subject.ifBlank { root.context.getString(R.string.message_no_subject) }
messagePreviewDate.text = root.context.getString(R.string.message_date, message.date.toFormattedString("yyyy-MM-dd HH:mm:ss"))
messagePreviewContent.text = message.content
messagePreviewAuthor.text = if (message.folderId == MessageFolder.SENT.id) "${root.context.getString(R.string.message_to)} ${message.recipient}"
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
index 99eede15..575db75b 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewFragment.kt
@@ -1,12 +1,20 @@
package io.github.wulkanowy.ui.modules.message.preview
+import android.os.Build
import android.os.Bundle
+import android.print.PrintAttributes
+import android.print.PrintManager
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
+import android.webkit.WebResourceRequest
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.annotation.RequiresApi
+import androidx.core.content.getSystemService
import androidx.recyclerview.widget.LinearLayoutManager
import io.github.wulkanowy.R
import io.github.wulkanowy.data.db.entities.Message
@@ -17,6 +25,8 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
+import io.github.wulkanowy.utils.AppInfo
+import io.github.wulkanowy.utils.shareText
import javax.inject.Inject
class MessagePreviewFragment :
@@ -29,18 +39,31 @@ class MessagePreviewFragment :
@Inject
lateinit var previewAdapter: MessagePreviewAdapter
+ @Inject
+ lateinit var appInfo: AppInfo
+
private var menuReplyButton: MenuItem? = null
private var menuForwardButton: MenuItem? = null
private var menuDeleteButton: MenuItem? = null
+ private var menuShareButton: MenuItem? = null
+
+ private var menuPrintButton: MenuItem? = null
+
override val titleStringId: Int
get() = R.string.message_title
override val deleteMessageSuccessString: String
get() = getString(R.string.message_delete_success)
+ override val messageNoSubjectString: String
+ get() = getString(R.string.message_no_subject)
+
+ override val printHTML: String
+ get() = requireContext().assets.open("message-print-page.html").bufferedReader().use { it.readText() }
+
companion object {
const val MESSAGE_ID_KEY = "message_id"
@@ -77,6 +100,8 @@ class MessagePreviewFragment :
menuReplyButton = menu.findItem(R.id.messagePreviewMenuReply)
menuForwardButton = menu.findItem(R.id.messagePreviewMenuForward)
menuDeleteButton = menu.findItem(R.id.messagePreviewMenuDelete)
+ menuShareButton = menu.findItem(R.id.messagePreviewMenuShare)
+ menuPrintButton = menu.findItem(R.id.messagePreviewMenuPrint)
presenter.onCreateOptionsMenu()
}
@@ -85,6 +110,8 @@ class MessagePreviewFragment :
R.id.messagePreviewMenuReply -> presenter.onReply()
R.id.messagePreviewMenuForward -> presenter.onForward()
R.id.messagePreviewMenuDelete -> presenter.onMessageDelete()
+ R.id.messagePreviewMenuShare -> presenter.onShare()
+ R.id.messagePreviewMenuPrint -> presenter.onPrint()
else -> false
}
}
@@ -108,6 +135,8 @@ class MessagePreviewFragment :
menuReplyButton?.isVisible = show
menuForwardButton?.isVisible = show
menuDeleteButton?.isVisible = show
+ menuShareButton?.isVisible = show
+ menuPrintButton?.isVisible = show && appInfo.systemVersion >= Build.VERSION_CODES.LOLLIPOP
}
override fun setDeletedOptionsLabels() {
@@ -138,6 +167,38 @@ class MessagePreviewFragment :
context?.let { it.startActivity(SendMessageActivity.getStartIntent(it, message)) }
}
+ override fun shareText(text: String, subject: String) {
+ context?.shareText(text, subject)
+ }
+
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ override fun printDocument(html: String, jobName: String) {
+ val webView = WebView(activity)
+ webView.webViewClient = object : WebViewClient() {
+
+ override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest) = false
+
+ override fun onPageFinished(view: WebView, url: String) {
+ createWebPrintJob(view, jobName)
+ }
+ }
+
+ webView.loadDataWithBaseURL("file:///android_asset/", html, "text/HTML", "UTF-8", null)
+ }
+
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ private fun createWebPrintJob(webView: WebView, jobName: String) {
+ activity?.getSystemService()?.let { printManager ->
+ val printAdapter = webView.createPrintDocumentAdapter(jobName)
+
+ printManager.print(
+ jobName,
+ printAdapter,
+ PrintAttributes.Builder().build()
+ )
+ }
+ }
+
override fun popView() {
(activity as MainActivity).popView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
index 24678c70..db7996bc 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewPresenter.kt
@@ -1,12 +1,17 @@
package io.github.wulkanowy.ui.modules.message.preview
+import android.annotation.SuppressLint
+import android.os.Build
import io.github.wulkanowy.data.db.entities.Message
+import io.github.wulkanowy.data.db.entities.MessageAttachment
import io.github.wulkanowy.data.repositories.message.MessageRepository
import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler
+import io.github.wulkanowy.utils.AppInfo
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
import io.github.wulkanowy.utils.SchedulersProvider
+import io.github.wulkanowy.utils.toFormattedString
import timber.log.Timber
import javax.inject.Inject
@@ -15,11 +20,14 @@ class MessagePreviewPresenter @Inject constructor(
errorHandler: ErrorHandler,
studentRepository: StudentRepository,
private val messageRepository: MessageRepository,
- private val analytics: FirebaseAnalyticsHelper
+ private val analytics: FirebaseAnalyticsHelper,
+ private var appInfo: AppInfo
) : BasePresenter(errorHandler, studentRepository, schedulers) {
var message: Message? = null
+ var attachments: List? = null
+
private lateinit var lastError: Throwable
private var retryCallback: () -> Unit = {}
@@ -56,6 +64,7 @@ class MessagePreviewPresenter @Inject constructor(
.subscribe({ message ->
Timber.i("Loading message ${message.message.messageId} preview result: Success ")
this@MessagePreviewPresenter.message = message.message
+ this@MessagePreviewPresenter.attachments = message.attachments
view?.apply {
setMessageWithAttachment(message)
initOptions()
@@ -87,6 +96,60 @@ class MessagePreviewPresenter @Inject constructor(
} else false
}
+ fun onShare(): Boolean {
+ message?.let {
+ var text = "Temat: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}\n" + when (it.sender.isNotEmpty()) {
+ true -> "Od: ${it.sender}\n"
+ false -> "Do: ${it.recipient}\n"
+ } + "Data: ${it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")}\n\n${it.content}"
+
+ attachments?.let { attachments ->
+ if (attachments.isNotEmpty()) {
+ text += "\n\nZałączniki:"
+
+ attachments.forEach { attachment ->
+ text += "\n${attachment.filename}: ${attachment.url}"
+ }
+ }
+ }
+
+ view?.shareText(text, "FW: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }}")
+ return true
+ }
+ return false
+ }
+
+ @SuppressLint("NewApi")
+ fun onPrint(): Boolean {
+ if (appInfo.systemVersion < Build.VERSION_CODES.LOLLIPOP) return false
+ message?.let {
+ val dateString = it.date.toFormattedString("yyyy-MM-dd HH:mm:ss")
+ val infoContent = "Data wysłania
$dateString" + when {
+ it.sender.isNotEmpty() -> "Od
${it.sender}"
+ else -> "Do
${it.recipient}"
+ }
+
+ val messageContent = "${it.content}
"
+ .replace(Regex("[\\n\\r]{2,}"), "")
+ .replace(Regex("[\\n\\r]"), "
")
+
+ val jobName = "Wiadomość " + when {
+ it.sender.isNotEmpty() -> "od ${it.sender}"
+ else -> "do ${it.recipient}"
+ } + " $dateString: ${it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() }} | Wulkanowy"
+
+ view?.apply {
+ val html = printHTML
+ .replace("%SUBJECT%", it.subject.ifBlank { view?.messageNoSubjectString.orEmpty() })
+ .replace("%CONTENT%", messageContent)
+ .replace("%INFO%", infoContent)
+ printDocument(html, jobName)
+ }
+ return true
+ }
+ return false
+ }
+
private fun deleteMessage() {
message?.let { message ->
disposable.add(studentRepository.getCurrentStudent()
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
index 3d620459..0fdb4bda 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/message/preview/MessagePreviewView.kt
@@ -1,5 +1,7 @@
package io.github.wulkanowy.ui.modules.message.preview
+import android.os.Build
+import androidx.annotation.RequiresApi
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
import io.github.wulkanowy.ui.base.BaseView
@@ -8,6 +10,10 @@ interface MessagePreviewView : BaseView {
val deleteMessageSuccessString: String
+ val messageNoSubjectString: String
+
+ val printHTML: String
+
fun initView()
fun setMessageWithAttachment(item: MessageWithAttachment)
@@ -34,5 +40,10 @@ interface MessagePreviewView : BaseView {
fun openMessageForward(message: Message?)
+ fun shareText(text: String, subject: String)
+
+ @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
+ fun printDocument(html: String, jobName: String)
+
fun popView()
}
diff --git a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt
index 2b40cb47..cf715e65 100644
--- a/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt
+++ b/app/src/main/java/io/github/wulkanowy/utils/ContextExtension.kt
@@ -71,4 +71,17 @@ fun Context.openDialer(phone: String) {
startActivity(intent)
}
+fun Context.shareText(text: String, subject: String?) {
+ val sendIntent: Intent = Intent().apply {
+ action = Intent.ACTION_SEND
+ putExtra(Intent.EXTRA_TEXT, text)
+ if (subject != null) {
+ putExtra(Intent.EXTRA_SUBJECT, subject)
+ }
+ type = "text/plain"
+ }
+ val shareIntent = Intent.createChooser(sendIntent, null)
+ startActivity(shareIntent)
+}
+
fun Context.dpToPx(dp: Float) = dp * resources.displayMetrics.densityDpi / DENSITY_DEFAULT
diff --git a/app/src/main/res/drawable/ic_menu_message_print.xml b/app/src/main/res/drawable/ic_menu_message_print.xml
new file mode 100644
index 00000000..204b0f6e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_message_print.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_menu_message_share.xml b/app/src/main/res/drawable/ic_menu_message_share.xml
new file mode 100644
index 00000000..67a8ee49
--- /dev/null
+++ b/app/src/main/res/drawable/ic_menu_message_share.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/menu/action_menu_message_preview.xml b/app/src/main/res/menu/action_menu_message_preview.xml
index dfc12e23..4c1332e1 100644
--- a/app/src/main/res/menu/action_menu_message_preview.xml
+++ b/app/src/main/res/menu/action_menu_message_preview.xml
@@ -22,4 +22,18 @@
android:title="@string/message_delete"
app:iconTint="@color/material_on_surface_emphasis_medium"
app:showAsAction="ifRoom" />
+
+
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 2bba1640..a8eccabf 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -204,6 +204,8 @@
Przenieś do kosza
Usuń trwale
Wiadomość usunięta pomyślnie
+ Udostępnij
+ Drukuj
Temat
Treść
Wiadomość wysłana pomyślnie
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3efb53cb..1eaebf28 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -210,6 +210,8 @@
Move to trash
Delete permanently
Message deleted successfully
+ Share
+ Print
Subject
Content
Message sent successfully