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,5 +1,7 @@
package net.thunderbird.core.preference

import net.thunderbird.core.preference.privacy.PrivacySettings

/**
* Stores a snapshot of the app's general settings.
*
Expand Down Expand Up @@ -37,6 +39,7 @@ data class GeneralSettings(
val quietTimeStarts: String,
val isQuietTimeEnabled: Boolean,
val isQuietTime: Boolean,
val privacy: PrivacySettings,
)

enum class BackgroundSync {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package net.thunderbird.core.preference

import kotlinx.coroutines.flow.Flow
import net.thunderbird.core.preference.privacy.PrivacySettingsManager

/**
* Retrieve and modify general settings.
*
* TODO: Add more settings as needed.
*/
interface GeneralSettingsManager {
interface GeneralSettingsManager : PrivacySettingsManager {
fun getSettings(): GeneralSettings
fun getSettingsFlow(): Flow<GeneralSettings>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.thunderbird.core.preference.privacy

data class PrivacySettings(
val isHideTimeZone: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.thunderbird.core.preference.privacy

interface PrivacySettingsManager {
val privacySettings: PrivacySettings

fun setIsHideTimeZone(isHideTimeZone: Boolean)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.thunderbird.core.preference.privacy

import net.thunderbird.core.preference.PreferenceManager

interface PrivacySettingsPreferenceManager : PreferenceManager<PrivacySettings>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package net.thunderbird.core.preference.privacy

class DefaultPrivacySettingsManager(
private val preferenceManager: PrivacySettingsPreferenceManager,
) : PrivacySettingsManager {
override val privacySettings: PrivacySettings
get() = preferenceManager.getConfig()

override fun setIsHideTimeZone(isHideTimeZone: Boolean) {
val privacySettings = preferenceManager.getConfig()
preferenceManager.save(privacySettings.copy(isHideTimeZone = isHideTimeZone))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package net.thunderbird.core.preference.privacy

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import net.thunderbird.core.preference.PreferenceChangeBroker
import net.thunderbird.core.preference.PreferenceChangeSubscriber
import net.thunderbird.core.preference.storage.Storage
import net.thunderbird.core.preference.storage.StorageEditor

class DefaultPrivacySettingsPreferenceManager(
private val storage: Storage,
private val storageEditor: StorageEditor,
private val changeBroker: PreferenceChangeBroker,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
private var scope: CoroutineScope = CoroutineScope(SupervisorJob()),
) : PrivacySettingsPreferenceManager {
private val configState: MutableStateFlow<PrivacySettings> = MutableStateFlow(value = loadConfig())
private val mutex = Mutex()

init {
asSettingsFlow()
.onEach { config ->
configState.update { config }
}
.launchIn(scope)
}

override fun save(config: PrivacySettings) {
configState.update { config }
writeConfig(config)
}

override fun getConfig(): PrivacySettings = configState.value
override fun getConfigFlow(): Flow<PrivacySettings> = configState

// Not 100% sure if this method is really required, but applied the same logic
// present in the RealDrawerConfigManager implementation
private fun asSettingsFlow(): Flow<PrivacySettings> {
return callbackFlow {
send(loadConfig())

val subscriber = PreferenceChangeSubscriber {
configState.update { loadConfig() }
}

changeBroker.subscribe(subscriber)

awaitClose {
changeBroker.unsubscribe(subscriber)
}
}
}

private fun loadConfig(): PrivacySettings = PrivacySettings(
isHideTimeZone = storage.getBoolean(KEY_HIDE_TIME_ZONE, false),
)

private fun writeConfig(config: PrivacySettings) {
scope.launch(ioDispatcher) {
mutex.withLock {
storageEditor.putBoolean(KEY_HIDE_TIME_ZONE, config.isHideTimeZone)
storageEditor.commit()
}
}
}

companion object {
private const val KEY_HIDE_TIME_ZONE = "hideTimeZone"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import assertk.assertThat
import assertk.assertions.containsOnly
import assertk.assertions.hasSize
import assertk.assertions.isEmpty
import dev.mokkery.mock
import kotlin.random.Random
import kotlin.test.Test
import kotlin.uuid.ExperimentalUuidApi
Expand All @@ -19,6 +20,8 @@ import net.thunderbird.core.preference.BackgroundSync
import net.thunderbird.core.preference.GeneralSettings
import net.thunderbird.core.preference.GeneralSettingsManager
import net.thunderbird.core.preference.SubTheme
import net.thunderbird.core.preference.privacy.PrivacySettings
import net.thunderbird.core.preference.privacy.PrivacySettingsManager
import net.thunderbird.core.preference.storage.Storage
import net.thunderbird.feature.mail.message.list.fakes.FakeAccount
import net.thunderbird.feature.mail.message.list.fakes.FakeAccountManager
Expand Down Expand Up @@ -54,6 +57,8 @@ class BuildSwipeActionsTest {
quietTimeEnds = "7:00",
isQuietTime = false,
isQuietTimeEnabled = false,
privacy = PrivacySettings(isHideTimeZone = false),

)

@Test
Expand Down Expand Up @@ -366,15 +371,16 @@ class BuildSwipeActionsTest {
accountsUuids: List<String>,
storageValues: Map<String, String> = mapOf(),
): BuildSwipeActions = BuildSwipeActions(
generalSettingsManager = FakeGeneralSettingsManager(initialGeneralSettings),
generalSettingsManager = FakeGeneralSettingsManager(initialGeneralSettings, mock()),
accountManager = FakeAccountManager(accounts = accountsUuids.map { FakeAccount(uuid = it) }),
storage = FakeStorage(storageValues),
)
}

private class FakeGeneralSettingsManager(
initialGeneralSettings: GeneralSettings,
) : GeneralSettingsManager {
private val privacySettingsManager: PrivacySettingsManager,
) : GeneralSettingsManager, PrivacySettingsManager by privacySettingsManager {
private val generalSettings = MutableStateFlow(initialGeneralSettings)
override fun getSettings(): GeneralSettings = generalSettings.value

Expand Down Expand Up @@ -447,6 +453,10 @@ private class FakeGeneralSettingsManager(
override fun setIsQuietTimeEnabled(isQuietTimeEnabled: Boolean) = error(
"not implemented",
)

override fun setIsHideTimeZone(isHideTimeZone: Boolean) = error(
"not implemented",
)
}

private class FakeStorage(
Expand Down
5 changes: 0 additions & 5 deletions legacy/core/src/main/java/com/fsck/k9/K9.kt
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,6 @@ object K9 : KoinComponent {
@JvmStatic
var isHideUserAgent = false

@JvmStatic
var isHideTimeZone = false

@get:Synchronized
@set:Synchronized
@JvmStatic
Expand Down Expand Up @@ -300,7 +297,6 @@ object K9 : KoinComponent {
messageViewPostMarkAsUnreadNavigation =
storage.getEnum("messageViewPostMarkAsUnreadAction", PostMarkAsUnreadNavigation.ReturnToMessageList)
isHideUserAgent = storage.getBoolean("hideUserAgent", false)
isHideTimeZone = storage.getBoolean("hideTimeZone", false)

isConfirmDelete = storage.getBoolean("confirmDelete", false)
isConfirmDiscardMessage = storage.getBoolean("confirmDiscardMessage", true)
Expand Down Expand Up @@ -374,7 +370,6 @@ object K9 : KoinComponent {
editor.putEnum("messageViewPostDeleteAction", messageViewPostRemoveNavigation)
editor.putEnum("messageViewPostMarkAsUnreadAction", messageViewPostMarkAsUnreadNavigation)
editor.putBoolean("hideUserAgent", isHideUserAgent)
editor.putBoolean("hideTimeZone", isHideTimeZone)

editor.putString("language", k9Language)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.fsck.k9.autocrypt

import com.fsck.k9.K9
import com.fsck.k9.mail.Address
import com.fsck.k9.mail.Flag
import com.fsck.k9.mail.Message
Expand All @@ -13,8 +12,12 @@ import com.fsck.k9.mail.internet.MimeMultipart
import com.fsck.k9.mail.internet.TextBody
import com.fsck.k9.mailstore.BinaryMemoryBody
import java.util.Date
import net.thunderbird.core.preference.GeneralSettingsManager

class AutocryptTransferMessageCreator(private val stringProvider: AutocryptStringProvider) {
class AutocryptTransferMessageCreator(
private val stringProvider: AutocryptStringProvider,
private val generalSettingsManager: GeneralSettingsManager,
) {
fun createAutocryptTransferMessage(data: ByteArray, address: Address): Message {
try {
val subjectText = stringProvider.transferMessageSubject()
Expand All @@ -41,7 +44,10 @@ class AutocryptTransferMessageCreator(private val stringProvider: AutocryptStrin
message.subject = subjectText
message.setHeader("Autocrypt-Setup-Message", "v1")
message.internalDate = nowDate
message.addSentDate(nowDate, K9.isHideTimeZone)
message.addSentDate(
nowDate,
generalSettingsManager.getSettings().privacy.isHideTimeZone,
)
message.setFrom(address)
message.setHeader("To", address.toEncodedString())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package com.fsck.k9.autocrypt
import org.koin.dsl.module

val autocryptModule = module {
single { AutocryptTransferMessageCreator(get()) }
single {
AutocryptTransferMessageCreator(
stringProvider = get(),
generalSettingsManager = get(),
)
}
single { AutocryptDraftStateHeaderParser() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.Message.RecipientType;
import com.fsck.k9.message.html.HtmlConverter;
import net.thunderbird.core.preference.GeneralSettingsManager;


public class HtmlQuoteCreator {
Expand Down Expand Up @@ -42,11 +43,11 @@ public class HtmlQuoteCreator {
* @return Modified insertable message.
*/
public static InsertableHtmlContent quoteOriginalHtmlMessage(Message originalMessage,
String messageBody, QuoteStyle quoteStyle) {
String messageBody, QuoteStyle quoteStyle, GeneralSettingsManager generalSettingsManager) {
CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
InsertableHtmlContent insertable = findInsertionPoints(messageBody);

String sentDate = new QuoteDateFormatter().format(originalMessage.getSentDate());
String sentDate = new QuoteDateFormatter(generalSettingsManager).format(originalMessage.getSentDate());
String fromAddress = Address.toString(originalMessage.getFrom());
if (quoteStyle == QuoteStyle.PREFIX) {
StringBuilder header = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ package com.fsck.k9.message.quote
import org.koin.dsl.module

val quoteModule = module {
factory { QuoteDateFormatter() }
factory { QuoteDateFormatter(generalSettingsManager = get()) }
factory { TextQuoteCreator(get(), get()) }
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.fsck.k9.message.quote

import com.fsck.k9.K9
import java.text.DateFormat
import java.util.Date
import java.util.TimeZone
import net.thunderbird.core.preference.GeneralSettingsManager

/**
* Convert a date into a locale-specific date string suitable for use in a header for a quoted message.
*/
class QuoteDateFormatter {
class QuoteDateFormatter(
private val generalSettingsManager: GeneralSettingsManager,
) {

fun format(date: Date): String {
return try {
Expand All @@ -21,7 +23,7 @@ class QuoteDateFormatter {

private fun createDateFormat(): DateFormat {
return DateFormat.getDateTimeInstance(DATE_STYLE, TIME_STYLE).apply {
if (K9.isHideTimeZone) {
if (generalSettingsManager.getSettings().privacy.isHideTimeZone) {
timeZone = TimeZone.getTimeZone("UTC")
}
}
Expand Down
13 changes: 13 additions & 0 deletions legacy/core/src/main/java/com/fsck/k9/preferences/KoinModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import net.thunderbird.core.preference.DefaultPreferenceChangeBroker
import net.thunderbird.core.preference.GeneralSettingsManager
import net.thunderbird.core.preference.PreferenceChangeBroker
import net.thunderbird.core.preference.PreferenceChangePublisher
import net.thunderbird.core.preference.privacy.DefaultPrivacySettingsManager
import net.thunderbird.core.preference.privacy.DefaultPrivacySettingsPreferenceManager
import net.thunderbird.core.preference.privacy.PrivacySettingsManager
import net.thunderbird.core.preference.privacy.PrivacySettingsPreferenceManager
import net.thunderbird.feature.mail.account.api.AccountManager
import org.koin.core.qualifier.named
import org.koin.dsl.bind
Expand All @@ -26,11 +30,20 @@ val preferencesModule = module {
factory { FolderSettingsProvider(folderRepository = get()) }
factory<LegacyAccountManager> { get<Preferences>() }
factory<AccountManager<*>> { get<LegacyAccountManager>() }
single<PrivacySettingsPreferenceManager> {
DefaultPrivacySettingsPreferenceManager(
storage = get<Preferences>().storage,
storageEditor = get<Preferences>().createStorageEditor(),
changeBroker = get(),
)
}
single<PrivacySettingsManager> { DefaultPrivacySettingsManager(preferenceManager = get()) }
single {
RealGeneralSettingsManager(
preferences = get(),
coroutineScope = get(named("AppCoroutineScope")),
changePublisher = get(),
privacySettingsManager = get(),
)
} bind GeneralSettingsManager::class
single {
Expand Down
Loading