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

Commit 433ab20a authored by Fahim Salam Chowdhury's avatar Fahim Salam Chowdhury 👽
Browse files

5560-sync_mail_with_account_manager

issue: https://gitlab.e.foundation/e/backlog/-/issues/5560

Introduce new broadCast receiver which will be called from
accountManager & settings app when new account is confiured, or any
account is removed, so that mail app accounts also got synced with them.

- new AccountSyncReceiver implemented
- refactor EeloAccountCreator code
- Bug fix: invalid account created automatically on accountSync call
- Bug fix: on new account creation account name always updated with
  email
parent 5f52e0f8
Loading
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.os.SystemClock;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.work.ListenableWorker.Result;
import com.fsck.k9.Account;
import com.fsck.k9.Account.DeletePolicy;
import com.fsck.k9.Account.Expunge;
@@ -2243,7 +2244,7 @@ public class MessagingController {
        return !backend.getSupportsTrashFolder();
    }

    public boolean performPeriodicMailSync(Account account) {
    public Result performPeriodicMailSync(Account account) {
        final CountDownLatch latch = new CountDownLatch(1);
        MutableBoolean syncError = new MutableBoolean(false);
        checkMail(account, false, false, true, new SimpleMessagingListener() {
@@ -2269,13 +2270,17 @@ public class MessagingController {

        boolean success = !syncError.getValue();
        if (success) {
            if (preferences.getAccount(account.getUuid()) == null) {
                Timber.e("Account %s not present. Can't perform mail sync.", account.getUuid());
                return Result.failure();
            }
            long now = System.currentTimeMillis();
            Timber.v("Account %s successfully synced @ %tc", account, now);
            account.setLastSyncTime(now);
            preferences.saveAccount(account);
        }

        return success;
        return success ? Result.success() : Result.retry();
    }

    /**
+1 −3
Original line number Diff line number Diff line
@@ -44,9 +44,7 @@ class MailSyncWorker(
            return Result.success()
        }

        val success = messagingController.performPeriodicMailSync(account)

        return if (success) Result.success() else Result.retry()
        return messagingController.performPeriodicMailSync(account)
    }

    private fun isBackgroundSyncDisabled(): Boolean {
+9 −0
Original line number Diff line number Diff line
@@ -343,6 +343,15 @@
            </intent-filter>
        </receiver>

        <receiver android:name=".account.AccountSyncReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="foundation.e.accountmanager.account.create"/>
                <action android:name="foundation.e.accountmanager.account.remove"/>
            </intent-filter>
        </receiver>

        <service
            android:name=".widget.list.MessageListWidgetService"
            android:enabled="true"
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright ECORP SAS 2022
 * 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.account

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.fsck.k9.Preferences
import com.fsck.k9.activity.setup.accountmanager.EeloAccountCreator
import com.fsck.k9.controller.push.PushController
import java.util.concurrent.Executors
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

class AccountSyncReceiver : BroadcastReceiver(), KoinComponent {

    private val pushController: PushController by inject()
    private val preferences: Preferences by inject()
    private val accountRemover: BackgroundAccountRemover by inject()

    override fun onReceive(context: Context?, intent: Intent?) {
        intent?.let {
            if (it.action.equals("foundation.e.accountmanager.account.create", ignoreCase = true)) {
                createNewAccount(context)
            } else if (it.action.equals("foundation.e.accountmanager.account.remove", ignoreCase = true)) {
                removeAccount(it)
            }
        }
    }

    private fun createNewAccount(context: Context?) {
        pushController.init()
        context?.let {
            Executors.newSingleThreadExecutor().execute {
                EeloAccountCreator.loadAccountsFromAccountManager(it.applicationContext, preferences, accountRemover, null)
            }
        }
    }

    private fun removeAccount(intent: Intent) {
        val account = intent.extras?.getString("account")
        account?.let { email ->
            preferences.accounts.forEach {
                if (it.email == email) {
                    accountRemover.removeAccountAsync(it.uuid)
                    return@forEach
                }
            }
        }
    }
}
 No newline at end of file
+5 −66
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.fsck.k9.activity

import android.accounts.AccountManager
import android.annotation.SuppressLint
import android.app.SearchManager
import android.content.Context
@@ -53,9 +52,6 @@ import com.fsck.k9.Preferences
import com.fsck.k9.account.BackgroundAccountRemover
import com.fsck.k9.activity.compose.MessageActions
import com.fsck.k9.activity.setup.AccountSetupBasics
import com.fsck.k9.activity.setup.accountmanager.AccountManagerConstants.ACCOUNT_EMAIL_ADDRESS_KEY
import com.fsck.k9.activity.setup.accountmanager.AccountManagerConstants.EELO_ACCOUNT_TYPE
import com.fsck.k9.activity.setup.accountmanager.AccountManagerConstants.GOOGLE_ACCOUNT_TYPE
import com.fsck.k9.activity.setup.accountmanager.EeloAccountCreator
import com.fsck.k9.controller.MessageReference
import com.fsck.k9.controller.MessagingController
@@ -157,17 +153,11 @@ open class MessageList :
    private var viewSwitcher: ViewSwitcher? = null
    private lateinit var recentChangesSnackbar: Snackbar

    private lateinit var accountManager: AccountManager

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setLayout(R.layout.message_list_loading)

        val accounts = preferences.accounts
        deleteIncompleteAccounts(accounts)

        accountManager = AccountManager.get(this)
        addNewAccountsAutomatically(accounts, savedInstanceState)
        addNewAccountsAutomatically(savedInstanceState)
    }

    private fun onAccountConfigurationFinish(savedInstanceState: Bundle?) {
@@ -276,12 +266,6 @@ open class MessageList :
        displayViews()
    }

    private fun deleteIncompleteAccounts(accounts: List<Account>) {
        accounts.filter { !it.isFinishedSetup }.forEach {
            accountRemover.removeAccountAsync(it.uuid)
        }
    }

    private fun findFragments() {
        val fragmentManager = supportFragmentManager
        messageListFragment = fragmentManager.findFragmentById(R.id.message_list_container) as MessageListFragment?
@@ -1704,61 +1688,16 @@ open class MessageList :
        val messageViewOnly: Boolean = false
    )

    private fun addNewAccountsAutomatically(accounts: List<Account>, savedInstanceState: Bundle?) {
    private fun addNewAccountsAutomatically(savedInstanceState: Bundle?) {
        lifecycleScope.launch(Dispatchers.IO) {
            try {
                val eeloAccounts: Array<android.accounts.Account> = getEeloAccountsOnDevice()
                val googleAccounts: Array<android.accounts.Account> = getGoogleAccountsOnDevice()
                for (eeloAccount in eeloAccounts) {
                    val emailId: String = accountManager.getUserData(eeloAccount, ACCOUNT_EMAIL_ADDRESS_KEY)
                    if (!emailId.contains("@")) continue
                    var accountIsSignedIn = false
                    for (account in accounts) {
                        if (emailId == account.email) {
                            accountIsSignedIn = true
                            break
                        }
                    }
                    if (!accountIsSignedIn) {
                        val password: String = accountManager.getPassword(eeloAccount)
                        EeloAccountCreator.createAccount(applicationContext, emailId, password, false)
                    }
                }

                for (googleAccount in googleAccounts) {
                    val emailId: String = accountManager.getUserData(googleAccount, ACCOUNT_EMAIL_ADDRESS_KEY)

                    var accountIsSignedIn = false
                    for (account in accounts) {
                        if (emailId == account.email) {
                            if (account.name == null) { // we need to fix an old bug
                                account.name = emailId
                                Preferences.getPreferences(applicationContext).saveAccount(account)
                            }
                            accountIsSignedIn = true
                            break
                        }
                    }
                    if (!accountIsSignedIn) {
                        EeloAccountCreator.createAccount(applicationContext, emailId, "", true)
                    }
                }
            } catch (e: SecurityException) {
                Timber.e(e)
            }
            EeloAccountCreator.loadAccountsFromAccountManager(applicationContext, preferences, accountRemover) {
                lifecycleScope.launch(Dispatchers.Main) {
                    onAccountConfigurationFinish(savedInstanceState)
                }
            }
        }

    private fun getEeloAccountsOnDevice(): Array<android.accounts.Account> {
        return accountManager.getAccountsByType(EELO_ACCOUNT_TYPE)
    }

    private fun getGoogleAccountsOnDevice(): Array<android.accounts.Account> {
        return accountManager.getAccountsByType(GOOGLE_ACCOUNT_TYPE)
    }

    companion object : KoinComponent {
        private const val EXTRA_SEARCH = "search_bytes"
Loading