0
0
mirror of https://github.com/thunderbird/thunderbird-android.git synced 2024-09-19 19:52:14 +02:00

Change MessageHelper to Kotlin

This commit is contained in:
Wolf Montwé 2023-03-06 14:42:52 +01:00
parent 0c299aeb7d
commit 9fe1983c1a
No known key found for this signature in database
GPG Key ID: 6D45B21512ACBF72
3 changed files with 138 additions and 135 deletions

View File

@ -1,152 +1,152 @@
package com.fsck.k9.helper;
package com.fsck.k9.helper
import android.content.Context
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import com.fsck.k9.Account
import com.fsck.k9.CoreResourceProvider
import com.fsck.k9.DI
import com.fsck.k9.K9.contactNameColor
import com.fsck.k9.K9.isChangeContactNameColor
import com.fsck.k9.K9.isShowContactName
import com.fsck.k9.K9.isShowCorrespondentNames
import com.fsck.k9.mail.Address
import java.util.regex.Pattern
import java.util.List;
import java.util.regex.Pattern;
class MessageHelper private constructor(
private val mContext: Context,
private val resourceProvider: CoreResourceProvider,
) {
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import com.fsck.k9.Account;
import com.fsck.k9.CoreResourceProvider;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
import com.fsck.k9.mail.Address;
public class MessageHelper {
/**
* If the number of addresses exceeds this value the addresses aren't
* resolved to the names of Android contacts.
*
* <p>
* TODO: This number was chosen arbitrarily and should be determined by
* performance tests.
* </p>
*
* @see #toFriendly(Address[], com.fsck.k9.helper.Contacts)
*/
private static final int TOO_MANY_ADDRESSES = 50;
private static final Pattern SPOOF_ADDRESS_PATTERN = Pattern.compile("[^(]@");
private static MessageHelper sInstance;
public synchronized static MessageHelper getInstance(final Context context) {
if (sInstance == null) {
CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
sInstance = new MessageHelper(context, resourceProvider);
}
return sInstance;
}
private final CoreResourceProvider resourceProvider;
private Context mContext;
private MessageHelper(Context context, CoreResourceProvider resourceProvider) {
mContext = context;
this.resourceProvider = resourceProvider;
}
public CharSequence getSenderDisplayName(Address address) {
fun getSenderDisplayName(address: Address?): CharSequence {
if (address == null) {
return resourceProvider.contactUnknownSender();
return resourceProvider.contactUnknownSender()
}
Contacts contactHelper = K9.isShowContactName() ? DI.get(Contacts.class) : null;
return toFriendly(address, contactHelper);
val contactHelper = if (isShowContactName) DI.get(Contacts::class.java) else null
return toFriendly(address, contactHelper)
}
public CharSequence getRecipientDisplayNames(Address[] addresses) {
if (addresses == null || addresses.length == 0) {
return resourceProvider.contactUnknownRecipient();
fun getRecipientDisplayNames(addresses: Array<Address>?): CharSequence {
if (addresses == null || addresses.isEmpty()) {
return resourceProvider.contactUnknownRecipient()
}
Contacts contactHelper = K9.isShowContactName() ? DI.get(Contacts.class) : null;
CharSequence recipients = toFriendly(addresses, contactHelper);
return new SpannableStringBuilder(resourceProvider.contactDisplayNamePrefix()).append(recipients);
val contactHelper = if (isShowContactName) DI.get(Contacts::class.java) else null
val recipients = toFriendly(addresses, contactHelper)
return SpannableStringBuilder(resourceProvider.contactDisplayNamePrefix()).append(recipients)
}
public boolean toMe(Account account, List<Address> toAddrs) {
for (Address address : toAddrs) {
if (account.isAnIdentity(address)) {
return true;
fun toMe(account: Account, toAddrs: List<Address?>): Boolean {
for (address in toAddrs) {
if (account.isAnIdentity(address!!)) {
return true
}
}
return false;
return false
}
/**
* Returns the name of the contact this email address belongs to if
* the {@link Contacts contacts} parameter is not {@code null} and a
* contact is found. Otherwise the personal portion of the {@link Address}
* is returned. If that isn't available either, the email address is
* returned.
*
* @param address An {@link com.fsck.k9.mail.Address}
* @param contacts A {@link Contacts} instance or {@code null}.
* @return A "friendly" name for this {@link Address}.
*/
public static CharSequence toFriendly(Address address, Contacts contacts) {
return toFriendly(address,contacts,
K9.isShowCorrespondentNames(),
K9.isChangeContactNameColor(),
K9.getContactNameColor());
}
companion object {
/**
* If the number of addresses exceeds this value the addresses aren't
* resolved to the names of Android contacts.
*
* TODO: This number was chosen arbitrarily and should be determined by performance tests.
*
* @see .toFriendly
*/
private const val TOO_MANY_ADDRESSES = 50
private val SPOOF_ADDRESS_PATTERN = Pattern.compile("[^(]@")
private var sInstance: MessageHelper? = null
public static CharSequence toFriendly(Address[] addresses, Contacts contacts) {
if (addresses == null) {
return null;
}
if (addresses.length >= TOO_MANY_ADDRESSES) {
// Don't look up contacts if the number of addresses is very high.
contacts = null;
}
SpannableStringBuilder sb = new SpannableStringBuilder();
for (int i = 0; i < addresses.length; i++) {
sb.append(toFriendly(addresses[i], contacts));
if (i < addresses.length - 1) {
sb.append(',');
@JvmStatic
@Synchronized
fun getInstance(context: Context): MessageHelper? {
if (sInstance == null) {
val resourceProvider = DI.get(CoreResourceProvider::class.java)
sInstance = MessageHelper(context, resourceProvider)
}
return sInstance
}
return sb;
}
/* package, for testing */ static CharSequence toFriendly(Address address, Contacts contacts,
boolean showCorrespondentNames,
boolean changeContactNameColor,
int contactNameColor) {
if (!showCorrespondentNames) {
return address.getAddress();
} else if (contacts != null) {
final String name = contacts.getNameForAddress(address.getAddress());
if (name != null) {
if (changeContactNameColor) {
final SpannableString coloredName = new SpannableString(name);
coloredName.setSpan(new ForegroundColorSpan(contactNameColor),
0,
coloredName.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
return coloredName;
} else {
return name;
/**
* Returns the name of the contact this email address belongs to if
* the [contacts][Contacts] parameter is not `null` and a
* contact is found. Otherwise the personal portion of the [Address]
* is returned. If that isn't available either, the email address is
* returned.
*
* @param address An [com.fsck.k9.mail.Address]
* @param contacts A [Contacts] instance or `null`.
* @return A "friendly" name for this [Address].
*/
fun toFriendly(address: Address, contacts: Contacts?): CharSequence {
return toFriendly(
address,
contacts,
isShowCorrespondentNames,
isChangeContactNameColor,
contactNameColor,
)
}
fun toFriendly(addresses: Array<Address>?, contacts: Contacts?): CharSequence? {
var contacts = contacts
if (addresses == null) {
return null
}
if (addresses.size >= TOO_MANY_ADDRESSES) {
// Don't look up contacts if the number of addresses is very high.
contacts = null
}
val stringBuilder = SpannableStringBuilder()
for (i in addresses.indices) {
stringBuilder.append(toFriendly(addresses[i], contacts))
if (i < addresses.size - 1) {
stringBuilder.append(',')
}
}
return stringBuilder
}
if (!TextUtils.isEmpty(address.getPersonal()) && !isSpoofAddress(address.getPersonal())) {
return address.getPersonal();
} else {
return address.getAddress();
/* package, for testing */
@JvmStatic
fun toFriendly(
address: Address,
contacts: Contacts?,
showCorrespondentNames: Boolean,
changeContactNameColor: Boolean,
contactNameColor: Int,
): CharSequence {
if (!showCorrespondentNames) {
return address.address
} else if (contacts != null) {
val name = contacts.getNameForAddress(address.address)
if (name != null) {
return if (changeContactNameColor) {
val coloredName = SpannableString(name)
coloredName.setSpan(
ForegroundColorSpan(contactNameColor),
0,
coloredName.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE,
)
coloredName
} else {
name
}
}
}
return if (!TextUtils.isEmpty(address.personal) && !isSpoofAddress(address.personal)) {
address.personal
} else {
address.address
}
}
}
private static boolean isSpoofAddress(String displayName) {
return displayName.contains("@") && SPOOF_ADDRESS_PATTERN.matcher(displayName).find();
private fun isSpoofAddress(displayName: String): Boolean {
return displayName.contains("@") && SPOOF_ADDRESS_PATTERN.matcher(displayName).find()
}
}
}

View File

@ -47,13 +47,13 @@ public class MessageHelperTest extends RobolectricTest {
@Test
public void testToFriendlyShowsPersonalPartIfItExists() throws Exception {
Address address = new Address("test@testor.com", "Tim Testor");
assertEquals("Tim Testor", MessageHelper.toFriendly(address, contacts));
assertEquals("Tim Testor", MessageHelper.Companion.toFriendly(address, contacts));
}
@Test
public void testToFriendlyShowsEmailPartIfNoPersonalPartExists() throws Exception {
Address address = new Address("test@testor.com");
assertEquals("test@testor.com", MessageHelper.toFriendly(address, contacts));
assertEquals("test@testor.com", MessageHelper.Companion.toFriendly(address, contacts));
}
@Test
@ -61,13 +61,13 @@ public class MessageHelperTest extends RobolectricTest {
Address address1 = new Address("test@testor.com", "Tim Testor");
Address address2 = new Address("foo@bar.com", "Foo Bar");
Address[] addresses = new Address[] { address1, address2 };
assertEquals("Tim Testor,Foo Bar", MessageHelper.toFriendly(addresses, contacts).toString());
assertEquals("Tim Testor,Foo Bar", MessageHelper.Companion.toFriendly(addresses, contacts).toString());
}
@Test
public void testToFriendlyWithContactLookup() throws Exception {
Address address = new Address("test@testor.com");
assertEquals("Tim Testor", MessageHelper.toFriendly(address, contactsWithFakeContact).toString());
assertEquals("Tim Testor", MessageHelper.Companion.toFriendly(address, contactsWithFakeContact).toString());
}
@Test
@ -90,29 +90,29 @@ public class MessageHelperTest extends RobolectricTest {
@Test
public void toFriendly_spoofPreventionOverridesPersonal() {
Address address = new Address("test@testor.com", "potus@whitehouse.gov");
CharSequence friendly = MessageHelper.toFriendly(address, contacts);
CharSequence friendly = MessageHelper.Companion.toFriendly(address, contacts);
assertEquals("test@testor.com", friendly.toString());
}
@Test
public void toFriendly_atPrecededByOpeningParenthesisShouldNotTriggerSpoofPrevention() {
Address address = new Address("gitlab@gitlab.example", "username (@username)");
CharSequence friendly = MessageHelper.toFriendly(address, contacts);
CharSequence friendly = MessageHelper.Companion.toFriendly(address, contacts);
assertEquals("username (@username)", friendly.toString());
}
@Test
public void toFriendly_nameStartingWithAtShouldNotTriggerSpoofPrevention() {
Address address = new Address("address@domain.example", "@username");
CharSequence friendly = MessageHelper.toFriendly(address, contacts);
CharSequence friendly = MessageHelper.Companion.toFriendly(address, contacts);
assertEquals("@username", friendly.toString());
}
@Test
public void toFriendly_spoofPreventionDoesntOverrideContact() {
Address address = new Address("test@testor.com", "Tim Testor");
CharSequence friendly = MessageHelper.toFriendly(address, contactsWithFakeSpoofContact,
true, false, 0);
CharSequence friendly = MessageHelper.Companion.toFriendly(address, contactsWithFakeSpoofContact,
true, false, 0);
assertEquals("Tim@Testor", friendly.toString());
}
}

View File

@ -76,6 +76,7 @@
<ID>ForbiddenComment:K9ThemeProvider.kt$K9ThemeProvider$// TODO: Move this class and the theme resources to the main app module</ID>
<ID>ForbiddenComment:MessageDetailsFragment.kt$MessageDetailsFragment$// FIXME: Replace this with a mechanism that survives process death</ID>
<ID>ForbiddenComment:MessageDetailsFragment.kt$MessageDetailsFragment$// TODO: Use the identity this message was sent to as sender identity</ID>
<ID>ForbiddenComment:MessageHelper.kt$MessageHelper.Companion$* If the number of addresses exceeds this value the addresses aren't * resolved to the names of Android contacts. * * TODO: This number was chosen arbitrarily and should be determined by performance tests. * * @see .toFriendly</ID>
<ID>ForbiddenComment:MessageListFragment.kt$MessageListFragment$// FIXME: Don't save the changes in the UI thread</ID>
<ID>ForbiddenComment:MessageListFragment.kt$MessageListFragment$// TODO: empty thread view -&gt; return to full message list</ID>
<ID>ForbiddenComment:MessageListFragment.kt$MessageListFragment.ActionModeCallback$// TODO: Only finish action mode if all messages have been moved.</ID>
@ -551,6 +552,7 @@
<ID>ReturnCount:ListUnsubscribeHelper.kt$ListUnsubscribeHelper$fun getPreferredListUnsubscribeUri(message: Message): UnsubscribeUri?</ID>
<ID>ReturnCount:ListUnsubscribeHelper.kt$ListUnsubscribeHelper$private fun extractUri(headerValue: String?): Uri?</ID>
<ID>ReturnCount:MailSyncWorker.kt$MailSyncWorker$override fun doWork(): Result</ID>
<ID>ReturnCount:MessageHelper.kt$MessageHelper.Companion$@JvmStatic fun toFriendly( address: Address, contacts: Contacts?, showCorrespondentNames: Boolean, changeContactNameColor: Boolean, contactNameColor: Int, ): CharSequence</ID>
<ID>ReturnCount:MessageList.kt$MessageList$private fun decodeExtrasToLaunchData(intent: Intent): LaunchData</ID>
<ID>ReturnCount:MessageList.kt$MessageList$private fun onCustomKeyDown(event: KeyEvent): Boolean</ID>
<ID>ReturnCount:MessageList.kt$MessageList$public override fun onCreate(savedInstanceState: Bundle?)</ID>
@ -807,6 +809,7 @@
<ID>UnusedPrivateMember:Contacts.kt$Contacts$addresses: Array&lt;Address?&gt;?</ID>
<ID>UnusedPrivateMember:ExtraAccountDiscovery.kt$ExtraAccountDiscovery$email: String</ID>
<ID>UnusedPrivateMember:HttpUriParser.kt$HttpUriParser$i</ID>
<ID>UnusedPrivateMember:MessageHelper.kt$MessageHelper$private val mContext: Context</ID>
<ID>UnusedPrivateMember:MessageListLoader.kt$MessageListLoader$account: Account</ID>
<ID>UnusedPrivateMember:MessageViewFragment.kt$MessageViewFragment$requestKey: String</ID>
<ID>UnusedPrivateMember:NewSetupUiHack.kt$NewSetupUiHack$builder: SettingsListBuilder</ID>