Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit cbf3ef98 authored by cketti's avatar cketti Committed by GitHub
Browse files

Merge pull request #6600 from thundernest/bottom_sheet_contents

Message View Redesign: Add bottom sheet (2)
parents 7dd0ed79 6762b2c4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ dependencies {
    implementation libs.moshi
    implementation libs.timber
    implementation libs.mime4j.core
    implementation libs.mime4j.dom

    testImplementation project(':mail:testing')
    testImplementation project(":backend:imap")
+27 −5
Original line number Diff line number Diff line
package com.fsck.k9.helper;


import java.util.HashMap;

import android.Manifest;
import android.content.ContentResolver;
import android.content.Context;
@@ -9,13 +11,12 @@ import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import timber.log.Timber;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import androidx.core.content.ContextCompat;

import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.fsck.k9.mail.Address;

import java.util.HashMap;
import timber.log.Timber;

/**
 * Helper class to access the contacts stored on the device.
@@ -37,7 +38,8 @@ public class Contacts {
            ContactsContract.CommonDataKinds.Email._ID,
            ContactsContract.Contacts.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Email.CONTACT_ID,
            Photo.PHOTO_URI
            Photo.PHOTO_URI,
            ContactsContract.Contacts.LOOKUP_KEY
    };

    /**
@@ -52,6 +54,8 @@ public class Contacts {
     */
    protected static final int CONTACT_ID_INDEX = 2;

    protected static final int LOOKUP_KEY_INDEX = 4;


    /**
     * Get instance of the Contacts class.
@@ -169,6 +173,24 @@ public class Contacts {
        return false;
    }

    @Nullable
    public Uri getContactUri(String emailAddress) {
        Cursor cursor = getContactByAddress(emailAddress);
        if (cursor == null) {
            return null;
        }

        try (cursor) {
            if (!cursor.moveToFirst()) {
                return null;
            }

            long contactId = cursor.getLong(CONTACT_ID_INDEX);
            String lookupKey = cursor.getString(LOOKUP_KEY_INDEX);
            return ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
        }
    }

    /**
     * Get the name of the contact an email address belongs to.
     *
+22 −0
Original line number Diff line number Diff line
package com.fsck.k9.mailstore

import com.fsck.k9.mail.Address
import java.util.Date

data class MessageDetails(
    val date: MessageDate,
    val from: List<Address>,
    val sender: Address?,
    val replyTo: List<Address>,
    val to: List<Address>,
    val cc: List<Address>,
    val bcc: List<Address>
)

sealed interface MessageDate {
    data class ValidDate(val date: Date) : MessageDate

    data class InvalidDate(val dateHeader: String) : MessageDate

    object MissingDate : MessageDate
}
+58 −0
Original line number Diff line number Diff line
package com.fsck.k9.mailstore

import com.fsck.k9.controller.MessageReference
import com.fsck.k9.mail.Address
import com.fsck.k9.mail.Header
import com.fsck.k9.mail.internet.MimeUtility
import org.apache.james.mime4j.dom.field.DateTimeField
import org.apache.james.mime4j.field.DefaultFieldParser

class MessageRepository(private val messageStoreManager: MessageStoreManager) {
    fun getHeaders(messageReference: MessageReference): List<Header> {
        val messageStore = messageStoreManager.getMessageStore(messageReference.accountUuid)
        return messageStore.getHeaders(messageReference.folderId, messageReference.uid)
    }

    fun getMessageDetails(messageReference: MessageReference): MessageDetails {
        val messageStore = messageStoreManager.getMessageStore(messageReference.accountUuid)
        val headers = messageStore.getHeaders(messageReference.folderId, messageReference.uid, MESSAGE_DETAILS_HEADERS)

        val messageDate = headers.parseDate("date")
        val fromAddresses = headers.parseAddresses("from")
        val senderAddresses = headers.parseAddresses("sender")
        val replyToAddresses = headers.parseAddresses("reply-to")
        val toAddresses = headers.parseAddresses("to")
        val ccAddresses = headers.parseAddresses("cc")
        val bccAddresses = headers.parseAddresses("bcc")

        return MessageDetails(
            date = messageDate,
            from = fromAddresses,
            sender = senderAddresses.firstOrNull(),
            replyTo = replyToAddresses,
            to = toAddresses,
            cc = ccAddresses,
            bcc = bccAddresses
        )
    }

    private fun List<Header>.firstHeaderOrNull(name: String): String? {
        return firstOrNull { it.name.equals(name, ignoreCase = true) }?.value
    }

    private fun List<Header>.parseAddresses(headerName: String): List<Address> {
        return Address.parse(MimeUtility.unfold(firstHeaderOrNull(headerName))).toList()
    }

    private fun List<Header>.parseDate(headerName: String): MessageDate {
        val dateHeader = firstHeaderOrNull(headerName) ?: return MessageDate.MissingDate

        return try {
            val dateTimeField = DefaultFieldParser.parse("Date: $dateHeader") as DateTimeField
            return MessageDate.ValidDate(date = dateTimeField.date)
        } catch (e: Exception) {
            MessageDate.InvalidDate(dateHeader)
        }
    }

    companion object {
        private val MESSAGE_DETAILS_HEADERS = setOf(
            "date",
            "from",
            "sender",
            "reply-to",
            "to",
            "cc",
            "bcc",
        )
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -155,6 +155,11 @@ interface MessageStore {
     */
    fun getHeaders(folderId: Long, messageServerId: String): List<Header>

    /**
     * Retrieve selected header fields of a message.
     */
    fun getHeaders(folderId: Long, messageServerId: String, headerNames: Set<String>): List<Header>

    /**
     * Return the size of this message store in bytes.
     */
Loading