Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a440a4f authored by Mohammed Althaf T's avatar Mohammed Althaf T 😊
Browse files

mail: Move helper class to feature

parent 832ac044
Loading
Loading
Loading
Loading
+88 −1
Original line number Diff line number Diff line
@@ -19,15 +19,102 @@ package app.k9mail.feature.account.accountmanager

import android.accounts.Account
import android.accounts.AccountManager
import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import app.k9mail.core.common.mail.Protocols
import app.k9mail.feature.account.accountmanager.providersxml.DiscoveredServerSettings
import app.k9mail.legacy.account.Account.DeletePolicy
import com.fsck.k9.logging.Timber
import com.fsck.k9.mail.AuthType
import com.fsck.k9.mail.ServerSettings
import com.fsck.k9.mail.oauth.AuthStateStorage
import app.k9mail.legacy.account.Account as kAccount
import app.k9mail.legacy.account.AccountManager as kAccountManager

object AccountManagerHelper {
    fun pickColor(context: Context, accounts: List<kAccount>): Int {
        val resources = context.resources
        val usedAccountColors = accounts.map { it.chipColor }.toSet()
        val accountColors = resources.getIntArray(R.array.account_colors).toList()

        val availableColors = accountColors - usedAccountColors
        if (availableColors.isEmpty()) {
            return accountColors.random()
        }

        val defaultAccountColors = resources.getIntArray(R.array.default_account_colors)
        return availableColors.shuffled().minByOrNull { color ->
            val index = defaultAccountColors.indexOf(color)
            if (index != -1) index else defaultAccountColors.size
        } ?: accountColors.random()
    }

    fun getServerSettings(discoveredServerSettings: DiscoveredServerSettings, password: String): ServerSettings? {
        if (discoveredServerSettings.authType == null || discoveredServerSettings.username == null) return null

        return ServerSettings(
            type = discoveredServerSettings.protocol,
            host = discoveredServerSettings.host,
            port = discoveredServerSettings.port,
            connectionSecurity = discoveredServerSettings.security,
            authenticationType = discoveredServerSettings.authType!!,
            username = discoveredServerSettings.username!!,
            password = password,
            clientCertificateAlias = null,
            extra = emptyMap()
        )
    }

    @SuppressLint("MissingPermission")
    fun isNetworkAvailable(context: Context): Boolean {
        val connectivityManager = context.getSystemService(ConnectivityManager::class.java)
        val activeNetwork = connectivityManager.activeNetwork
        val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
        return networkCapabilities?.run {
            hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
                hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) &&
                (hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                    hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
                    hasTransport(NetworkCapabilities.TRANSPORT_USB) ||
                    hasTransport(NetworkCapabilities.TRANSPORT_VPN) ||
                    hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
        } ?: false
    }

    fun getDefaultDeletePolicy(type: String): DeletePolicy? {
        return when (type) {
            Protocols.IMAP -> DeletePolicy.ON_DELETE
            Protocols.POP3 -> DeletePolicy.NEVER
            "demo" -> DeletePolicy.ON_DELETE
            else -> {
                Timber.d("Unhandled case: $type")
                null
            }
        }
    }

    fun isInvalidEmail(emailId: String?): Boolean {
        return emailId == null || !emailId.contains("@")
    }

    // check the account sync for mail authority is enable or not
    fun isSyncable(account: Account?): Boolean {
        // if master sync disable, then account sync is disable
        if (account == null || !ContentResolver.getMasterSyncAutomatically()) {
            return false
        }

        return ContentResolver.getSyncAutomatically(account, AccountManagerConstants.MAIL_CONTENT_AUTHORITY)
    }

    fun isOpenIdAccount(accountManager: AccountManager, account: Account): Boolean {
        val authState = accountManager.getUserData(account, AccountManagerConstants.KEY_AUTH_STATE)
        return authState != null && authState.trim { it <= ' ' }.isNotEmpty()
    }

    /**
     * Update oAuthState for google accounts which is logged in using accountManager
     * @return is the update operation successful or not
@@ -205,7 +292,7 @@ object AccountManagerHelper {
                    )
                }
            } catch (e: Throwable) {
                timber.log.Timber.e(e)
                Timber.e(e)
            }
        }

+9 −7
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.accounts.AccountManager
import android.content.Context
import app.k9mail.core.common.oauth.OAuthConfigurationProvider
import app.k9mail.feature.account.accountmanager.AccountManagerConstants
import app.k9mail.feature.account.accountmanager.AccountManagerHelper
import app.k9mail.feature.account.accountmanager.providersxml.DiscoveryResults
import app.k9mail.feature.account.accountmanager.providersxml.ProvidersXmlDiscovery
import app.k9mail.feature.account.accountmanager.providersxml.ProvidersXmlProvider
@@ -49,7 +50,8 @@ internal class EeloAccountCreator(context: Context) : KoinComponent {

    private fun createAccount(emailId: String, password: String, authState: String?, accountType: String): Boolean {
        val newAccount = preferences.newAccount()
        newAccount.chipColor = EeloAccountHelper.pickColor(mContext, preferences)
        val accounts = preferences.getAccounts()
        newAccount.chipColor = AccountManagerHelper.pickColor(mContext, accounts)
        newAccount.email = emailId
        newAccount.name = emailId
        newAccount.senderName = emailId
@@ -62,8 +64,8 @@ internal class EeloAccountCreator(context: Context) : KoinComponent {
            return false
        }

        var incomingSettings: ServerSettings? = EeloAccountHelper.getServerSettings(serverSettings.incoming[0], password)
        var outgoingSettings: ServerSettings? = EeloAccountHelper.getServerSettings(serverSettings.outgoing[0], password)
        var incomingSettings: ServerSettings? = AccountManagerHelper.getServerSettings(serverSettings.incoming[0], password)
        var outgoingSettings: ServerSettings? = AccountManagerHelper.getServerSettings(serverSettings.outgoing[0], password)

        if (incomingSettings == null || outgoingSettings == null) {
            Timber.d("Unable to find server settings")
@@ -80,7 +82,7 @@ internal class EeloAccountCreator(context: Context) : KoinComponent {

        newAccount.oAuthState = authState

        val deletePolicy: DeletePolicy? = EeloAccountHelper.getDefaultDeletePolicy(incomingSettings.type)
        val deletePolicy: DeletePolicy? = AccountManagerHelper.getDefaultDeletePolicy(incomingSettings.type)
        if (deletePolicy != null) {
            newAccount.deletePolicy = deletePolicy
        }
@@ -131,8 +133,8 @@ internal class EeloAccountCreator(context: Context) : KoinComponent {
        val accountList = accountManager.getAccountsByType(accountType)
        for (account in accountList) {
            val emailId = accountManager.getUserData(account, AccountManagerConstants.ACCOUNT_EMAIL_ADDRESS_KEY)
            val isInvalidAccount = EeloAccountHelper.isInvalidEmail(emailId) || !EeloAccountHelper.isSyncable(account)
            val isOpenId = EeloAccountHelper.isOpenIdAccount(accountManager, account)
            val isInvalidAccount = AccountManagerHelper.isInvalidEmail(emailId) || !AccountManagerHelper.isSyncable(account)
            val isOpenId = AccountManagerHelper.isOpenIdAccount(accountManager, account)
            val shouldSkip = when (accountType) {
                AccountManagerConstants.EELO_ACCOUNT_TYPE -> isInvalidAccount || isOpenId
                else -> isInvalidAccount || !isOpenId
@@ -169,7 +171,7 @@ internal class EeloAccountCreator(context: Context) : KoinComponent {
        val providersXmlDiscovery = ProvidersXmlDiscovery(providersXmlProvider, oAuthConfigurationProvider)
        val providerXmlConfig = providersXmlDiscovery.providersXmlDiscoveryDiscover(emailId)

        if (EeloAccountHelper.isNetworkAvailable(mContext) &&
        if (AccountManagerHelper.isNetworkAvailable(mContext) &&
            (providerXmlConfig.incoming.isEmpty() || providerXmlConfig.outgoing.isEmpty())) {
            val autoconfigUrlProvider = EeloAutoConfigUrlProvider(emailId)
            val autoConfigs = autoconfigUrlProvider.fetchFromValidXml()
+0 −115
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 MURENA SAS
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 *
 */
package com.fsck.k9.activity.accountmanager

import android.accounts.Account
import android.accounts.AccountManager
import android.content.ContentResolver
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import app.k9mail.core.common.mail.Protocols
import app.k9mail.feature.account.accountmanager.AccountManagerConstants
import app.k9mail.feature.account.accountmanager.providersxml.DiscoveredServerSettings
import app.k9mail.legacy.account.Account.DeletePolicy
import com.fsck.k9.Preferences
import com.fsck.k9.logging.Timber
import com.fsck.k9.mail.ServerSettings
import com.fsck.k9.ui.R

object EeloAccountHelper {
    fun pickColor(context: Context, preferences: Preferences): Int {
        val accounts = preferences.getAccounts()
        val resources = context.resources
        val usedAccountColors = accounts.map { it.chipColor }.toSet()
        val accountColors = resources.getIntArray(R.array.account_colors).toList()

        val availableColors = accountColors - usedAccountColors
        if (availableColors.isEmpty()) {
            return accountColors.random()
        }

        val defaultAccountColors = resources.getIntArray(R.array.default_account_colors)
        return availableColors.shuffled().minByOrNull { color ->
            val index = defaultAccountColors.indexOf(color)
            if (index != -1) index else defaultAccountColors.size
        } ?: accountColors.random()
    }

    fun getServerSettings(discoveredServerSettings: DiscoveredServerSettings, password: String): ServerSettings? {
        if (discoveredServerSettings.authType == null || discoveredServerSettings.username == null) return null

        return ServerSettings(
            type = discoveredServerSettings.protocol,
            host = discoveredServerSettings.host,
            port = discoveredServerSettings.port,
            connectionSecurity = discoveredServerSettings.security,
            authenticationType = discoveredServerSettings.authType!!,
            username = discoveredServerSettings.username!!,
            password = password,
            clientCertificateAlias = null,
            extra = emptyMap()
        )
    }

    fun isNetworkAvailable(context: Context): Boolean {
        val connectivityManager = context.getSystemService(ConnectivityManager::class.java)
        val activeNetwork = connectivityManager.activeNetwork
        val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
        return networkCapabilities?.run {
            hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
                hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) &&
                (hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                    hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
                    hasTransport(NetworkCapabilities.TRANSPORT_USB) ||
                    hasTransport(NetworkCapabilities.TRANSPORT_VPN) ||
                    hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
        } ?: false
    }

    fun getDefaultDeletePolicy(type: String): DeletePolicy? {
        return when (type) {
            Protocols.IMAP -> DeletePolicy.ON_DELETE
            Protocols.POP3 -> DeletePolicy.NEVER
            "demo" -> DeletePolicy.ON_DELETE
            else -> {
                Timber.d("Unhandled case: $type")
                null
            }
        }
    }

    fun isInvalidEmail(emailId: String?): Boolean {
        return emailId == null || !emailId.contains("@")
    }

    // check the account sync for mail authority is enable or not
    fun isSyncable(account: Account?): Boolean {
        // if master sync disable, then account sync is disable
        if (account == null || !ContentResolver.getMasterSyncAutomatically()) {
            return false
        }

        return ContentResolver.getSyncAutomatically(account, AccountManagerConstants.MAIL_CONTENT_AUTHORITY)
    }

    fun isOpenIdAccount(accountManager: AccountManager, account: Account): Boolean {
        val authState = accountManager.getUserData(account, AccountManagerConstants.KEY_AUTH_STATE)
        return authState != null && authState.trim { it <= ' ' }.isNotEmpty()
    }
}