Merge pull request #5902 from k9mail/convert_to_kotlin
Convert some classes to Kotlin
This commit is contained in:
commit
c61b097f8b
19 changed files with 967 additions and 1446 deletions
File diff suppressed because it is too large
Load diff
703
app/core/src/main/java/com/fsck/k9/Account.kt
Normal file
703
app/core/src/main/java/com/fsck/k9/Account.kt
Normal file
|
@ -0,0 +1,703 @@
|
|||
package com.fsck.k9
|
||||
|
||||
import com.fsck.k9.backend.api.SyncConfig.ExpungePolicy
|
||||
import com.fsck.k9.mail.Address
|
||||
import com.fsck.k9.mail.NetworkType
|
||||
import com.fsck.k9.mail.ServerSettings
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* Account stores all of the settings for a single account defined by the user. Each account is defined by a UUID.
|
||||
*/
|
||||
class Account(override val uuid: String) : BaseAccount {
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var deletePolicy = DeletePolicy.NEVER
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
private var internalIncomingServerSettings: ServerSettings? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
private var internalOutgoingServerSettings: ServerSettings? = null
|
||||
|
||||
var incomingServerSettings: ServerSettings
|
||||
get() = internalIncomingServerSettings ?: error("Incoming server settings not set yet")
|
||||
set(value) {
|
||||
internalIncomingServerSettings = value
|
||||
}
|
||||
|
||||
var outgoingServerSettings: ServerSettings
|
||||
get() = internalOutgoingServerSettings ?: error("Outgoing server settings not set yet")
|
||||
set(value) {
|
||||
internalOutgoingServerSettings = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage provider ID, used to locate and manage the underlying DB/file storage.
|
||||
*/
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var localStorageProviderId: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
override var name: String? = null
|
||||
set(value) {
|
||||
field = value?.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var alwaysBcc: String? = null
|
||||
|
||||
/**
|
||||
* -1 for never.
|
||||
*/
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var automaticCheckIntervalMinutes = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var displayCount = 0
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
field = value.takeIf { it != -1 } ?: K9.DEFAULT_VISIBLE_LIMIT
|
||||
isChangedVisibleLimits = true
|
||||
}
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var chipColor = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isNotifyNewMail = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var folderNotifyNewMailMode = FolderMode.ALL
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isNotifySelfNewMail = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isNotifyContactsMailOnly = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isIgnoreChatMessages = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var legacyInboxFolder: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var importedDraftsFolder: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var importedSentFolder: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var importedTrashFolder: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var importedArchiveFolder: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var importedSpamFolder: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var inboxFolderId: Long? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var outboxFolderId: Long? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var draftsFolderId: Long? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var sentFolderId: Long? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var trashFolderId: Long? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var archiveFolderId: Long? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var spamFolderId: Long? = null
|
||||
|
||||
@get:Synchronized
|
||||
var draftsFolderSelection = SpecialFolderSelection.AUTOMATIC
|
||||
private set
|
||||
|
||||
@get:Synchronized
|
||||
var sentFolderSelection = SpecialFolderSelection.AUTOMATIC
|
||||
private set
|
||||
|
||||
@get:Synchronized
|
||||
var trashFolderSelection = SpecialFolderSelection.AUTOMATIC
|
||||
private set
|
||||
|
||||
@get:Synchronized
|
||||
var archiveFolderSelection = SpecialFolderSelection.AUTOMATIC
|
||||
private set
|
||||
|
||||
@get:Synchronized
|
||||
var spamFolderSelection = SpecialFolderSelection.AUTOMATIC
|
||||
private set
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var importedAutoExpandFolder: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var autoExpandFolderId: Long? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var folderDisplayMode = FolderMode.NOT_SECOND_CLASS
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var folderSyncMode = FolderMode.FIRST_CLASS
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var folderPushMode = FolderMode.NONE
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var folderTargetMode = FolderMode.NOT_SECOND_CLASS
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var accountNumber = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isNotifySync = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var sortType: SortType = SortType.SORT_DATE
|
||||
|
||||
private val sortAscending: MutableMap<SortType, Boolean> = mutableMapOf()
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var showPictures = ShowPictures.NEVER
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isSignatureBeforeQuotedText = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var expungePolicy = Expunge.EXPUNGE_IMMEDIATELY
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var maxPushFolders = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var idleRefreshMinutes = 0
|
||||
|
||||
private val compressionMap: MutableMap<NetworkType, Boolean> = ConcurrentHashMap()
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var searchableFolders = Searchable.ALL
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isSubscribedFoldersOnly = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var maximumPolledMessageAge = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var maximumAutoDownloadMessageSize = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var messageFormat = MessageFormat.HTML
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isMessageFormatAuto = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isMessageReadReceipt = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var quoteStyle = QuoteStyle.PREFIX
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var quotePrefix: String? = null
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isDefaultQuotedTextShown = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isReplyAfterQuote = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isStripSignature = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isSyncRemoteDeletions = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var openPgpProvider: String? = null
|
||||
set(value) {
|
||||
field = value?.takeIf { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var openPgpKey: Long = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var autocryptPreferEncryptMutual = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isOpenPgpHideSignOnly = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isOpenPgpEncryptSubject = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isOpenPgpEncryptAllDrafts = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isMarkMessageAsReadOnView = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isMarkMessageAsReadOnDelete = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isAlwaysShowCcBcc = false
|
||||
|
||||
// Temporarily disabled
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isRemoteSearchFullText = false
|
||||
get() = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var remoteSearchNumResults = 0
|
||||
set(value) {
|
||||
field = value.coerceAtLeast(0)
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isUploadSentMessages = false
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var lastSyncTime: Long = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var lastFolderListRefreshTime: Long = 0
|
||||
|
||||
@get:Synchronized
|
||||
var isFinishedSetup = false
|
||||
private set
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var messagesNotificationChannelVersion = 0
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var isChangedVisibleLimits = false
|
||||
private set
|
||||
|
||||
/**
|
||||
* Database ID of the folder that was last selected for a copy or move operation.
|
||||
*
|
||||
* Note: For now this value isn't persisted. So it will be reset when K-9 Mail is restarted.
|
||||
*/
|
||||
@get:Synchronized
|
||||
var lastSelectedFolderId: Long? = null
|
||||
private set
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var identities: MutableList<Identity> = mutableListOf()
|
||||
set(value) {
|
||||
field = value.toMutableList()
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
var notificationSettings = NotificationSettings()
|
||||
private set
|
||||
|
||||
val displayName: String
|
||||
get() = name ?: email
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
override var email: String
|
||||
get() = identities[0].email!!
|
||||
set(email) {
|
||||
val newIdentity = identities[0].withEmail(email)
|
||||
identities[0] = newIdentity
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var senderName: String?
|
||||
get() = identities[0].name
|
||||
set(name) {
|
||||
val newIdentity = identities[0].withName(name)
|
||||
identities[0] = newIdentity
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var signatureUse: Boolean
|
||||
get() = identities[0].signatureUse
|
||||
set(signatureUse) {
|
||||
val newIdentity = identities[0].withSignatureUse(signatureUse)
|
||||
identities[0] = newIdentity
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var signature: String?
|
||||
get() = identities[0].signature
|
||||
set(signature) {
|
||||
val newIdentity = identities[0].withSignature(signature)
|
||||
identities[0] = newIdentity
|
||||
}
|
||||
|
||||
/**
|
||||
* @param automaticCheckIntervalMinutes or -1 for never.
|
||||
*/
|
||||
@Synchronized
|
||||
fun updateAutomaticCheckIntervalMinutes(automaticCheckIntervalMinutes: Int): Boolean {
|
||||
val oldInterval = this.automaticCheckIntervalMinutes
|
||||
this.automaticCheckIntervalMinutes = automaticCheckIntervalMinutes
|
||||
|
||||
return oldInterval != automaticCheckIntervalMinutes
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun setDraftsFolderId(folderId: Long?, selection: SpecialFolderSelection) {
|
||||
draftsFolderId = folderId
|
||||
draftsFolderSelection = selection
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun hasDraftsFolder(): Boolean {
|
||||
return draftsFolderId != null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun setSentFolderId(folderId: Long?, selection: SpecialFolderSelection) {
|
||||
sentFolderId = folderId
|
||||
sentFolderSelection = selection
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun hasSentFolder(): Boolean {
|
||||
return sentFolderId != null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun setTrashFolderId(folderId: Long?, selection: SpecialFolderSelection) {
|
||||
trashFolderId = folderId
|
||||
trashFolderSelection = selection
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun hasTrashFolder(): Boolean {
|
||||
return trashFolderId != null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun setArchiveFolderId(folderId: Long?, selection: SpecialFolderSelection) {
|
||||
archiveFolderId = folderId
|
||||
archiveFolderSelection = selection
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun hasArchiveFolder(): Boolean {
|
||||
return archiveFolderId != null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun setSpamFolderId(folderId: Long?, selection: SpecialFolderSelection) {
|
||||
spamFolderId = folderId
|
||||
spamFolderSelection = selection
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun hasSpamFolder(): Boolean {
|
||||
return spamFolderId != null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun updateFolderSyncMode(syncMode: FolderMode): Boolean {
|
||||
val oldSyncMode = folderSyncMode
|
||||
folderSyncMode = syncMode
|
||||
|
||||
return (oldSyncMode == FolderMode.NONE && syncMode != FolderMode.NONE) ||
|
||||
(oldSyncMode != FolderMode.NONE && syncMode == FolderMode.NONE)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun incrementMessagesNotificationChannelVersion() {
|
||||
messagesNotificationChannelVersion++
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun isSortAscending(sortType: SortType): Boolean {
|
||||
return sortAscending.getOrPut(sortType) { sortType.isDefaultAscending }
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun setSortAscending(sortType: SortType, sortAscending: Boolean) {
|
||||
this.sortAscending[sortType] = sortAscending
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun setCompression(networkType: NetworkType, useCompression: Boolean) {
|
||||
compressionMap[networkType] = useCompression
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun useCompression(networkType: NetworkType): Boolean {
|
||||
return compressionMap[networkType] ?: return true
|
||||
}
|
||||
|
||||
fun getCompressionMap(): Map<NetworkType, Boolean> {
|
||||
return compressionMap.toMap()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun replaceIdentities(identities: List<Identity>) {
|
||||
this.identities = identities.toMutableList()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun getIdentity(index: Int): Identity {
|
||||
if (index !in identities.indices) error("Identity with index $index not found")
|
||||
|
||||
return identities[index]
|
||||
}
|
||||
|
||||
fun isAnIdentity(addresses: Array<Address>?): Boolean {
|
||||
if (addresses == null) return false
|
||||
|
||||
return addresses.any { address -> isAnIdentity(address) }
|
||||
}
|
||||
|
||||
fun isAnIdentity(address: Address): Boolean {
|
||||
return findIdentity(address) != null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun findIdentity(address: Address): Identity? {
|
||||
return identities.find { identity ->
|
||||
identity.email.equals(address.address, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
|
||||
val earliestPollDate: Date?
|
||||
get() {
|
||||
val age = maximumPolledMessageAge.takeIf { it >= 0 } ?: return null
|
||||
|
||||
val now = Calendar.getInstance()
|
||||
now[Calendar.HOUR_OF_DAY] = 0
|
||||
now[Calendar.MINUTE] = 0
|
||||
now[Calendar.SECOND] = 0
|
||||
now[Calendar.MILLISECOND] = 0
|
||||
|
||||
if (age < 28) {
|
||||
now.add(Calendar.DATE, age * -1)
|
||||
} else when (age) {
|
||||
28 -> now.add(Calendar.MONTH, -1)
|
||||
56 -> now.add(Calendar.MONTH, -2)
|
||||
84 -> now.add(Calendar.MONTH, -3)
|
||||
168 -> now.add(Calendar.MONTH, -6)
|
||||
365 -> now.add(Calendar.YEAR, -1)
|
||||
}
|
||||
|
||||
return now.time
|
||||
}
|
||||
|
||||
val isOpenPgpProviderConfigured: Boolean
|
||||
get() = openPgpProvider != null
|
||||
|
||||
@Synchronized
|
||||
fun hasOpenPgpKey(): Boolean {
|
||||
return openPgpKey != NO_OPENPGP_KEY
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun setLastSelectedFolderId(folderId: Long) {
|
||||
lastSelectedFolderId = folderId
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun resetChangeMarkers() {
|
||||
isChangedVisibleLimits = false
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun markSetupFinished() {
|
||||
isFinishedSetup = true
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun updateNotificationSettings(block: (oldNotificationSettings: NotificationSettings) -> NotificationSettings) {
|
||||
notificationSettings = block(notificationSettings)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return if (K9.isSensitiveDebugLoggingEnabled) displayName else uuid
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return if (other is Account) {
|
||||
other.uuid == uuid
|
||||
} else {
|
||||
super.equals(other)
|
||||
}
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return uuid.hashCode()
|
||||
}
|
||||
|
||||
enum class FolderMode {
|
||||
NONE,
|
||||
ALL,
|
||||
FIRST_CLASS,
|
||||
FIRST_AND_SECOND_CLASS,
|
||||
NOT_SECOND_CLASS
|
||||
}
|
||||
|
||||
enum class SpecialFolderSelection {
|
||||
AUTOMATIC,
|
||||
MANUAL
|
||||
}
|
||||
|
||||
enum class ShowPictures {
|
||||
NEVER,
|
||||
ALWAYS,
|
||||
ONLY_FROM_CONTACTS
|
||||
}
|
||||
|
||||
enum class Searchable {
|
||||
ALL,
|
||||
DISPLAYABLE,
|
||||
NONE
|
||||
}
|
||||
|
||||
enum class QuoteStyle {
|
||||
PREFIX,
|
||||
HEADER
|
||||
}
|
||||
|
||||
enum class MessageFormat {
|
||||
TEXT,
|
||||
HTML,
|
||||
AUTO
|
||||
}
|
||||
|
||||
enum class Expunge {
|
||||
EXPUNGE_IMMEDIATELY,
|
||||
EXPUNGE_MANUALLY,
|
||||
EXPUNGE_ON_POLL;
|
||||
|
||||
fun toBackendExpungePolicy(): ExpungePolicy = when (this) {
|
||||
EXPUNGE_IMMEDIATELY -> ExpungePolicy.IMMEDIATELY
|
||||
EXPUNGE_MANUALLY -> ExpungePolicy.MANUALLY
|
||||
EXPUNGE_ON_POLL -> ExpungePolicy.ON_POLL
|
||||
}
|
||||
}
|
||||
|
||||
enum class DeletePolicy(@JvmField val setting: Int) {
|
||||
NEVER(0),
|
||||
SEVEN_DAYS(1),
|
||||
ON_DELETE(2),
|
||||
MARK_AS_READ(3);
|
||||
|
||||
companion object {
|
||||
fun fromInt(initialSetting: Int): DeletePolicy {
|
||||
return values().find { it.setting == initialSetting } ?: error("DeletePolicy $initialSetting unknown")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class SortType(val isDefaultAscending: Boolean) {
|
||||
SORT_DATE(false),
|
||||
SORT_ARRIVAL(false),
|
||||
SORT_SUBJECT(true),
|
||||
SORT_SENDER(true),
|
||||
SORT_UNREAD(true),
|
||||
SORT_FLAGGED(true),
|
||||
SORT_ATTACHMENT(true);
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Fixed name of outbox - not actually displayed.
|
||||
*/
|
||||
const val OUTBOX_NAME = "Outbox"
|
||||
|
||||
@JvmField
|
||||
val DEFAULT_SORT_TYPE = SortType.SORT_DATE
|
||||
const val DEFAULT_SORT_ASCENDING = false
|
||||
const val NO_OPENPGP_KEY: Long = 0
|
||||
const val UNASSIGNED_ACCOUNT_NUMBER = -1
|
||||
const val INTERVAL_MINUTES_NEVER = -1
|
||||
const val DEFAULT_SYNC_INTERVAL = 60
|
||||
}
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
package com.fsck.k9
|
||||
|
||||
import com.fsck.k9.Account.DEFAULT_SORT_ASCENDING
|
||||
import com.fsck.k9.Account.DEFAULT_SORT_TYPE
|
||||
import com.fsck.k9.Account.DEFAULT_SYNC_INTERVAL
|
||||
import com.fsck.k9.Account.Companion.DEFAULT_SORT_ASCENDING
|
||||
import com.fsck.k9.Account.Companion.DEFAULT_SORT_TYPE
|
||||
import com.fsck.k9.Account.Companion.DEFAULT_SYNC_INTERVAL
|
||||
import com.fsck.k9.Account.Companion.NO_OPENPGP_KEY
|
||||
import com.fsck.k9.Account.Companion.UNASSIGNED_ACCOUNT_NUMBER
|
||||
import com.fsck.k9.Account.DeletePolicy
|
||||
import com.fsck.k9.Account.Expunge
|
||||
import com.fsck.k9.Account.FolderMode
|
||||
import com.fsck.k9.Account.MessageFormat
|
||||
import com.fsck.k9.Account.NO_OPENPGP_KEY
|
||||
import com.fsck.k9.Account.QuoteStyle
|
||||
import com.fsck.k9.Account.Searchable
|
||||
import com.fsck.k9.Account.ShowPictures
|
||||
import com.fsck.k9.Account.SortType
|
||||
import com.fsck.k9.Account.SpecialFolderSelection
|
||||
import com.fsck.k9.Account.UNASSIGNED_ACCOUNT_NUMBER
|
||||
import com.fsck.k9.helper.Utility
|
||||
import com.fsck.k9.mail.NetworkType
|
||||
import com.fsck.k9.mailstore.StorageManager
|
||||
|
@ -137,16 +137,17 @@ class AccountPreferenceSerializer(
|
|||
|
||||
showPictures = getEnumStringPref<ShowPictures>(storage, "$accountUuid.showPicturesEnum", ShowPictures.NEVER)
|
||||
|
||||
notificationSetting.isVibrateEnabled = storage.getBoolean("$accountUuid.vibrate", false)
|
||||
notificationSetting.vibratePattern = storage.getInt("$accountUuid.vibratePattern", 0)
|
||||
notificationSetting.vibrateTimes = storage.getInt("$accountUuid.vibrateTimes", 5)
|
||||
notificationSetting.isRingEnabled = storage.getBoolean("$accountUuid.ring", true)
|
||||
notificationSetting.ringtone = storage.getString(
|
||||
"$accountUuid.ringtone",
|
||||
"content://settings/system/notification_sound"
|
||||
)
|
||||
notificationSetting.setLed(storage.getBoolean("$accountUuid.led", true))
|
||||
notificationSetting.ledColor = storage.getInt("$accountUuid.ledColor", chipColor)
|
||||
updateNotificationSettings {
|
||||
NotificationSettings(
|
||||
isRingEnabled = storage.getBoolean("$accountUuid.ring", true),
|
||||
ringtone = storage.getString("$accountUuid.ringtone", DEFAULT_RINGTONE_URI),
|
||||
isLedEnabled = storage.getBoolean("$accountUuid.led", true),
|
||||
ledColor = storage.getInt("$accountUuid.ledColor", chipColor),
|
||||
isVibrateEnabled = storage.getBoolean("$accountUuid.vibrate", false),
|
||||
vibratePattern = VibratePattern.deserialize(storage.getInt("$accountUuid.vibratePattern", 0)),
|
||||
vibrateTimes = storage.getInt("$accountUuid.vibrateTimes", 5)
|
||||
)
|
||||
}
|
||||
|
||||
folderDisplayMode = getEnumStringPref<FolderMode>(storage, "$accountUuid.folderDisplayMode", FolderMode.NOT_SECOND_CLASS)
|
||||
|
||||
|
@ -159,7 +160,7 @@ class AccountPreferenceSerializer(
|
|||
searchableFolders = getEnumStringPref<Searchable>(storage, "$accountUuid.searchableFolders", Searchable.ALL)
|
||||
|
||||
isSignatureBeforeQuotedText = storage.getBoolean("$accountUuid.signatureBeforeQuotedText", false)
|
||||
identities = loadIdentities(accountUuid, storage)
|
||||
replaceIdentities(loadIdentities(accountUuid, storage))
|
||||
|
||||
openPgpProvider = storage.getString("$accountUuid.openPgpProvider", "")
|
||||
openPgpKey = storage.getLong("$accountUuid.cryptoKey", NO_OPENPGP_KEY)
|
||||
|
@ -322,17 +323,18 @@ class AccountPreferenceSerializer(
|
|||
editor.putBoolean("$accountUuid.markMessageAsReadOnDelete", isMarkMessageAsReadOnDelete)
|
||||
editor.putBoolean("$accountUuid.alwaysShowCcBcc", isAlwaysShowCcBcc)
|
||||
|
||||
editor.putBoolean("$accountUuid.vibrate", notificationSetting.isVibrateEnabled)
|
||||
editor.putInt("$accountUuid.vibratePattern", notificationSetting.vibratePattern)
|
||||
editor.putInt("$accountUuid.vibrateTimes", notificationSetting.vibrateTimes)
|
||||
editor.putBoolean("$accountUuid.ring", notificationSetting.isRingEnabled)
|
||||
editor.putString("$accountUuid.ringtone", notificationSetting.ringtone)
|
||||
editor.putBoolean("$accountUuid.led", notificationSetting.isLedEnabled)
|
||||
editor.putInt("$accountUuid.ledColor", notificationSetting.ledColor)
|
||||
editor.putBoolean("$accountUuid.vibrate", notificationSettings.isVibrateEnabled)
|
||||
editor.putInt("$accountUuid.vibratePattern", notificationSettings.vibratePattern.serialize())
|
||||
editor.putInt("$accountUuid.vibrateTimes", notificationSettings.vibrateTimes)
|
||||
editor.putBoolean("$accountUuid.ring", notificationSettings.isRingEnabled)
|
||||
editor.putString("$accountUuid.ringtone", notificationSettings.ringtone)
|
||||
editor.putBoolean("$accountUuid.led", notificationSettings.isLedEnabled)
|
||||
editor.putInt("$accountUuid.ledColor", notificationSettings.ledColor)
|
||||
editor.putLong("$accountUuid.lastSyncTime", lastSyncTime)
|
||||
editor.putLong("$accountUuid.lastFolderListRefreshTime", lastFolderListRefreshTime)
|
||||
editor.putBoolean("$accountUuid.isFinishedSetup", isFinishedSetup)
|
||||
|
||||
val compressionMap = getCompressionMap()
|
||||
for (type in NetworkType.values()) {
|
||||
val useCompression = compressionMap[type]
|
||||
if (useCompression != null) {
|
||||
|
@ -603,13 +605,16 @@ class AccountPreferenceSerializer(
|
|||
)
|
||||
identities.add(identity)
|
||||
|
||||
with(notificationSetting) {
|
||||
isVibrateEnabled = false
|
||||
vibratePattern = 0
|
||||
vibrateTimes = 5
|
||||
isRingEnabled = true
|
||||
ringtone = "content://settings/system/notification_sound"
|
||||
ledColor = chipColor
|
||||
updateNotificationSettings {
|
||||
NotificationSettings(
|
||||
isRingEnabled = true,
|
||||
ringtone = DEFAULT_RINGTONE_URI,
|
||||
isLedEnabled = false,
|
||||
ledColor = chipColor,
|
||||
isVibrateEnabled = false,
|
||||
vibratePattern = VibratePattern.Default,
|
||||
vibrateTimes = 5
|
||||
)
|
||||
}
|
||||
|
||||
resetChangeMarkers()
|
||||
|
@ -639,5 +644,6 @@ class AccountPreferenceSerializer(
|
|||
const val DEFAULT_REPLY_AFTER_QUOTE = false
|
||||
const val DEFAULT_STRIP_SIGNATURE = true
|
||||
const val DEFAULT_REMOTE_SEARCH_NUM_RESULTS = 25
|
||||
const val DEFAULT_RINGTONE_URI = "content://settings/system/notification_sound"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
package com.fsck.k9;
|
||||
|
||||
public interface BaseAccount {
|
||||
String getEmail();
|
||||
String getName();
|
||||
String getUuid();
|
||||
}
|
7
app/core/src/main/java/com/fsck/k9/BaseAccount.kt
Normal file
7
app/core/src/main/java/com/fsck/k9/BaseAccount.kt
Normal file
|
@ -0,0 +1,7 @@
|
|||
package com.fsck.k9
|
||||
|
||||
interface BaseAccount {
|
||||
val uuid: String
|
||||
val name: String?
|
||||
val email: String
|
||||
}
|
|
@ -1,138 +0,0 @@
|
|||
package com.fsck.k9;
|
||||
|
||||
/**
|
||||
* Describes how a notification should behave.
|
||||
*/
|
||||
public class NotificationSetting {
|
||||
private boolean ringEnabled;
|
||||
private String ringtoneUri;
|
||||
|
||||
private boolean ledEnabled;
|
||||
private int ledColor;
|
||||
|
||||
private boolean vibrateEnabled;
|
||||
|
||||
private int vibratePattern;
|
||||
private int vibrateTimes;
|
||||
|
||||
/**
|
||||
* Set the ringtone kill switch. Allow to disable ringtone without losing
|
||||
* ringtone selection.
|
||||
*
|
||||
* @param ringEnabled
|
||||
* <code>true</code> to allow ringtones, <code>false</code>
|
||||
* otherwise.
|
||||
*/
|
||||
public synchronized void setRingEnabled(boolean ringEnabled) {
|
||||
this.ringEnabled = ringEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if ringtone is allowed to play,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public synchronized boolean isRingEnabled() {
|
||||
return ringEnabled;
|
||||
}
|
||||
|
||||
public synchronized String getRingtone() {
|
||||
return ringtoneUri;
|
||||
}
|
||||
|
||||
public synchronized void setRingtone(String ringtoneUri) {
|
||||
this.ringtoneUri = ringtoneUri;
|
||||
}
|
||||
|
||||
public synchronized boolean isLedEnabled() {
|
||||
return ledEnabled;
|
||||
}
|
||||
|
||||
public synchronized void setLed(final boolean led) {
|
||||
ledEnabled = led;
|
||||
}
|
||||
|
||||
public synchronized int getLedColor() {
|
||||
return ledColor;
|
||||
}
|
||||
|
||||
public synchronized void setLedColor(int color) {
|
||||
ledColor = color;
|
||||
}
|
||||
|
||||
public synchronized boolean isVibrateEnabled() {
|
||||
return vibrateEnabled;
|
||||
}
|
||||
|
||||
public synchronized void setVibrateEnabled(boolean vibrate) {
|
||||
vibrateEnabled = vibrate;
|
||||
}
|
||||
|
||||
public synchronized int getVibratePattern() {
|
||||
return vibratePattern;
|
||||
}
|
||||
|
||||
public synchronized int getVibrateTimes() {
|
||||
return vibrateTimes;
|
||||
}
|
||||
|
||||
public synchronized void setVibratePattern(int pattern) {
|
||||
vibratePattern = pattern;
|
||||
}
|
||||
|
||||
public synchronized void setVibrateTimes(int times) {
|
||||
vibrateTimes = times;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Fetch a vibration pattern.
|
||||
*
|
||||
* @param vibratePattern Vibration pattern index to use.
|
||||
* @param vibrateTimes Number of times to do the vibration pattern.
|
||||
* @return Pattern multiplied by the number of times requested.
|
||||
*/
|
||||
|
||||
public long[] getVibration() {
|
||||
return getVibration(vibratePattern, vibrateTimes);
|
||||
}
|
||||
|
||||
public static long[] getVibration(int pattern, int times) {
|
||||
// These are "off, on" patterns, specified in milliseconds
|
||||
long[] pattern0 = new long[] {300, 200}; // like the default pattern
|
||||
long[] pattern1 = new long[] {100, 200};
|
||||
long[] pattern2 = new long[] {100, 500};
|
||||
long[] pattern3 = new long[] {200, 200};
|
||||
long[] pattern4 = new long[] {200, 500};
|
||||
long[] pattern5 = new long[] {500, 500};
|
||||
|
||||
long[] selectedPattern = pattern0; //default pattern
|
||||
|
||||
switch (pattern) {
|
||||
case 1:
|
||||
selectedPattern = pattern1;
|
||||
break;
|
||||
case 2:
|
||||
selectedPattern = pattern2;
|
||||
break;
|
||||
case 3:
|
||||
selectedPattern = pattern3;
|
||||
break;
|
||||
case 4:
|
||||
selectedPattern = pattern4;
|
||||
break;
|
||||
case 5:
|
||||
selectedPattern = pattern5;
|
||||
break;
|
||||
}
|
||||
|
||||
long[] repeatedPattern = new long[selectedPattern.length * times];
|
||||
for (int n = 0; n < times; n++) {
|
||||
System.arraycopy(selectedPattern, 0, repeatedPattern, n * selectedPattern.length, selectedPattern.length);
|
||||
}
|
||||
// Do not wait before starting the vibration pattern.
|
||||
repeatedPattern[0] = 0;
|
||||
return repeatedPattern;
|
||||
}
|
||||
|
||||
}
|
67
app/core/src/main/java/com/fsck/k9/NotificationSettings.kt
Normal file
67
app/core/src/main/java/com/fsck/k9/NotificationSettings.kt
Normal file
|
@ -0,0 +1,67 @@
|
|||
package com.fsck.k9
|
||||
|
||||
/**
|
||||
* Describes how a notification should behave.
|
||||
*/
|
||||
data class NotificationSettings(
|
||||
val isRingEnabled: Boolean = false,
|
||||
val ringtone: String? = null,
|
||||
val isLedEnabled: Boolean = false,
|
||||
val ledColor: Int = 0,
|
||||
val isVibrateEnabled: Boolean = false,
|
||||
val vibratePattern: VibratePattern = VibratePattern.Default,
|
||||
val vibrateTimes: Int = 0
|
||||
) {
|
||||
val vibrationPattern: LongArray
|
||||
get() = getVibrationPattern(vibratePattern, vibrateTimes)
|
||||
|
||||
companion object {
|
||||
fun getVibrationPattern(vibratePattern: VibratePattern, times: Int): LongArray {
|
||||
val selectedPattern = vibratePattern.vibrationPattern
|
||||
val repeatedPattern = LongArray(selectedPattern.size * times)
|
||||
for (n in 0 until times) {
|
||||
System.arraycopy(selectedPattern, 0, repeatedPattern, n * selectedPattern.size, selectedPattern.size)
|
||||
}
|
||||
|
||||
// Do not wait before starting the vibration pattern.
|
||||
repeatedPattern[0] = 0
|
||||
|
||||
return repeatedPattern
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class VibratePattern(
|
||||
/**
|
||||
* These are "off, on" patterns, specified in milliseconds.
|
||||
*/
|
||||
val vibrationPattern: LongArray
|
||||
) {
|
||||
Default(vibrationPattern = longArrayOf(300, 200)),
|
||||
Pattern1(vibrationPattern = longArrayOf(100, 200)),
|
||||
Pattern2(vibrationPattern = longArrayOf(100, 500)),
|
||||
Pattern3(vibrationPattern = longArrayOf(200, 200)),
|
||||
Pattern4(vibrationPattern = longArrayOf(200, 500)),
|
||||
Pattern5(vibrationPattern = longArrayOf(500, 500));
|
||||
|
||||
fun serialize(): Int = when (this) {
|
||||
Default -> 0
|
||||
Pattern1 -> 1
|
||||
Pattern2 -> 2
|
||||
Pattern3 -> 3
|
||||
Pattern4 -> 4
|
||||
Pattern5 -> 5
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun deserialize(value: Int): VibratePattern = when (value) {
|
||||
0 -> Default
|
||||
1 -> Pattern1
|
||||
2 -> Pattern2
|
||||
3 -> Pattern3
|
||||
4 -> Pattern4
|
||||
5 -> Pattern5
|
||||
else -> error("Unknown VibratePattern value: $value")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,8 +40,8 @@ internal class BaseNotificationDataCreator {
|
|||
}
|
||||
|
||||
private fun createNotificationAppearance(account: Account): NotificationAppearance {
|
||||
return with(account.notificationSetting) {
|
||||
val vibrationPattern = if (isVibrateEnabled) vibration else null
|
||||
return with(account.notificationSettings) {
|
||||
val vibrationPattern = if (isVibrateEnabled) vibrationPattern else null
|
||||
NotificationAppearance(ringtone, vibrationPattern, ledColor)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import android.app.NotificationManager
|
|||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.fsck.k9.Account
|
||||
import com.fsck.k9.NotificationSetting
|
||||
import com.fsck.k9.NotificationSettings
|
||||
import com.fsck.k9.Preferences
|
||||
import java.util.concurrent.Executor
|
||||
import timber.log.Timber
|
||||
|
@ -165,7 +165,7 @@ class NotificationChannelManager(
|
|||
val oldChannelId = getChannelIdFor(account, ChannelType.MESSAGES)
|
||||
val oldNotificationChannel = notificationManager.getNotificationChannel(oldChannelId)
|
||||
|
||||
if (oldNotificationChannel.matches(account.notificationSetting)) {
|
||||
if (oldNotificationChannel.matches(account.notificationSettings)) {
|
||||
Timber.v("Not recreating NotificationChannel. The current one already matches the app's settings.")
|
||||
return
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ class NotificationChannelManager(
|
|||
group = account.uuid
|
||||
|
||||
copyPropertiesFrom(oldNotificationChannel)
|
||||
copyPropertiesFrom(account.notificationSetting)
|
||||
copyPropertiesFrom(account.notificationSettings)
|
||||
}
|
||||
|
||||
Timber.v("Recreating NotificationChannel(%s => %s)", oldChannelId, newChannelId)
|
||||
|
@ -191,10 +191,10 @@ class NotificationChannelManager(
|
|||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun NotificationChannel.matches(notificationSetting: NotificationSetting): Boolean {
|
||||
return lightColor == notificationSetting.ledColor &&
|
||||
shouldVibrate() == notificationSetting.isVibrateEnabled &&
|
||||
vibrationPattern.contentEquals(notificationSetting.vibration)
|
||||
private fun NotificationChannel.matches(notificationSettings: NotificationSettings): Boolean {
|
||||
return lightColor == notificationSettings.ledColor &&
|
||||
shouldVibrate() == notificationSettings.isVibrateEnabled &&
|
||||
vibrationPattern.contentEquals(notificationSettings.vibrationPattern)
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
|
@ -211,10 +211,10 @@ class NotificationChannelManager(
|
|||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun NotificationChannel.copyPropertiesFrom(notificationSetting: NotificationSetting) {
|
||||
lightColor = notificationSetting.ledColor
|
||||
vibrationPattern = notificationSetting.vibration
|
||||
enableVibration(notificationSetting.isVibrateEnabled)
|
||||
private fun NotificationChannel.copyPropertiesFrom(notificationSettings: NotificationSettings) {
|
||||
lightColor = notificationSettings.ledColor
|
||||
vibrationPattern = notificationSettings.vibrationPattern
|
||||
enableVibration(notificationSettings.isVibrateEnabled)
|
||||
}
|
||||
|
||||
private val Account.messagesNotificationChannelSuffix: String
|
||||
|
|
|
@ -41,7 +41,7 @@ internal class SyncNotificationController(
|
|||
builder = notificationBuilder,
|
||||
ringtone = null,
|
||||
vibrationPattern = null,
|
||||
ledColor = account.notificationSetting.ledColor,
|
||||
ledColor = account.notificationSettings.ledColor,
|
||||
ledSpeed = NotificationHelper.NOTIFICATION_LED_BLINK_FAST,
|
||||
ringAndVibrate = true
|
||||
)
|
||||
|
@ -88,7 +88,7 @@ internal class SyncNotificationController(
|
|||
builder = notificationBuilder,
|
||||
ringtone = null,
|
||||
vibrationPattern = null,
|
||||
ledColor = account.notificationSetting.ledColor,
|
||||
ledColor = account.notificationSettings.ledColor,
|
||||
ledSpeed = NotificationHelper.NOTIFICATION_LED_BLINK_FAST,
|
||||
ringAndVibrate = true
|
||||
)
|
||||
|
@ -118,7 +118,7 @@ internal class SyncNotificationController(
|
|||
builder = notificationBuilder,
|
||||
ringtone = null,
|
||||
vibrationPattern = null,
|
||||
ledColor = account.notificationSetting.ledColor,
|
||||
ledColor = account.notificationSettings.ledColor,
|
||||
ledSpeed = NotificationHelper.NOTIFICATION_LED_BLINK_FAST,
|
||||
ringAndVibrate = true
|
||||
)
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
package com.fsck.k9.search;
|
||||
|
||||
|
||||
import com.fsck.k9.BaseAccount;
|
||||
import com.fsck.k9.CoreResourceProvider;
|
||||
import com.fsck.k9.DI;
|
||||
import com.fsck.k9.search.SearchSpecification.Attribute;
|
||||
import com.fsck.k9.search.SearchSpecification.SearchField;
|
||||
|
||||
|
||||
/**
|
||||
* This class is basically a wrapper around a LocalSearch. It allows to expose it as
|
||||
* an account. This is a meta-account containing all the email that matches the search.
|
||||
*/
|
||||
public class SearchAccount implements BaseAccount {
|
||||
public static final String UNIFIED_INBOX = "unified_inbox";
|
||||
public static final String NEW_MESSAGES = "new_messages";
|
||||
|
||||
|
||||
// create the unified inbox meta account ( all accounts is default when none specified )
|
||||
public static SearchAccount createUnifiedInboxAccount() {
|
||||
CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
|
||||
LocalSearch tmpSearch = new LocalSearch();
|
||||
tmpSearch.setId(UNIFIED_INBOX);
|
||||
tmpSearch.and(SearchField.INTEGRATE, "1", Attribute.EQUALS);
|
||||
return new SearchAccount(UNIFIED_INBOX, tmpSearch, resourceProvider.searchUnifiedInboxTitle(),
|
||||
resourceProvider.searchUnifiedInboxDetail());
|
||||
}
|
||||
|
||||
private String mId;
|
||||
private String mEmail;
|
||||
private String name;
|
||||
private LocalSearch mSearch;
|
||||
|
||||
public SearchAccount(String id, LocalSearch search, String name, String email)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
if (search == null) {
|
||||
throw new IllegalArgumentException("Provided LocalSearch was null");
|
||||
}
|
||||
|
||||
mId = id;
|
||||
mSearch = search;
|
||||
this.name = name;
|
||||
mEmail = email;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String getEmail() {
|
||||
return mEmail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public LocalSearch getRelatedSearch() {
|
||||
return mSearch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of this {@code SearchAccount} instance.
|
||||
*
|
||||
* <p>
|
||||
* This isn't really a UUID. But since we don't expose this value to other apps and we only
|
||||
* use the account UUID as opaque string (e.g. as key in a {@code Map}) we're fine.<br>
|
||||
* Using a constant string is necessary to identify the same search account even when the
|
||||
* corresponding {@link SearchAccount} object has been recreated.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return mId;
|
||||
}
|
||||
}
|
53
app/core/src/main/java/com/fsck/k9/search/SearchAccount.kt
Normal file
53
app/core/src/main/java/com/fsck/k9/search/SearchAccount.kt
Normal file
|
@ -0,0 +1,53 @@
|
|||
package com.fsck.k9.search
|
||||
|
||||
import com.fsck.k9.BaseAccount
|
||||
import com.fsck.k9.CoreResourceProvider
|
||||
import com.fsck.k9.search.SearchSpecification.SearchField
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
/**
|
||||
* This class is basically a wrapper around a LocalSearch. It allows to expose it as an account.
|
||||
* This is a meta-account containing all the messages that match the search.
|
||||
*/
|
||||
class SearchAccount(
|
||||
val id: String,
|
||||
search: LocalSearch,
|
||||
override val name: String,
|
||||
override val email: String
|
||||
) : BaseAccount {
|
||||
/**
|
||||
* Returns the ID of this `SearchAccount` instance.
|
||||
*
|
||||
* This isn't really a UUID. But since we don't expose this value to other apps and we only use the account UUID
|
||||
* as opaque string (e.g. as key in a `Map`) we're fine.
|
||||
*
|
||||
* Using a constant string is necessary to identify the same search account even when the corresponding
|
||||
* [SearchAccount] object has been recreated.
|
||||
*/
|
||||
override val uuid: String = id
|
||||
|
||||
val relatedSearch: LocalSearch = search
|
||||
|
||||
companion object : KoinComponent {
|
||||
private val resourceProvider: CoreResourceProvider by inject()
|
||||
|
||||
const val UNIFIED_INBOX = "unified_inbox"
|
||||
const val NEW_MESSAGES = "new_messages"
|
||||
|
||||
@JvmStatic
|
||||
fun createUnifiedInboxAccount(): SearchAccount {
|
||||
val tmpSearch = LocalSearch().apply {
|
||||
id = UNIFIED_INBOX
|
||||
and(SearchField.INTEGRATE, "1", SearchSpecification.Attribute.EQUALS)
|
||||
}
|
||||
|
||||
return SearchAccount(
|
||||
id = UNIFIED_INBOX,
|
||||
search = tmpSearch,
|
||||
name = resourceProvider.searchUnifiedInboxTitle(),
|
||||
email = resourceProvider.searchUnifiedInboxDetail()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -115,13 +115,15 @@ class IdentityHelperTest : RobolectricTest() {
|
|||
}
|
||||
|
||||
private fun createDummyAccount() = Account(UUID.randomUUID().toString()).apply {
|
||||
identities = listOf(
|
||||
newIdentity("Default", DEFAULT_ADDRESS),
|
||||
newIdentity("Identity 1", IDENTITY_1_ADDRESS),
|
||||
newIdentity("Identity 2", IDENTITY_2_ADDRESS),
|
||||
newIdentity("Identity 3", IDENTITY_3_ADDRESS),
|
||||
newIdentity("Identity 4", IDENTITY_4_ADDRESS),
|
||||
newIdentity("Identity 5", IDENTITY_5_ADDRESS)
|
||||
replaceIdentities(
|
||||
listOf(
|
||||
newIdentity("Default", DEFAULT_ADDRESS),
|
||||
newIdentity("Identity 1", IDENTITY_1_ADDRESS),
|
||||
newIdentity("Identity 2", IDENTITY_2_ADDRESS),
|
||||
newIdentity("Identity 3", IDENTITY_3_ADDRESS),
|
||||
newIdentity("Identity 4", IDENTITY_4_ADDRESS),
|
||||
newIdentity("Identity 5", IDENTITY_5_ADDRESS)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@ import com.fsck.k9.Account
|
|||
import com.fsck.k9.Identity
|
||||
import com.fsck.k9.K9
|
||||
import com.fsck.k9.K9.LockScreenNotificationVisibility
|
||||
import com.fsck.k9.NotificationSetting
|
||||
import com.fsck.k9.NotificationSettings
|
||||
import com.fsck.k9.VibratePattern
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.mockito.kotlin.mock
|
||||
|
@ -138,7 +139,7 @@ class BaseNotificationDataCreatorTest {
|
|||
|
||||
@Test
|
||||
fun ringtone() {
|
||||
account.notificationSetting.ringtone = "content://ringtone/1"
|
||||
account.updateNotificationSettings { it.copy(ringtone = "content://ringtone/1") }
|
||||
val notificationData = createNotificationData()
|
||||
|
||||
val result = notificationDataCreator.createBaseNotificationData(notificationData)
|
||||
|
@ -148,19 +149,21 @@ class BaseNotificationDataCreatorTest {
|
|||
|
||||
@Test
|
||||
fun `vibration pattern`() {
|
||||
account.notificationSetting.isVibrateEnabled = true
|
||||
account.notificationSetting.vibratePattern = 3
|
||||
account.notificationSetting.vibrateTimes = 2
|
||||
account.updateNotificationSettings {
|
||||
it.copy(isVibrateEnabled = true, vibratePattern = VibratePattern.Pattern3, vibrateTimes = 2)
|
||||
}
|
||||
val notificationData = createNotificationData()
|
||||
|
||||
val result = notificationDataCreator.createBaseNotificationData(notificationData)
|
||||
|
||||
assertThat(result.appearance.vibrationPattern).isEqualTo(NotificationSetting.getVibration(3, 2))
|
||||
assertThat(result.appearance.vibrationPattern).isEqualTo(
|
||||
NotificationSettings.getVibrationPattern(VibratePattern.Pattern3, 2)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `led color`() {
|
||||
account.notificationSetting.ledColor = 0x00FF00
|
||||
account.updateNotificationSettings { it.copy(ledColor = 0x00FF00) }
|
||||
val notificationData = createNotificationData()
|
||||
|
||||
val result = notificationDataCreator.createBaseNotificationData(notificationData)
|
||||
|
@ -192,7 +195,7 @@ class BaseNotificationDataCreatorTest {
|
|||
private fun createAccount(): Account {
|
||||
return Account("00000000-0000-4000-0000-000000000000").apply {
|
||||
name = "account name"
|
||||
identities = listOf(Identity())
|
||||
replaceIdentities(listOf(Identity()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class UnreadWidgetDataProvider(
|
|||
|
||||
private fun loadSearchAccountData(configuration: UnreadWidgetConfiguration): UnreadWidgetData {
|
||||
val searchAccount = getSearchAccount(configuration.accountUuid)
|
||||
val title = searchAccount.name
|
||||
val title = searchAccount.name ?: searchAccount.email
|
||||
val unreadCount = messagingController.getUnreadMessageCount(searchAccount)
|
||||
val clickIntent = MessageList.intentDisplaySearch(context, searchAccount.relatedSearch, false, true, true)
|
||||
|
||||
|
|
|
@ -10,3 +10,8 @@ inline fun <reified T : Enum<T>> Bundle.getEnum(key: String, defaultValue: T): T
|
|||
val value = getString(key) ?: return defaultValue
|
||||
return enumValueOf(value)
|
||||
}
|
||||
|
||||
inline fun <reified T : Enum<T>> Bundle.getEnum(key: String): T {
|
||||
val value = getString(key) ?: error("Missing enum value for key '$key'")
|
||||
return enumValueOf(value)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ class AccountSettingsDataStore(
|
|||
"account_notify" -> account.isNotifyNewMail
|
||||
"account_notify_self" -> account.isNotifySelfNewMail
|
||||
"account_notify_contacts_mail_only" -> account.isNotifyContactsMailOnly
|
||||
"account_led" -> account.notificationSetting.isLedEnabled
|
||||
"account_led" -> account.notificationSettings.isLedEnabled
|
||||
"account_notify_sync" -> account.isNotifySync
|
||||
"openpgp_hide_sign_only" -> account.isOpenPgpHideSignOnly
|
||||
"openpgp_encrypt_subject" -> account.isOpenPgpEncryptSubject
|
||||
|
@ -55,7 +55,7 @@ class AccountSettingsDataStore(
|
|||
"account_notify" -> account.isNotifyNewMail = value
|
||||
"account_notify_self" -> account.isNotifySelfNewMail = value
|
||||
"account_notify_contacts_mail_only" -> account.isNotifyContactsMailOnly = value
|
||||
"account_led" -> account.notificationSetting.setLed(value)
|
||||
"account_led" -> account.updateNotificationSettings { it.copy(isLedEnabled = value) }
|
||||
"account_notify_sync" -> account.isNotifySync = value
|
||||
"openpgp_hide_sign_only" -> account.isOpenPgpHideSignOnly = value
|
||||
"openpgp_encrypt_subject" -> account.isOpenPgpEncryptSubject = value
|
||||
|
@ -72,7 +72,7 @@ class AccountSettingsDataStore(
|
|||
override fun getInt(key: String?, defValue: Int): Int {
|
||||
return when (key) {
|
||||
"chip_color" -> account.chipColor
|
||||
"led_color" -> account.notificationSetting.ledColor
|
||||
"led_color" -> account.notificationSettings.ledColor
|
||||
else -> defValue
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class AccountSettingsDataStore(
|
|||
"folder_notify_new_mail_mode" -> account.folderNotifyNewMailMode.name
|
||||
"account_combined_vibration" -> getCombinedVibrationValue()
|
||||
"account_remote_search_num_results" -> account.remoteSearchNumResults.toString()
|
||||
"account_ringtone" -> account.notificationSetting.ringtone
|
||||
"account_ringtone" -> account.notificationSettings.ringtone
|
||||
else -> defValue
|
||||
}
|
||||
}
|
||||
|
@ -149,12 +149,12 @@ class AccountSettingsDataStore(
|
|||
"account_message_age" -> account.maximumPolledMessageAge = value.toInt()
|
||||
"account_autodownload_size" -> account.maximumAutoDownloadMessageSize = value.toInt()
|
||||
"account_check_frequency" -> {
|
||||
if (account.setAutomaticCheckIntervalMinutes(value.toInt())) {
|
||||
if (account.updateAutomaticCheckIntervalMinutes(value.toInt())) {
|
||||
reschedulePoll()
|
||||
}
|
||||
}
|
||||
"folder_sync_mode" -> {
|
||||
if (account.setFolderSyncMode(Account.FolderMode.valueOf(value))) {
|
||||
if (account.updateFolderSyncMode(Account.FolderMode.valueOf(value))) {
|
||||
reschedulePoll()
|
||||
}
|
||||
}
|
||||
|
@ -178,10 +178,7 @@ class AccountSettingsDataStore(
|
|||
"folder_notify_new_mail_mode" -> account.folderNotifyNewMailMode = Account.FolderMode.valueOf(value)
|
||||
"account_combined_vibration" -> setCombinedVibrationValue(value)
|
||||
"account_remote_search_num_results" -> account.remoteSearchNumResults = value.toInt()
|
||||
"account_ringtone" -> with(account.notificationSetting) {
|
||||
isRingEnabled = true
|
||||
ringtone = value
|
||||
}
|
||||
"account_ringtone" -> account.updateNotificationSettings { it.copy(isRingEnabled = true, ringtone = value) }
|
||||
else -> return
|
||||
}
|
||||
|
||||
|
@ -189,8 +186,8 @@ class AccountSettingsDataStore(
|
|||
}
|
||||
|
||||
private fun setNotificationLightColor(value: Int) {
|
||||
if (account.notificationSetting.ledColor != value) {
|
||||
account.notificationSetting.ledColor = value
|
||||
if (account.notificationSettings.ledColor != value) {
|
||||
account.updateNotificationSettings { it.copy(ledColor = value) }
|
||||
notificationSettingsChanged = true
|
||||
}
|
||||
}
|
||||
|
@ -245,17 +242,21 @@ class AccountSettingsDataStore(
|
|||
|
||||
private fun getCombinedVibrationValue(): String {
|
||||
return VibrationPreference.encode(
|
||||
isVibrationEnabled = account.notificationSetting.isVibrateEnabled,
|
||||
vibrationPattern = account.notificationSetting.vibratePattern,
|
||||
vibrationTimes = account.notificationSetting.vibrateTimes
|
||||
isVibrationEnabled = account.notificationSettings.isVibrateEnabled,
|
||||
vibratePattern = account.notificationSettings.vibratePattern,
|
||||
vibrationTimes = account.notificationSettings.vibrateTimes
|
||||
)
|
||||
}
|
||||
|
||||
private fun setCombinedVibrationValue(value: String) {
|
||||
val (isVibrationEnabled, vibrationPattern, vibrationTimes) = VibrationPreference.decode(value)
|
||||
account.notificationSetting.isVibrateEnabled = isVibrationEnabled
|
||||
account.notificationSetting.vibratePattern = vibrationPattern
|
||||
account.notificationSetting.vibrateTimes = vibrationTimes
|
||||
account.updateNotificationSettings { notificationSettings ->
|
||||
notificationSettings.copy(
|
||||
isVibrateEnabled = isVibrationEnabled,
|
||||
vibratePattern = vibrationPattern,
|
||||
vibrateTimes = vibrationTimes,
|
||||
)
|
||||
}
|
||||
notificationSettingsChanged = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,11 @@ import androidx.appcompat.app.AlertDialog
|
|||
import androidx.appcompat.widget.SwitchCompat
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.preference.PreferenceDialogFragmentCompat
|
||||
import com.fsck.k9.NotificationSetting
|
||||
import com.fsck.k9.NotificationSettings
|
||||
import com.fsck.k9.VibratePattern
|
||||
import com.fsck.k9.ui.R
|
||||
import com.fsck.k9.ui.getEnum
|
||||
import com.fsck.k9.ui.putEnum
|
||||
|
||||
class VibrationDialogFragment : PreferenceDialogFragmentCompat() {
|
||||
private val vibrator by lazy { requireContext().getSystemService<Vibrator>() ?: error("Vibrator service missing") }
|
||||
|
@ -31,15 +34,15 @@ class VibrationDialogFragment : PreferenceDialogFragmentCompat() {
|
|||
val context = requireContext()
|
||||
|
||||
val isVibrationEnabled: Boolean
|
||||
val vibrationPattern: Int
|
||||
val vibratePattern: VibratePattern
|
||||
val vibrationTimes: Int
|
||||
if (savedInstanceState != null) {
|
||||
isVibrationEnabled = savedInstanceState.getBoolean(STATE_VIBRATE)
|
||||
vibrationPattern = savedInstanceState.getInt(STATE_VIBRATION_PATTERN)
|
||||
vibratePattern = savedInstanceState.getEnum(STATE_VIBRATE_PATTERN)
|
||||
vibrationTimes = savedInstanceState.getInt(STATE_VIBRATION_TIMES)
|
||||
} else {
|
||||
isVibrationEnabled = vibrationPreference.isVibrationEnabled
|
||||
vibrationPattern = vibrationPreference.vibrationPattern
|
||||
vibratePattern = vibrationPreference.vibratePattern
|
||||
vibrationTimes = vibrationPreference.vibrationTimes
|
||||
}
|
||||
|
||||
|
@ -47,7 +50,7 @@ class VibrationDialogFragment : PreferenceDialogFragmentCompat() {
|
|||
isVibrationEnabled,
|
||||
entries = vibrationPreference.entries.map { it.toString() },
|
||||
entryValues = vibrationPreference.entryValues.map { it.toString().toInt() },
|
||||
vibrationPattern,
|
||||
vibratePattern,
|
||||
vibrationTimes
|
||||
)
|
||||
|
||||
|
@ -62,7 +65,7 @@ class VibrationDialogFragment : PreferenceDialogFragmentCompat() {
|
|||
if (positiveResult) {
|
||||
vibrationPreference.setVibration(
|
||||
isVibrationEnabled = adapter.isVibrationEnabled,
|
||||
vibrationPattern = adapter.vibrationPattern,
|
||||
vibratePattern = adapter.vibratePattern,
|
||||
vibrationTimes = adapter.vibrationTimes
|
||||
)
|
||||
}
|
||||
|
@ -71,21 +74,21 @@ class VibrationDialogFragment : PreferenceDialogFragmentCompat() {
|
|||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putBoolean(STATE_VIBRATE, adapter.isVibrationEnabled)
|
||||
outState.putInt(STATE_VIBRATION_PATTERN, adapter.vibrationPattern)
|
||||
outState.putEnum(STATE_VIBRATE_PATTERN, adapter.vibratePattern)
|
||||
outState.putInt(STATE_VIBRATION_TIMES, adapter.vibrationTimes)
|
||||
}
|
||||
|
||||
private fun playVibration() {
|
||||
val vibrationPattern = adapter.vibrationPattern
|
||||
val vibratePattern = adapter.vibratePattern
|
||||
val vibrationTimes = adapter.vibrationTimes
|
||||
val combinedPattern = NotificationSetting.getVibration(vibrationPattern, vibrationTimes)
|
||||
val vibrationPattern = NotificationSettings.getVibrationPattern(vibratePattern, vibrationTimes)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val vibrationEffect = VibrationEffect.createWaveform(combinedPattern, -1)
|
||||
val vibrationEffect = VibrationEffect.createWaveform(vibrationPattern, -1)
|
||||
vibrator.vibrate(vibrationEffect)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
vibrator.vibrate(combinedPattern, -1)
|
||||
vibrator.vibrate(vibrationPattern, -1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,13 +96,13 @@ class VibrationDialogFragment : PreferenceDialogFragmentCompat() {
|
|||
var isVibrationEnabled: Boolean,
|
||||
private val entries: List<String>,
|
||||
private val entryValues: List<Int>,
|
||||
initialVibrationPattern: Int,
|
||||
initialVibratePattern: VibratePattern,
|
||||
initialVibrationTimes: Int
|
||||
) : BaseAdapter() {
|
||||
private var checkedEntryIndex = entryValues.indexOf(initialVibrationPattern).takeIf { it != -1 } ?: 0
|
||||
private var checkedEntryIndex = entryValues.indexOf(initialVibratePattern.serialize()).takeIf { it != -1 } ?: 0
|
||||
|
||||
val vibrationPattern: Int
|
||||
get() = entryValues[checkedEntryIndex]
|
||||
val vibratePattern: VibratePattern
|
||||
get() = VibratePattern.deserialize(entryValues[checkedEntryIndex])
|
||||
|
||||
var vibrationTimes = initialVibrationTimes
|
||||
|
||||
|
@ -209,7 +212,7 @@ class VibrationDialogFragment : PreferenceDialogFragmentCompat() {
|
|||
|
||||
companion object {
|
||||
private const val STATE_VIBRATE = "vibrate"
|
||||
private const val STATE_VIBRATION_PATTERN = "vibrationPattern"
|
||||
private const val STATE_VIBRATE_PATTERN = "vibratePattern"
|
||||
private const val STATE_VIBRATION_TIMES = "vibrationTimes"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ import android.content.Context
|
|||
import android.util.AttributeSet
|
||||
import androidx.core.content.res.TypedArrayUtils
|
||||
import androidx.preference.ListPreference
|
||||
import com.fsck.k9.NotificationSetting
|
||||
import com.fsck.k9.NotificationSettings
|
||||
import com.fsck.k9.VibratePattern
|
||||
import com.fsck.k9.ui.R
|
||||
import com.takisoft.preferencex.PreferenceFragmentCompat
|
||||
|
||||
|
@ -28,7 +29,7 @@ constructor(
|
|||
internal var isVibrationEnabled: Boolean = false
|
||||
private set
|
||||
|
||||
internal var vibrationPattern: Int = DEFAULT_VIBRATION_PATTERN
|
||||
internal var vibratePattern = DEFAULT_VIBRATE_PATTERN
|
||||
private set
|
||||
|
||||
internal var vibrationTimes: Int = DEFAULT_VIBRATION_TIMES
|
||||
|
@ -39,7 +40,7 @@ constructor(
|
|||
val (isVibrationEnabled, vibrationPattern, vibrationTimes) = decode(encoded)
|
||||
|
||||
this.isVibrationEnabled = isVibrationEnabled
|
||||
this.vibrationPattern = vibrationPattern
|
||||
this.vibratePattern = vibrationPattern
|
||||
this.vibrationTimes = vibrationTimes
|
||||
|
||||
updateSummary()
|
||||
|
@ -49,12 +50,12 @@ constructor(
|
|||
preferenceManager.showDialog(this)
|
||||
}
|
||||
|
||||
fun setVibration(isVibrationEnabled: Boolean, vibrationPattern: Int, vibrationTimes: Int) {
|
||||
fun setVibration(isVibrationEnabled: Boolean, vibratePattern: VibratePattern, vibrationTimes: Int) {
|
||||
this.isVibrationEnabled = isVibrationEnabled
|
||||
this.vibrationPattern = vibrationPattern
|
||||
this.vibratePattern = vibratePattern
|
||||
this.vibrationTimes = vibrationTimes
|
||||
|
||||
val encoded = encode(isVibrationEnabled, vibrationPattern, vibrationTimes)
|
||||
val encoded = encode(isVibrationEnabled, vibratePattern, vibrationTimes)
|
||||
persistString(encoded)
|
||||
|
||||
updateSummary()
|
||||
|
@ -62,26 +63,29 @@ constructor(
|
|||
|
||||
fun setVibrationFromSystem(isVibrationEnabled: Boolean, combinedPattern: List<Long>?) {
|
||||
if (combinedPattern == null || combinedPattern.size < 2 || combinedPattern.size % 2 != 0) {
|
||||
setVibration(isVibrationEnabled, DEFAULT_VIBRATION_PATTERN, DEFAULT_VIBRATION_TIMES)
|
||||
setVibration(isVibrationEnabled, DEFAULT_VIBRATE_PATTERN, DEFAULT_VIBRATION_TIMES)
|
||||
return
|
||||
}
|
||||
|
||||
val combinedPatternArray = combinedPattern.toLongArray()
|
||||
val vibrationTimes = combinedPattern.size / 2
|
||||
val vibrationPattern = entryValues.asSequence()
|
||||
.map { entryValue -> entryValue.toString().toInt() }
|
||||
.firstOrNull { vibrationPattern ->
|
||||
val testPattern = NotificationSetting.getVibration(vibrationPattern, vibrationTimes)
|
||||
.map { entryValue ->
|
||||
val serializedVibratePattern = entryValue.toString().toInt()
|
||||
VibratePattern.deserialize(serializedVibratePattern)
|
||||
}
|
||||
.firstOrNull { vibratePattern ->
|
||||
val testPattern = NotificationSettings.getVibrationPattern(vibratePattern, vibrationTimes)
|
||||
|
||||
testPattern.contentEquals(combinedPatternArray)
|
||||
} ?: DEFAULT_VIBRATION_PATTERN
|
||||
} ?: DEFAULT_VIBRATE_PATTERN
|
||||
|
||||
setVibration(isVibrationEnabled, vibrationPattern, vibrationTimes)
|
||||
}
|
||||
|
||||
private fun updateSummary() {
|
||||
summary = if (isVibrationEnabled) {
|
||||
val index = entryValues.indexOf(vibrationPattern.toString())
|
||||
val index = entryValues.indexOf(vibratePattern.serialize().toString())
|
||||
entries[index]
|
||||
} else {
|
||||
context.getString(R.string.account_settings_vibrate_summary_disabled)
|
||||
|
@ -89,7 +93,7 @@ constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val DEFAULT_VIBRATION_PATTERN = 0
|
||||
private val DEFAULT_VIBRATE_PATTERN = VibratePattern.Default
|
||||
private const val DEFAULT_VIBRATION_TIMES = 1
|
||||
|
||||
init {
|
||||
|
@ -98,14 +102,14 @@ constructor(
|
|||
)
|
||||
}
|
||||
|
||||
fun encode(isVibrationEnabled: Boolean, vibrationPattern: Int, vibrationTimes: Int): String {
|
||||
return "$isVibrationEnabled|$vibrationPattern|$vibrationTimes"
|
||||
fun encode(isVibrationEnabled: Boolean, vibratePattern: VibratePattern, vibrationTimes: Int): String {
|
||||
return "$isVibrationEnabled|${vibratePattern.name}|$vibrationTimes"
|
||||
}
|
||||
|
||||
fun decode(encoded: String): Triple<Boolean, Int, Int> {
|
||||
fun decode(encoded: String): Triple<Boolean, VibratePattern, Int> {
|
||||
val parts = encoded.split('|')
|
||||
val isVibrationEnabled = parts[0].toBoolean()
|
||||
val vibrationPattern = parts[1].toInt()
|
||||
val vibrationPattern = VibratePattern.valueOf(parts[1])
|
||||
val vibrationTimes = parts[2].toInt()
|
||||
return Triple(isVibrationEnabled, vibrationPattern, vibrationTimes)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue