Merge pull request #6647 from thundernest/message_details_folder_name

Display folder name in message details screen
This commit is contained in:
cketti 2023-02-10 10:55:25 +01:00 committed by GitHub
commit ae374bd5f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 122 additions and 4 deletions

View file

@ -0,0 +1,34 @@
package com.fsck.k9.ui.messagedetails
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.DrawableRes
import com.fsck.k9.ui.R
import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.items.AbstractItem
internal class FolderNameItem(
val displayName: String,
@DrawableRes val iconResourceId: Int
) : AbstractItem<FolderNameItem.ViewHolder>() {
override val type: Int = R.id.message_details_folder_name
override val layoutRes = R.layout.message_details_folder_name_item
override fun getViewHolder(v: View) = ViewHolder(v)
class ViewHolder(view: View) : FastAdapter.ViewHolder<FolderNameItem>(view) {
private val folderIcon: ImageView = view.findViewById(R.id.folder_icon)
private val folderName = view.findViewById<TextView>(R.id.folder_name)
override fun bindView(item: FolderNameItem, payloads: List<Any>) {
folderName.text = item.displayName
folderIcon.setImageResource(item.iconResourceId)
}
override fun unbindView(item: FolderNameItem) {
folderName.text = null
folderIcon.setImageDrawable(null)
}
}
}

View file

@ -8,11 +8,13 @@ val messageDetailsUiModule = module {
MessageDetailsViewModel(
resources = get(),
messageRepository = get(),
folderRepository = get(),
contactSettingsProvider = get(),
contacts = get(),
clipboardManager = get(),
accountManager = get(),
participantFormatter = get()
participantFormatter = get(),
folderNameFormatter = get()
)
}
factory { ContactSettingsProvider() }

View file

@ -24,6 +24,7 @@ import com.fsck.k9.controller.MessageReference
import com.fsck.k9.mail.Address
import com.fsck.k9.mailstore.CryptoResultAnnotation
import com.fsck.k9.ui.R
import com.fsck.k9.ui.folders.FolderIconProvider
import com.fsck.k9.ui.observe
import com.fsck.k9.ui.withArguments
import com.mikepenz.fastadapter.FastAdapter
@ -32,12 +33,14 @@ import com.mikepenz.fastadapter.adapters.ItemAdapter
import com.mikepenz.fastadapter.listeners.ClickEventHook
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
class MessageDetailsFragment : ToolbarBottomSheetDialogFragment() {
private val viewModel: MessageDetailsViewModel by viewModel()
private val addToContactsLauncher: AddToContactsLauncher by inject()
private val showContactLauncher: ShowContactLauncher by inject()
private val contactPictureLoader: ContactPictureLoader by inject()
private val folderIconProvider: FolderIconProvider by inject { parametersOf(requireContext().theme) }
private lateinit var messageReference: MessageReference
@ -138,6 +141,10 @@ class MessageDetailsFragment : ToolbarBottomSheetDialogFragment() {
addParticipants(details.to, R.string.message_details_to_section_title, showContactPicture)
addParticipants(details.cc, R.string.message_details_cc_section_title, showContactPicture)
addParticipants(details.bcc, R.string.message_details_bcc_section_title, showContactPicture)
if (details.folder != null) {
addFolderName(details.folder)
}
}
val adapter = FastAdapter.with(itemAdapter).apply {
@ -166,6 +173,14 @@ class MessageDetailsFragment : ToolbarBottomSheetDialogFragment() {
}
}
private fun ItemAdapter<GenericItem>.addFolderName(folder: FolderInfoUi) {
val folderNameItem = FolderNameItem(
displayName = folder.displayName,
iconResourceId = folderIconProvider.getFolderIcon(folder.type)
)
add(folderNameItem)
}
private val cryptoStatusClickEventHook = object : ClickEventHook<CryptoStatusItem>() {
override fun onBind(viewHolder: RecyclerView.ViewHolder): View? {
return if (viewHolder is CryptoStatusItem.ViewHolder) {

View file

@ -2,6 +2,7 @@ package com.fsck.k9.ui.messagedetails
import android.net.Uri
import com.fsck.k9.mail.Address
import com.fsck.k9.mailstore.FolderType
import com.fsck.k9.view.MessageCryptoDisplayStatus
data class MessageDetailsUi(
@ -12,7 +13,8 @@ data class MessageDetailsUi(
val replyTo: List<Participant>,
val to: List<Participant>,
val cc: List<Participant>,
val bcc: List<Participant>
val bcc: List<Participant>,
val folder: FolderInfoUi?
)
data class CryptoDetails(
@ -31,3 +33,8 @@ data class Participant(
val address: Address
get() = Address(emailAddress, displayName?.toString())
}
data class FolderInfoUi(
val displayName: String,
val type: FolderType
)

View file

@ -10,10 +10,13 @@ import com.fsck.k9.helper.ClipboardManager
import com.fsck.k9.helper.Contacts
import com.fsck.k9.mail.Address
import com.fsck.k9.mailstore.CryptoResultAnnotation
import com.fsck.k9.mailstore.Folder
import com.fsck.k9.mailstore.FolderRepository
import com.fsck.k9.mailstore.MessageDate
import com.fsck.k9.mailstore.MessageRepository
import com.fsck.k9.preferences.AccountManager
import com.fsck.k9.ui.R
import com.fsck.k9.ui.folders.FolderNameFormatter
import com.fsck.k9.view.MessageCryptoDisplayStatus
import java.text.DateFormat
import java.util.Locale
@ -27,11 +30,13 @@ import kotlinx.coroutines.launch
internal class MessageDetailsViewModel(
private val resources: Resources,
private val messageRepository: MessageRepository,
private val folderRepository: FolderRepository,
private val contactSettingsProvider: ContactSettingsProvider,
private val contacts: Contacts,
private val clipboardManager: ClipboardManager,
private val accountManager: AccountManager,
private val participantFormatter: MessageDetailsParticipantFormatter
private val participantFormatter: MessageDetailsParticipantFormatter,
private val folderNameFormatter: FolderNameFormatter
) : ViewModel() {
private val dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM, Locale.getDefault())
private val uiState = MutableStateFlow<MessageDetailsState>(MessageDetailsState.Loading)
@ -46,6 +51,8 @@ internal class MessageDetailsViewModel(
val account = accountManager.getAccount(messageReference.accountUuid) ?: error("Account not found")
val messageDetails = messageRepository.getMessageDetails(messageReference)
val folder = folderRepository.getFolder(account, folderId = messageReference.folderId)
val senderList = messageDetails.sender?.let { listOf(it) } ?: emptyList()
val messageDetailsUi = MessageDetailsUi(
date = buildDisplayDate(messageDetails.date),
@ -55,7 +62,8 @@ internal class MessageDetailsViewModel(
replyTo = messageDetails.replyTo.toParticipants(account),
to = messageDetails.to.toParticipants(account),
cc = messageDetails.cc.toParticipants(account),
bcc = messageDetails.bcc.toParticipants(account)
bcc = messageDetails.bcc.toParticipants(account),
folder = folder?.toFolderInfo()
)
MessageDetailsState.DataLoaded(
@ -100,6 +108,13 @@ internal class MessageDetailsViewModel(
}
}
private fun Folder.toFolderInfo(): FolderInfoUi {
return FolderInfoUi(
displayName = folderNameFormatter.displayName(this),
type = this.type
)
}
fun onCryptoStatusClicked() {
val cryptoResult = cryptoResult ?: return
val cryptoStatus = MessageCryptoDisplayStatus.fromResultAnnotation(cryptoResult)

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/keyline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="72dp" />
<ImageView
android:id="@+id/folder_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:contentDescription="@null"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/keyline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:srcCompat="@drawable/ic_folder" />
<TextView
android:id="@+id/folder_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:textAppearance="?attr/textAppearanceBody2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/keyline"
app:layout_constraintTop_toTopOf="parent"
tools:text="Regular folder" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -4,5 +4,6 @@
<item type="id" name="message_details_crypto_status"/>
<item type="id" name="message_details_section_header"/>
<item type="id" name="message_details_participant"/>
<item type="id" name="message_details_folder_name"/>
<item type="id" name="message_details_divider"/>
</resources>