Skip to content
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package app.k9mail.featureflag

import com.fsck.k9.ui.messagelist.MessageListFeatureFlags
import net.thunderbird.core.featureflag.FeatureFlag
import net.thunderbird.core.featureflag.FeatureFlagFactory
import net.thunderbird.core.featureflag.FeatureFlagKey
Expand All @@ -16,6 +17,7 @@ class K9FeatureFlagFactory : FeatureFlagFactory {
FeatureFlag("enable_dropdown_drawer_ui".toFeatureFlagKey(), enabled = true),
FeatureFlag(FeatureFlagKey.DisplayInAppNotifications, enabled = true),
FeatureFlag(FeatureFlagKey.UseNotificationSenderForSystemNotifications, enabled = true),
FeatureFlag(MessageListFeatureFlags.UseComposeForMessageListItems, enabled = false),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package app.k9mail.featureflag

import com.fsck.k9.ui.messagelist.MessageListFeatureFlags
import net.thunderbird.core.featureflag.FeatureFlag
import net.thunderbird.core.featureflag.FeatureFlagFactory
import net.thunderbird.core.featureflag.FeatureFlagKey
Expand All @@ -20,6 +21,7 @@ class K9FeatureFlagFactory : FeatureFlagFactory {
FeatureFlag("enable_dropdown_drawer_ui".toFeatureFlagKey(), enabled = false),
FeatureFlag(FeatureFlagKey.DisplayInAppNotifications, enabled = false),
FeatureFlag(FeatureFlagKey.UseNotificationSenderForSystemNotifications, enabled = false),
FeatureFlag(MessageListFeatureFlags.UseComposeForMessageListItems, enabled = false),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.thunderbird.android.featureflag

import com.fsck.k9.ui.messagelist.MessageListFeatureFlags
import net.thunderbird.core.featureflag.FeatureFlag
import net.thunderbird.core.featureflag.FeatureFlagFactory
import net.thunderbird.core.featureflag.FeatureFlagKey
Expand All @@ -19,6 +20,7 @@ class TbFeatureFlagFactory : FeatureFlagFactory {
FeatureFlag("enable_dropdown_drawer_ui".toFeatureFlagKey(), enabled = true),
FeatureFlag(FeatureFlagKey.DisplayInAppNotifications, enabled = true),
FeatureFlag(FeatureFlagKey.UseNotificationSenderForSystemNotifications, enabled = false),
FeatureFlag(MessageListFeatureFlags.UseComposeForMessageListItems, enabled = false),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.thunderbird.android.featureflag

import com.fsck.k9.ui.messagelist.MessageListFeatureFlags
import net.thunderbird.core.featureflag.FeatureFlag
import net.thunderbird.core.featureflag.FeatureFlagFactory
import net.thunderbird.core.featureflag.FeatureFlagKey
Expand All @@ -19,6 +20,7 @@ class TbFeatureFlagFactory : FeatureFlagFactory {
FeatureFlag("enable_dropdown_drawer_ui".toFeatureFlagKey(), enabled = true),
FeatureFlag(FeatureFlagKey.DisplayInAppNotifications, enabled = true),
FeatureFlag(FeatureFlagKey.UseNotificationSenderForSystemNotifications, enabled = true),
FeatureFlag(MessageListFeatureFlags.UseComposeForMessageListItems, enabled = false),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.thunderbird.android.featureflag

import com.fsck.k9.ui.messagelist.MessageListFeatureFlags
import net.thunderbird.core.featureflag.FeatureFlag
import net.thunderbird.core.featureflag.FeatureFlagFactory
import net.thunderbird.core.featureflag.FeatureFlagKey
Expand All @@ -19,6 +20,7 @@ class TbFeatureFlagFactory : FeatureFlagFactory {
FeatureFlag("enable_dropdown_drawer_ui".toFeatureFlagKey(), enabled = true),
FeatureFlag(FeatureFlagKey.DisplayInAppNotifications, enabled = true),
FeatureFlag(FeatureFlagKey.UseNotificationSenderForSystemNotifications, enabled = true),
FeatureFlag(MessageListFeatureFlags.UseComposeForMessageListItems, enabled = false),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.thunderbird.android.featureflag

import com.fsck.k9.ui.messagelist.MessageListFeatureFlags
import net.thunderbird.core.featureflag.FeatureFlag
import net.thunderbird.core.featureflag.FeatureFlagFactory
import net.thunderbird.core.featureflag.FeatureFlagKey
Expand All @@ -19,6 +20,7 @@ class TbFeatureFlagFactory : FeatureFlagFactory {
FeatureFlag("enable_dropdown_drawer_ui".toFeatureFlagKey(), enabled = false),
FeatureFlag(FeatureFlagKey.DisplayInAppNotifications, enabled = false),
FeatureFlag(FeatureFlagKey.UseNotificationSenderForSystemNotifications, enabled = false),
FeatureFlag(MessageListFeatureFlags.UseComposeForMessageListItems, enabled = false),
)
}
}
1 change: 1 addition & 0 deletions legacy/ui/legacy/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
implementation(projects.core.ui.theme.api)
implementation(projects.feature.launcher)
implementation(projects.core.common)
implementation(projects.core.ui.compose.designsystem)
implementation(projects.feature.navigation.drawer.api)
implementation(projects.feature.navigation.drawer.dropdown)
implementation(projects.feature.navigation.drawer.siderail)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.fsck.k9.ui.messagelist.item

import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewLightDark
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemesLightDark
import com.fsck.k9.FontSizes
import com.fsck.k9.UiDensity
import com.fsck.k9.mail.AuthType
import com.fsck.k9.mail.ConnectionSecurity
import com.fsck.k9.mail.ServerSettings
import com.fsck.k9.ui.messagelist.MessageListAppearance
import com.fsck.k9.ui.messagelist.MessageListItem
import net.thunderbird.core.android.account.Identity
import net.thunderbird.core.android.account.LegacyAccount
import net.thunderbird.feature.account.AccountIdFactory
import net.thunderbird.feature.account.storage.profile.AvatarDto
import net.thunderbird.feature.account.storage.profile.AvatarTypeDto
import net.thunderbird.feature.account.storage.profile.ProfileDto

@Composable
@PreviewLightDark
internal fun MessageItemContentPreview() {
PreviewWithThemesLightDark {
MessageItemContent(
item = fakeMessageListItem,
isActive = true,
isSelected = false,
onClick = {},
onLongClick = {},
onAvatarClick = {},
onFavouriteClick = {},
appearance = fakeMessageListAppearance,
)
}
}

private val accountId = AccountIdFactory.create()

private val serverSettings = ServerSettings(
type = "imap",
host = "imap.example.com",
port = 993,
connectionSecurity = ConnectionSecurity.SSL_TLS_REQUIRED,
authenticationType = AuthType.PLAIN,
username = "username",
password = "password",
clientCertificateAlias = null,
)
private val fakeMessageListItem = MessageListItem(
account = LegacyAccount(
id = accountId,
name = "Name",
email = "[email protected]",
profile = ProfileDto(
id = accountId,
name = "Name",
color = 0xFF0000FF.toInt(),
avatar = AvatarDto(
avatarType = AvatarTypeDto.MONOGRAM,
avatarMonogram = "AB",
avatarImageUri = null,
avatarIconName = null,
),
),
incomingServerSettings = serverSettings,
outgoingServerSettings = serverSettings,
identities = listOf(Identity()),
),
subject = "Subject",
threadCount = 0,
messageDate = 1234456789L,
internalDate = 1234456789L,
displayName = "Sender Name",
displayAddress = null,
previewText = "This is the preview text.",
isMessageEncrypted = false,
isRead = false,
isStarred = false,
isAnswered = false,
isForwarded = false,
hasAttachments = false,
uniqueId = 42L,
folderId = 123L,
messageUid = "654321",
databaseId = 1L,
threadRoot = 1L,
)

private val fakeMessageListAppearance = MessageListAppearance(
fontSizes = FontSizes(),
previewLines = 2,
stars = true,
senderAboveSubject = false,
showContactPicture = true,
showingThreadedList = false,
backGroundAsReadIndicator = false,
showAccountIndicator = true,
density = UiDensity.Default,
)
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ open class MessageList :
private var messageListWasDisplayed = false
private var viewSwitcher: ViewSwitcher? = null

private val isShowAccountChip: Boolean
get() = messageListFragment?.isShowAccountChip ?: true
private val isShowAccountIndicator: Boolean
get() = messageListFragment?.isShowAccountIndicator ?: true

public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -1106,7 +1106,7 @@ open class MessageList :
} else {
val fragment = MessageViewContainerFragment.newInstance(
reference = messageReference,
showAccountChip = isShowAccountChip,
isShowAccountIndicator = isShowAccountIndicator,
)
supportFragmentManager.commitNow {
replace(R.id.message_view_container, fragment, FRAGMENT_TAG_MESSAGE_VIEW_CONTAINER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ import app.k9mail.feature.launcher.FeatureLauncherTarget
import app.k9mail.legacy.message.controller.MessageReference
import com.fsck.k9.contacts.ContactPictureLoader
import com.fsck.k9.ui.helper.RelativeDateTimeFormatter
import com.fsck.k9.ui.messagelist.MessageListFeatureFlags.UseComposeForMessageListItems
import com.fsck.k9.ui.messagelist.item.BannerInlineListInAppNotificationViewHolder
import com.fsck.k9.ui.messagelist.item.ComposableMessageViewHolder
import com.fsck.k9.ui.messagelist.item.FooterViewHolder
import com.fsck.k9.ui.messagelist.item.MessageListViewHolder
import com.fsck.k9.ui.messagelist.item.MessageViewHolder
import com.fsck.k9.ui.messagelist.item.MessageViewHolderColors
import net.thunderbird.core.featureflag.FeatureFlagKey
import net.thunderbird.core.featureflag.FeatureFlagProvider
import net.thunderbird.core.featureflag.FeatureFlagResult
import net.thunderbird.core.ui.theme.api.FeatureThemeProvider
import net.thunderbird.feature.notification.api.ui.action.NotificationAction

private const val FOOTER_ID = 1L
Expand All @@ -42,6 +45,7 @@ class MessageListAdapter internal constructor(
private val listItemListener: MessageListItemActionListener,
private val appearance: MessageListAppearance,
private val relativeDateTimeFormatter: RelativeDateTimeFormatter,
private val themeProvider: FeatureThemeProvider,
private val featureFlagProvider: FeatureFlagProvider,
) : RecyclerView.Adapter<MessageListViewHolder>() {

Expand Down Expand Up @@ -227,7 +231,15 @@ class MessageListAdapter internal constructor(

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageListViewHolder {
return when (viewType) {
TYPE_MESSAGE -> createMessageViewHolder(parent)
TYPE_MESSAGE -> {
val result = featureFlagProvider.provide(UseComposeForMessageListItems)
if (result.isEnabled()) {
createComposableMessageViewHolder(parent)
} else {
createMessageViewHolder(parent)
}
}

TYPE_FOOTER -> FooterViewHolder.create(layoutInflater, parent, footerClickListener)
TYPE_IN_APP_NOTIFICATION_BANNER_INLINE_LIST if isInAppNotificationEnabled ->
BannerInlineListInAppNotificationViewHolder(
Expand Down Expand Up @@ -259,7 +271,7 @@ class MessageListAdapter internal constructor(
}
}

private fun createMessageViewHolder(parent: ViewGroup?): MessageViewHolder =
private fun createMessageViewHolder(parent: ViewGroup): MessageViewHolder =
MessageViewHolder.create(
layoutInflater = layoutInflater,
parent = parent,
Expand All @@ -275,19 +287,40 @@ class MessageListAdapter internal constructor(
starClickListener = starClickListener,
)

private fun createComposableMessageViewHolder(parent: ViewGroup): MessageListViewHolder =
ComposableMessageViewHolder.create(
context = parent.context,
themeProvider = themeProvider,
onClick = { listItemListener.onMessageClicked(it) },
onLongClick = { listItemListener.onToggleMessageSelection(it) },
onFavouriteClick = { listItemListener.onToggleMessageFlag(it) },
onAvatarClick = { listItemListener.onToggleMessageSelection(it) },
appearance = appearance,
)

override fun onBindViewHolder(holder: MessageListViewHolder, position: Int) {
when (val viewType = getItemViewType(position)) {
TYPE_IN_APP_NOTIFICATION_BANNER_INLINE_LIST if isInAppNotificationEnabled ->
(holder as BannerInlineListInAppNotificationViewHolder).bind()

TYPE_MESSAGE -> {
val messageListItem = getItem(position)
val messageViewHolder = holder as MessageViewHolder
messageViewHolder.bind(
messageListItem = messageListItem,
isActive = isActiveMessage(messageListItem),
isSelected = isSelected(messageListItem),
)
val result = featureFlagProvider.provide(UseComposeForMessageListItems)
if (result.isEnabled()) {
val messageViewHolder = holder as ComposableMessageViewHolder
messageViewHolder.bind(
item = messageListItem,
isActive = isActiveMessage(messageListItem),
isSelected = isSelected(messageListItem),
)
} else {
val messageViewHolder = holder as MessageViewHolder
messageViewHolder.bind(
messageListItem = messageListItem,
isActive = isActiveMessage(messageListItem),
isSelected = isSelected(messageListItem),
)
}
}

TYPE_FOOTER -> {
Expand Down Expand Up @@ -368,8 +401,13 @@ class MessageListAdapter internal constructor(
}

private fun getItemFromView(view: View): MessageListItem? {
val messageViewHolder = view.tag as MessageViewHolder
return getItemById(messageViewHolder.uniqueId)
if (featureFlagProvider.provide(UseComposeForMessageListItems).isEnabled()) {
val messageViewHolder = view.tag as ComposableMessageViewHolder
return getItemById(messageViewHolder.uniqueId)
} else {
val messageViewHolder = view.tag as MessageViewHolder
return getItemById(messageViewHolder.uniqueId)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ data class MessageListAppearance(
val showContactPicture: Boolean,
val showingThreadedList: Boolean,
val backGroundAsReadIndicator: Boolean,
val showAccountChip: Boolean,
/**
* Whether to show an account color indicator on the left side of the message item.
*/
val showAccountIndicator: Boolean,
val density: UiDensity,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.fsck.k9.ui.messagelist

import net.thunderbird.core.featureflag.FeatureFlagKey

object MessageListFeatureFlags {

val UseComposeForMessageListItems = FeatureFlagKey("use_compose_for_message_list_items")
}
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class MessageListFragment :
maybeHideFloatingActionButton()
}

val isShowAccountChip: Boolean
val isShowAccountIndicator: Boolean
get() = isUnifiedFolders || !isSingleAccountMode

override fun onAttach(context: Context) {
Expand Down Expand Up @@ -344,6 +344,7 @@ class MessageListFragment :
listItemListener = this,
appearance = messageListAppearance,
relativeDateTimeFormatter = RelativeDateTimeFormatter(requireContext(), clock),
themeProvider = featureThemeProvider,
featureFlagProvider = featureFlagProvider,
).apply {
activeMessage = [email protected]
Expand Down Expand Up @@ -784,7 +785,7 @@ class MessageListFragment :
showingThreadedList = showingThreadedList,
backGroundAsReadIndicator = generalSettingsManager
.getConfig().display.visualSettings.isUseBackgroundAsUnreadIndicator,
showAccountChip = isShowAccountChip,
showAccountIndicator = isShowAccountIndicator,
density = K9.messageListDensity,
)

Expand Down
Loading
Loading