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

Commit 92cc3b7a authored by Moez Bhatti's avatar Moez Bhatti Committed by Dayona Joseph
Browse files

Keep contacts in sync

Fixes #329
parent d9fba04d
Loading
Loading
Loading
Loading
+5 −10
Original line number Original line Diff line number Diff line
@@ -23,33 +23,28 @@ import android.database.ContentObserver
import android.net.Uri
import android.net.Uri
import android.os.Handler
import android.os.Handler
import android.provider.ContactsContract
import android.provider.ContactsContract
import com.moez.QKSMS.repository.SyncRepository
import io.reactivex.Observable
import io.reactivex.Observable
import io.reactivex.subjects.PublishSubject
import io.reactivex.subjects.BehaviorSubject
import javax.inject.Inject
import javax.inject.Inject


/**
/**
 * Listens for a contact being added, and then syncs it to Realm
 * Listens for a contact being added, and then syncs it to Realm
 *
 * TODO: Stop listening automatically. Currently, this will only happen if the contact is added
 */
 */
class ContactAddedListenerImpl @Inject constructor(
class ContactAddedListenerImpl @Inject constructor(
    private val context: Context,
    private val context: Context
    private val syncRepo: SyncRepository
) : ContactAddedListener {
) : ContactAddedListener {


    companion object {
    companion object {
        private val URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI
        private val URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI
    }
    }


    override fun listen(address: String): Observable<*> {
    override fun listen(): Observable<*> {
        return ContactContentObserver(context).observable
        return ContactContentObserver(context).observable
                .filter { syncRepo.syncContact(address) }
    }
    }


    private class ContactContentObserver(context: Context) : ContentObserver(Handler()) {
    private class ContactContentObserver(context: Context) : ContentObserver(Handler()) {


        private val subject = PublishSubject.create<Unit>()
        private val subject = BehaviorSubject.createDefault<Unit>(Unit)


        val observable: Observable<Unit> = subject
        val observable: Observable<Unit> = subject
                .doOnSubscribe { context.contentResolver.registerContentObserver(URI, true, this) }
                .doOnSubscribe { context.contentResolver.registerContentObserver(URI, true, this) }
+2 −28
Original line number Original line Diff line number Diff line
@@ -65,7 +65,7 @@ class SyncRepositoryImpl @Inject constructor(
) : SyncRepository {
) : SyncRepository {


    override val syncProgress: Subject<SyncRepository.SyncProgress> =
    override val syncProgress: Subject<SyncRepository.SyncProgress> =
            BehaviorSubject.createDefault(SyncRepository.SyncProgress.Idle())
            BehaviorSubject.createDefault(SyncRepository.SyncProgress.Idle)


    override fun syncMessages() {
    override fun syncMessages() {


@@ -185,7 +185,7 @@ class SyncRepositoryImpl @Inject constructor(
        // Only delete this after the sync has successfully completed
        // Only delete this after the sync has successfully completed
        oldBlockedSenders.delete()
        oldBlockedSenders.delete()


        syncProgress.onNext(SyncRepository.SyncProgress.Idle())
        syncProgress.onNext(SyncRepository.SyncProgress.Idle)
    }
    }


    override fun syncMessage(uri: Uri): Message? {
    override fun syncMessage(uri: Uri): Message? {
@@ -259,32 +259,6 @@ class SyncRepositoryImpl @Inject constructor(
        }
        }
    }
    }


    override fun syncContact(address: String): Boolean {
        // See if there's a contact that matches this phone number
        var contact = getContacts().find { contact ->
            contact.numbers.any { number -> phoneNumberUtils.compare(number.address, address) }
        } ?: return false

        Realm.getDefaultInstance().use { realm ->
            val recipients = realm.where(Recipient::class.java).findAll().filter { recipient ->
                contact.numbers.any { number ->
                    phoneNumberUtils.compare(recipient.address, number.address)
                }
            }

            realm.executeTransaction {
                contact = realm.copyToRealmOrUpdate(contact)

                // Update all the matching recipients with the new contact
                recipients.forEach { recipient -> recipient.contact = contact }

                realm.insertOrUpdate(recipients)
            }
        }

        return true
    }

    private fun getContacts(): List<Contact> {
    private fun getContacts(): List<Contact> {
        val defaultNumberIds = Realm.getDefaultInstance().use { realm ->
        val defaultNumberIds = Realm.getDefaultInstance().use { realm ->
            realm.where(PhoneNumber::class.java)
            realm.where(PhoneNumber::class.java)
+1 −3
Original line number Original line Diff line number Diff line
@@ -21,7 +21,6 @@ package com.moez.QKSMS.interactor
import com.moez.QKSMS.repository.SyncRepository
import com.moez.QKSMS.repository.SyncRepository
import io.reactivex.Flowable
import io.reactivex.Flowable
import timber.log.Timber
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Inject


class SyncContacts @Inject constructor(private val syncManager: SyncRepository) : Interactor<Unit>() {
class SyncContacts @Inject constructor(private val syncManager: SyncRepository) : Interactor<Unit>() {
@@ -30,8 +29,7 @@ class SyncContacts @Inject constructor(private val syncManager: SyncRepository)
        return Flowable.just(System.currentTimeMillis())
        return Flowable.just(System.currentTimeMillis())
                .doOnNext { syncManager.syncContacts() }
                .doOnNext { syncManager.syncContacts() }
                .map { startTime -> System.currentTimeMillis() - startTime }
                .map { startTime -> System.currentTimeMillis() - startTime }
                .map { elapsed -> TimeUnit.MILLISECONDS.toSeconds(elapsed) }
                .doOnNext { duration -> Timber.v("Completed sync in ${duration}ms") }
                .doOnNext { seconds -> Timber.v("Completed sync in $seconds seconds") }
    }
    }


}
}
 No newline at end of file
+2 −2
Original line number Original line Diff line number Diff line
@@ -22,6 +22,6 @@ import io.reactivex.Observable


interface ContactAddedListener {
interface ContactAddedListener {


    fun listen(address: String): Observable<*>
    fun listen(): Observable<*>


}
}
+2 −9
Original line number Original line Diff line number Diff line
@@ -25,7 +25,7 @@ import io.reactivex.Observable
interface SyncRepository {
interface SyncRepository {


    sealed class SyncProgress {
    sealed class SyncProgress {
        class Idle : SyncProgress()
        object Idle : SyncProgress()
        data class Running(val max: Int, val progress: Int, val indeterminate: Boolean) : SyncProgress()
        data class Running(val max: Int, val progress: Int, val indeterminate: Boolean) : SyncProgress()
    }
    }


@@ -37,11 +37,4 @@ interface SyncRepository {


    fun syncContacts()
    fun syncContacts()


    /**
     * Syncs a single contact to the Realm
     *
     * Return false if the contact couldn't be found
     */
    fun syncContact(address: String): Boolean

}
}
Loading