Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
package net.thunderbird.core.preference.display.visualSettings

import net.thunderbird.core.preference.BodyContentType
import net.thunderbird.core.preference.display.visualSettings.message.list.DisplayMessageListSettings

const val DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CONTACT_NAME = false
const val DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CONTACT_PICTURE = true
const val DISPLAY_SETTINGS_DEFAULT_IS_CHANGE_CONTACT_NAME_COLOR = true
const val DISPLAY_SETTINGS_DEFAULT_IS_COLORIZE_MISSING_CONTACT_PICTURE = true
const val DISPLAY_SETTINGS_DEFAULT_IS_USE_BACKGROUND_AS_INDICATOR = false
const val DISPLAY_SETTINGS_DEFAULT_IS_USE_MESSAGE_VIEW_FIXED_WIDTH_FONT = false
const val DISPLAY_SETTINGS_DEFAULT_IS_AUTO_FIT_WIDTH = true
const val DISPLAY_SETTINGS_DEFAULT_IS_SHOW_ANIMATION = true
const val DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CORRESPONDENT_NAMES = true
val DISPLAY_SETTINGS_DEFAULT_BODY_CONTENT_TYPE = BodyContentType.TEXT_HTML
const val DISPLAY_SETTINGS_DEFAULT_MESSAGE_LIST_PREVIEW_LINES = 2
const val DISPLAY_SETTINGS_DEFAULT_DRAWER_EXPAND_ALL_FOLDER = false

data class DisplayVisualSettings(
val isShowAnimations: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_SHOW_ANIMATION,
val isShowCorrespondentNames: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CORRESPONDENT_NAMES,
val isShowContactName: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CONTACT_NAME,
val isShowContactPicture: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CONTACT_PICTURE,
val isChangeContactNameColor: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_CHANGE_CONTACT_NAME_COLOR,
val isColorizeMissingContactPictures: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_COLORIZE_MISSING_CONTACT_PICTURE,
val isUseBackgroundAsUnreadIndicator: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_USE_BACKGROUND_AS_INDICATOR,
val isUseMessageViewFixedWidthFont: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_USE_MESSAGE_VIEW_FIXED_WIDTH_FONT,
val isAutoFitWidth: Boolean = DISPLAY_SETTINGS_DEFAULT_IS_AUTO_FIT_WIDTH,
val bodyContentType: BodyContentType = DISPLAY_SETTINGS_DEFAULT_BODY_CONTENT_TYPE,
val messageListPreviewLines: Int = DISPLAY_SETTINGS_DEFAULT_MESSAGE_LIST_PREVIEW_LINES,
val drawerExpandAllFolder: Boolean = DISPLAY_SETTINGS_DEFAULT_DRAWER_EXPAND_ALL_FOLDER,
val messageListSettings: DisplayMessageListSettings = DisplayMessageListSettings(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,10 @@ package net.thunderbird.core.preference.display.visualSettings

import net.thunderbird.core.preference.PreferenceManager

const val KEY_SHOW_CONTACT_NAME = "showContactName"
const val KEY_SHOW_CORRESPONDENT_NAMES = "showCorrespondentNames"
const val KEY_ANIMATION = "animations"
const val KEY_CHANGE_REGISTERED_NAME_COLOR = "changeRegisteredNameColor"
const val KEY_COLORIZE_MISSING_CONTACT_PICTURE = "colorizeMissingContactPictures"
const val KEY_USE_BACKGROUND_AS_UNREAD_INDICATOR = "isUseBackgroundAsUnreadIndicator"
const val KEY_MESSAGE_VIEW_FIXED_WIDTH_FONT = "messageViewFixedWidthFont"
const val KEY_AUTO_FIT_WIDTH = "autofitWidth"
const val KEY_SHOW_CONTACT_PICTURE = "showContactPicture"
const val KEY_MESSAGE_VIEW_BODY_CONTENT_TYPE = "messageViewBodyContentType"
const val KEY_MESSAGE_LIST_VIEW_PREVIEW_LINES = "messageListPreviewLines"

const val KEY_DRAWER_EXPAND_ALL_FOLDER = "drawerExpandAllFolder"

interface DisplayVisualSettingsPreferenceManager : PreferenceManager<DisplayVisualSettings>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.thunderbird.core.preference.display.visualSettings.message.list

const val MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CORRESPONDENT_NAMES = true
const val MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CONTACT_NAME = false
const val MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CONTACT_PICTURE = true
const val MESSAGE_LIST_SETTINGS_DEFAULT_IS_CHANGE_CONTACT_NAME_COLOR = true
const val MESSAGE_LIST_SETTINGS_DEFAULT_IS_COLORIZE_MISSING_CONTACT_PICTURE = true
const val MESSAGE_LIST_SETTINGS_DEFAULT_IS_USE_BACKGROUND_AS_INDICATOR = false
const val MESSAGE_LIST_SETTINGS_DEFAULT_PREVIEW_LINES = 2
val MESSAGE_LIST_SETTINGS_DEFAULT_UI_DENSITY = UiDensity.Default

data class DisplayMessageListSettings(
val isShowCorrespondentNames: Boolean = MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CORRESPONDENT_NAMES,
val isShowContactName: Boolean = MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CONTACT_NAME,
val isShowContactPicture: Boolean = MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CONTACT_PICTURE,
val isChangeContactNameColor: Boolean = MESSAGE_LIST_SETTINGS_DEFAULT_IS_CHANGE_CONTACT_NAME_COLOR,
val isColorizeMissingContactPictures: Boolean = MESSAGE_LIST_SETTINGS_DEFAULT_IS_COLORIZE_MISSING_CONTACT_PICTURE,
val isUseBackgroundAsUnreadIndicator: Boolean = MESSAGE_LIST_SETTINGS_DEFAULT_IS_USE_BACKGROUND_AS_INDICATOR,
val previewLines: Int = MESSAGE_LIST_SETTINGS_DEFAULT_PREVIEW_LINES,
val uiDensity: UiDensity = MESSAGE_LIST_SETTINGS_DEFAULT_UI_DENSITY,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package net.thunderbird.core.preference.display.visualSettings.message.list

import net.thunderbird.core.preference.PreferenceManager

const val KEY_COLORIZE_MISSING_CONTACT_PICTURE = "colorizeMissingContactPictures"
const val KEY_CHANGE_REGISTERED_NAME_COLOR = "changeRegisteredNameColor"
const val KEY_USE_BACKGROUND_AS_UNREAD_INDICATOR = "isUseBackgroundAsUnreadIndicator"
const val KEY_SHOW_CORRESPONDENT_NAMES = "showCorrespondentNames"
const val KEY_SHOW_CONTACT_NAME = "showContactName"
const val KEY_SHOW_CONTACT_PICTURE = "showContactPicture"
const val KEY_MESSAGE_LIST_VIEW_PREVIEW_LINES = "messageListPreviewLines"
const val KEY_MESSAGE_LIST_VIEW_DENSITY = "messageListDensity"

interface MessageListPreferencesManager : PreferenceManager<DisplayMessageListSettings>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package net.thunderbird.core.preference.display.visualSettings.message.list

/**
* Represents the different density levels for the user interface, specifically for the message list.
* This determines the spacing of UI elements.
*/
enum class UiDensity {
/**
* A dense layout with minimal spacing, allowing more items to be visible on the screen at once.
*/
Compact,

/** The standard, default density level, offering a balanced layout. */
Default,

/**
* Provides the most spacing between items, resulting in a less cluttered and more spread-out view.
*/
Relaxed,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import net.thunderbird.core.logging.Logger
import net.thunderbird.core.preference.display.visualSettings.message.list.MessageListPreferencesManager
import net.thunderbird.core.preference.storage.Storage
import net.thunderbird.core.preference.storage.StorageEditor
import net.thunderbird.core.preference.storage.getEnumOrDefault
Expand All @@ -22,32 +27,26 @@ class DefaultDisplayVisualSettingsPreferenceManager(
private val logger: Logger,
private val storage: Storage,
private val storageEditor: StorageEditor,
private val messageListPreferences: MessageListPreferencesManager,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
private var scope: CoroutineScope = CoroutineScope(SupervisorJob()),
private val scope: CoroutineScope = CoroutineScope(SupervisorJob()),
) : DisplayVisualSettingsPreferenceManager {

private val configState: MutableStateFlow<DisplayVisualSettings> = MutableStateFlow(value = loadConfig())
private val internalConfigState = MutableStateFlow(value = loadConfig())
private val configState: StateFlow<DisplayVisualSettings> = combine(
internalConfigState,
messageListPreferences.getConfigFlow(),
) { config, messageListConfig ->
config.copy(messageListSettings = messageListConfig)
}.stateIn(scope = scope, started = SharingStarted.Eagerly, initialValue = internalConfigState.value)
private val mutex = Mutex()

override fun save(config: DisplayVisualSettings) {
logger.debug(TAG) { "save() called with: config = $config" }
writeConfig(config)
configState.update { config }
internalConfigState.update { config }
}

private fun loadConfig(): DisplayVisualSettings = DisplayVisualSettings(
isColorizeMissingContactPictures = storage.getBoolean(
KEY_COLORIZE_MISSING_CONTACT_PICTURE,
DISPLAY_SETTINGS_DEFAULT_IS_COLORIZE_MISSING_CONTACT_PICTURE,
),
isChangeContactNameColor = storage.getBoolean(
KEY_CHANGE_REGISTERED_NAME_COLOR,
DISPLAY_SETTINGS_DEFAULT_IS_CHANGE_CONTACT_NAME_COLOR,
),
isUseBackgroundAsUnreadIndicator = storage.getBoolean(
KEY_USE_BACKGROUND_AS_UNREAD_INDICATOR,
DISPLAY_SETTINGS_DEFAULT_IS_USE_BACKGROUND_AS_INDICATOR,
),
isUseMessageViewFixedWidthFont = storage.getBoolean(
KEY_MESSAGE_VIEW_FIXED_WIDTH_FONT,
DISPLAY_SETTINGS_DEFAULT_IS_USE_MESSAGE_VIEW_FIXED_WIDTH_FONT,
Expand All @@ -60,26 +59,10 @@ class DefaultDisplayVisualSettingsPreferenceManager(
KEY_ANIMATION,
DISPLAY_SETTINGS_DEFAULT_IS_SHOW_ANIMATION,
),
isShowCorrespondentNames = storage.getBoolean(
KEY_SHOW_CORRESPONDENT_NAMES,
DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CORRESPONDENT_NAMES,
),
isShowContactName = storage.getBoolean(
KEY_SHOW_CONTACT_NAME,
DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CONTACT_NAME,
),
isShowContactPicture = storage.getBoolean(
KEY_SHOW_CONTACT_PICTURE,
DISPLAY_SETTINGS_DEFAULT_IS_SHOW_CONTACT_PICTURE,
),
bodyContentType = storage.getEnumOrDefault(
KEY_MESSAGE_VIEW_BODY_CONTENT_TYPE,
DISPLAY_SETTINGS_DEFAULT_BODY_CONTENT_TYPE,
),
messageListPreviewLines = storage.getInt(
KEY_MESSAGE_LIST_VIEW_PREVIEW_LINES,
DISPLAY_SETTINGS_DEFAULT_MESSAGE_LIST_PREVIEW_LINES,
),
drawerExpandAllFolder = storage.getBoolean(
KEY_DRAWER_EXPAND_ALL_FOLDER,
DISPLAY_SETTINGS_DEFAULT_DRAWER_EXPAND_ALL_FOLDER,
Expand All @@ -90,39 +73,15 @@ class DefaultDisplayVisualSettingsPreferenceManager(
logger.debug(TAG) { "writeConfig() called with: config = $config" }
scope.launch(ioDispatcher) {
mutex.withLock {
storageEditor.putBoolean(
KEY_CHANGE_REGISTERED_NAME_COLOR,
config.isChangeContactNameColor,
)
storageEditor.putBoolean(
KEY_COLORIZE_MISSING_CONTACT_PICTURE,
config.isColorizeMissingContactPictures,
)
storageEditor.putBoolean(KEY_ANIMATION, config.isShowAnimations)
storageEditor.putBoolean(
KEY_SHOW_CONTACT_PICTURE,
config.isShowContactPicture,
)
storageEditor.putBoolean(
KEY_USE_BACKGROUND_AS_UNREAD_INDICATOR,
config.isUseBackgroundAsUnreadIndicator,
)
storageEditor.putBoolean(
KEY_MESSAGE_VIEW_FIXED_WIDTH_FONT,
config.isUseMessageViewFixedWidthFont,
)
storageEditor.putBoolean(KEY_AUTO_FIT_WIDTH, config.isAutoFitWidth)
storageEditor.putBoolean(KEY_SHOW_CONTACT_NAME, config.isShowContactName)
storageEditor.putBoolean(
KEY_SHOW_CORRESPONDENT_NAMES,
config.isShowCorrespondentNames,
)
storageEditor.putEnum(KEY_MESSAGE_VIEW_BODY_CONTENT_TYPE, config.bodyContentType)
storageEditor.putInt(
KEY_MESSAGE_LIST_VIEW_PREVIEW_LINES,
config.messageListPreviewLines,
)
storageEditor.putBoolean(KEY_DRAWER_EXPAND_ALL_FOLDER, config.drawerExpandAllFolder)
messageListPreferences.save(config.messageListSettings)
storageEditor.commit().also { commited ->
logger.verbose(TAG) { "writeConfig: storageEditor.commit() resulted in: $commited" }
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package net.thunderbird.core.preference.display.visualSettings.message.list

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import net.thunderbird.core.logging.Logger
import net.thunderbird.core.preference.storage.Storage
import net.thunderbird.core.preference.storage.StorageEditor
import net.thunderbird.core.preference.storage.getEnumOrDefault
import net.thunderbird.core.preference.storage.putEnum

private const val TAG = "DefaultMessageListPreferencesManager"

class DefaultMessageListPreferencesManager(
private val logger: Logger,
private val storage: Storage,
private val storageEditor: StorageEditor,
) : MessageListPreferencesManager {
private val preferences = MutableStateFlow(value = loadPreferences())
override fun save(config: DisplayMessageListSettings) {
logger.debug(TAG) { "save() called with: config = $config" }
write(config)
preferences.update { config }
}

private fun loadPreferences(): DisplayMessageListSettings = DisplayMessageListSettings(
isColorizeMissingContactPictures = storage.getBoolean(
KEY_COLORIZE_MISSING_CONTACT_PICTURE,
MESSAGE_LIST_SETTINGS_DEFAULT_IS_COLORIZE_MISSING_CONTACT_PICTURE,
),
isChangeContactNameColor = storage.getBoolean(
KEY_CHANGE_REGISTERED_NAME_COLOR,
MESSAGE_LIST_SETTINGS_DEFAULT_IS_CHANGE_CONTACT_NAME_COLOR,
),
isUseBackgroundAsUnreadIndicator = storage.getBoolean(
KEY_USE_BACKGROUND_AS_UNREAD_INDICATOR,
MESSAGE_LIST_SETTINGS_DEFAULT_IS_USE_BACKGROUND_AS_INDICATOR,
),
isShowCorrespondentNames = storage.getBoolean(
KEY_SHOW_CORRESPONDENT_NAMES,
MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CORRESPONDENT_NAMES,
),
isShowContactName = storage.getBoolean(
KEY_SHOW_CONTACT_NAME,
MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CONTACT_NAME,
),
isShowContactPicture = storage.getBoolean(
KEY_SHOW_CONTACT_PICTURE,
MESSAGE_LIST_SETTINGS_DEFAULT_IS_SHOW_CONTACT_PICTURE,
),
previewLines = storage.getInt(
KEY_MESSAGE_LIST_VIEW_PREVIEW_LINES,
MESSAGE_LIST_SETTINGS_DEFAULT_PREVIEW_LINES,
),
uiDensity = storage.getEnumOrDefault(
KEY_MESSAGE_LIST_VIEW_DENSITY,
MESSAGE_LIST_SETTINGS_DEFAULT_UI_DENSITY,
),
)

private fun write(preferences: DisplayMessageListSettings) {
storageEditor.putBoolean(KEY_CHANGE_REGISTERED_NAME_COLOR, preferences.isChangeContactNameColor)
storageEditor.putBoolean(KEY_COLORIZE_MISSING_CONTACT_PICTURE, preferences.isColorizeMissingContactPictures)
storageEditor.putBoolean(KEY_SHOW_CONTACT_PICTURE, preferences.isShowContactPicture)
storageEditor.putBoolean(KEY_USE_BACKGROUND_AS_UNREAD_INDICATOR, preferences.isUseBackgroundAsUnreadIndicator)
storageEditor.putBoolean(KEY_SHOW_CONTACT_NAME, preferences.isShowContactName)
storageEditor.putBoolean(KEY_SHOW_CORRESPONDENT_NAMES, preferences.isShowCorrespondentNames)
storageEditor.putInt(KEY_MESSAGE_LIST_VIEW_PREVIEW_LINES, preferences.previewLines)
storageEditor.putEnum(KEY_MESSAGE_LIST_VIEW_DENSITY, preferences.uiDensity)
}

override fun getConfig(): DisplayMessageListSettings = preferences.value
override fun getConfigFlow(): Flow<DisplayMessageListSettings> = preferences
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ val featureWidgetMessageListModule = module {
accountManager = get(),
messageListRepository = get(),
messageHelper = get(),
generalSettingsManager = get(),
messageListPreferencesManager = get(),
outboxFolderManager = get(),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import com.fsck.k9.ui.helper.DisplayAddressHelper
import java.util.Calendar
import java.util.Locale
import net.thunderbird.core.android.account.LegacyAccount
import net.thunderbird.core.preference.GeneralSettingsManager
import net.thunderbird.core.preference.display.visualSettings.message.list.MessageListPreferencesManager
import net.thunderbird.feature.mail.folder.api.OutboxFolderManager

internal class MessageListItemMapper(
private val messageHelper: MessageHelper,
private val account: LegacyAccount,
private val generalSettingsManager: GeneralSettingsManager,
private val messageListPreferencesManager: MessageListPreferencesManager,
private val outboxFolderManager: OutboxFolderManager,
) : MessageMapper<MessageListItem> {
private val calendar: Calendar = Calendar.getInstance()
Expand All @@ -28,18 +28,11 @@ internal class MessageListItemMapper(
val showRecipients = DisplayAddressHelper.shouldShowRecipients(outboxFolderManager, account, message.folderId)
val displayAddress = if (showRecipients) toAddresses.firstOrNull() else fromAddresses.firstOrNull()
val displayName = if (showRecipients) {
val settings = messageListPreferencesManager.getConfig()
messageHelper.getRecipientDisplayNames(
addresses = toAddresses.toTypedArray(),
isShowCorrespondentNames = generalSettingsManager
.getConfig()
.display
.visualSettings
.isShowCorrespondentNames,
isChangeContactNameColor = generalSettingsManager
.getConfig()
.display
.visualSettings
.isChangeContactNameColor,
isShowCorrespondentNames = settings.isShowCorrespondentNames,
isChangeContactNameColor = settings.isChangeContactNameColor,
).toString()
} else {
messageHelper.getSenderDisplayName(displayAddress).toString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import net.thunderbird.core.android.account.LegacyAccount
import net.thunderbird.core.android.account.LegacyAccountManager
import net.thunderbird.core.android.account.SortType
import net.thunderbird.core.logging.legacy.Log
import net.thunderbird.core.preference.GeneralSettingsManager
import net.thunderbird.core.preference.display.visualSettings.message.list.MessageListPreferencesManager
import net.thunderbird.feature.mail.folder.api.OutboxFolderManager
import net.thunderbird.feature.search.legacy.sql.SqlWhereClause

internal class MessageListLoader(
private val accountManager: LegacyAccountManager,
private val messageListRepository: MessageListRepository,
private val messageHelper: MessageHelper,
private val generalSettingsManager: GeneralSettingsManager,
private val messageListPreferencesManager: MessageListPreferencesManager,
private val outboxFolderManager: OutboxFolderManager,
) {

Expand Down Expand Up @@ -46,7 +46,7 @@ internal class MessageListLoader(
private fun loadMessageListForAccount(account: LegacyAccount, config: MessageListConfig): List<MessageListItem> {
val accountUuid = account.uuid
val sortOrder = buildSortOrder(config)
val mapper = MessageListItemMapper(messageHelper, account, generalSettingsManager, outboxFolderManager)
val mapper = MessageListItemMapper(messageHelper, account, messageListPreferencesManager, outboxFolderManager)

return if (config.showingThreadedList) {
val (selection, selectionArgs) = buildSelection(config)
Expand Down
Loading
Loading