diff --git a/data/src/main/java/com/moez/QKSMS/repository/ContactRepositoryImpl.kt b/data/src/main/java/com/moez/QKSMS/repository/ContactRepositoryImpl.kt index 24c3c2e0..cba29074 100644 --- a/data/src/main/java/com/moez/QKSMS/repository/ContactRepositoryImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/repository/ContactRepositoryImpl.kt @@ -30,6 +30,7 @@ import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import io.realm.Realm +import io.realm.RealmResults import javax.inject.Inject import javax.inject.Singleton @@ -51,6 +52,13 @@ class ContactRepositoryImpl @Inject constructor(val context: Context) : ContactR .map { id -> Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, id) } } + override fun getContacts(): RealmResults { + val realm = Realm.getDefaultInstance() + return realm.where(Contact::class.java) + .sort("name") + .findAll() + } + override fun getUnmanagedContacts(): Flowable> { val realm = Realm.getDefaultInstance() return realm.where(Contact::class.java) diff --git a/domain/src/main/java/com/moez/QKSMS/repository/ContactRepository.kt b/domain/src/main/java/com/moez/QKSMS/repository/ContactRepository.kt index 3f40d148..03733626 100644 --- a/domain/src/main/java/com/moez/QKSMS/repository/ContactRepository.kt +++ b/domain/src/main/java/com/moez/QKSMS/repository/ContactRepository.kt @@ -22,11 +22,14 @@ import android.net.Uri import com.moez.QKSMS.model.Contact import io.reactivex.Flowable import io.reactivex.Single +import io.realm.RealmResults interface ContactRepository { fun findContactUri(address: String): Single + fun getContacts(): RealmResults + fun getUnmanagedContacts(): Flowable> } \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/QkRealmAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/QkRealmAdapter.kt index ee3af158..98470ea4 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/QkRealmAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/QkRealmAdapter.kt @@ -18,6 +18,12 @@ abstract class QkRealmAdapter : RealmRecyclerViewAdapter) -> Unit = { data -> emptyView?.setVisible(data.isLoaded && data.isEmpty()) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt index 89c63dab..4440e674 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt @@ -49,6 +49,7 @@ import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.util.extensions.setVisible import com.moez.QKSMS.feature.conversations.ConversationItemTouchCallback import com.moez.QKSMS.feature.conversations.ConversationsAdapter +import com.moez.QKSMS.feature.scheduled.ScheduledMessageAdapter import com.moez.QKSMS.repository.SyncRepository import com.uber.autodispose.kotlin.autoDisposable import dagger.android.AndroidInjection @@ -63,6 +64,7 @@ class MainActivity : QkThemedActivity(), MainView { @Inject lateinit var navigator: Navigator @Inject lateinit var conversationsAdapter: ConversationsAdapter + @Inject lateinit var scheduledMessageAdapter: ScheduledMessageAdapter @Inject lateinit var searchAdapter: SearchAdapter @Inject lateinit var itemTouchCallback: ConversationItemTouchCallback @Inject lateinit var viewModelFactory: ViewModelProvider.Factory @@ -122,8 +124,6 @@ class MainActivity : QkThemedActivity(), MainView { // Don't allow clicks to pass through the drawer layout drawer.clicks().subscribe() - scheduled.isEnabled = false - // Set the theme color tint to the recyclerView, progressbar, and FAB colors.themeObservable() .doOnNext { recyclerView.scrapViews() } @@ -160,7 +160,6 @@ class MainActivity : QkThemedActivity(), MainView { toggle.drawerArrowDrawable.color = resolveThemeColor(android.R.attr.textColorSecondary) conversationsAdapter.autoScrollToStart(recyclerView) - conversationsAdapter.emptyView = empty } override fun render(state: MainState) { @@ -194,6 +193,8 @@ class MainActivity : QkThemedActivity(), MainView { rateLayout.setVisible(state.showRating) compose.setVisible(state.page is Inbox || state.page is Archived) + conversationsAdapter.emptyView = empty.takeIf { state.page is Inbox || state.page is Archived } + scheduledMessageAdapter.emptyView = empty.takeIf { state.page is Archived } when (state.page) { is Inbox -> { @@ -227,7 +228,8 @@ class MainActivity : QkThemedActivity(), MainView { is Scheduled -> { setTitle(R.string.title_scheduled) - recyclerView.adapter = null + if (recyclerView.adapter !== scheduledMessageAdapter) recyclerView.adapter = scheduledMessageAdapter + scheduledMessageAdapter.updateData(state.page.data) itemTouchHelper.attachToRecyclerView(null) empty.setText(R.string.scheduled_empty_text) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainState.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainState.kt index 75fa7221..56621bce 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainState.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainState.kt @@ -18,7 +18,9 @@ */ package com.moez.QKSMS.feature.main +import com.moez.QKSMS.feature.scheduled.ScheduledMessageAdapter import com.moez.QKSMS.model.Conversation +import com.moez.QKSMS.model.ScheduledMessage import com.moez.QKSMS.model.SearchResult import com.moez.QKSMS.repository.SyncRepository import io.realm.RealmResults @@ -55,4 +57,4 @@ data class Archived( val selected: Int = 0) : MainPage() data class Scheduled( - val data: Any? = null) : MainPage() \ No newline at end of file + val data: RealmResults) : MainPage() \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt index 621d982f..4befa386 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt @@ -36,7 +36,7 @@ import com.moez.QKSMS.manager.PermissionManager import com.moez.QKSMS.manager.RatingManager import com.moez.QKSMS.model.SyncLog import com.moez.QKSMS.repository.ConversationRepository -import com.moez.QKSMS.repository.MessageRepository +import com.moez.QKSMS.repository.ScheduledMessageRepository import com.moez.QKSMS.repository.SyncRepository import com.uber.autodispose.kotlin.autoDisposable import io.reactivex.Observable @@ -50,7 +50,6 @@ import java.util.concurrent.TimeUnit import javax.inject.Inject class MainViewModel @Inject constructor( - private val messageRepo: MessageRepository, private val markAllSeen: MarkAllSeen, private val conversationRepo: ConversationRepository, private val deleteConversations: DeleteConversations, @@ -63,6 +62,7 @@ class MainViewModel @Inject constructor( private val navigator: Navigator, private val permissionManager: PermissionManager, private val ratingManager: RatingManager, + private val scheduledMessageRepo: ScheduledMessageRepository, private val syncMessages: SyncMessages, private val syncRepository: SyncRepository ) : QkViewModel(MainState(page = Inbox(data = conversationRepo.getConversations()))) { @@ -190,7 +190,7 @@ class MainViewModel @Inject constructor( when (it) { DrawerItem.INBOX -> newState { copy(page = Inbox(data = conversationRepo.getConversations())) } DrawerItem.ARCHIVED -> newState { copy(page = Archived(data = conversationRepo.getConversations(true))) } - DrawerItem.SCHEDULED -> newState { copy(page = Scheduled()) } + DrawerItem.SCHEDULED -> newState { copy(page = Scheduled(data = scheduledMessageRepo.getScheduledMessages())) } else -> { } // Do nothing } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAdapter.kt new file mode 100644 index 00000000..1183883b --- /dev/null +++ b/presentation/src/main/java/com/moez/QKSMS/feature/scheduled/ScheduledMessageAdapter.kt @@ -0,0 +1,54 @@ +package com.moez.QKSMS.feature.scheduled + +import android.telephony.PhoneNumberUtils +import android.view.LayoutInflater +import android.view.ViewGroup +import com.moez.QKSMS.R +import com.moez.QKSMS.common.base.QkRealmAdapter +import com.moez.QKSMS.common.base.QkViewHolder +import com.moez.QKSMS.common.util.DateFormatter +import com.moez.QKSMS.model.Contact +import com.moez.QKSMS.model.PhoneNumber +import com.moez.QKSMS.model.Recipient +import com.moez.QKSMS.model.ScheduledMessage +import com.moez.QKSMS.repository.ContactRepository +import io.realm.RealmList +import kotlinx.android.synthetic.main.scheduled_message_list_item.view.* +import javax.inject.Inject + +class ScheduledMessageAdapter @Inject constructor( + private val contactRepo: ContactRepository, + private val dateFormatter: DateFormatter +) : QkRealmAdapter() { + + private val contacts by lazy { contactRepo.getContacts() } + private val contactMap: HashMap = hashMapOf() + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { + return QkViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.scheduled_message_list_item, parent, false)) + } + + override fun onBindViewHolder(holder: QkViewHolder, position: Int) { + val message = getItem(position)!! + val view = holder.itemView + + message.recipients.forEach { address -> + if (!contactMap.containsKey(address)) { + contactMap[address] = contacts + .firstOrNull { it.numbers.any { number -> PhoneNumberUtils.compare(address, number.address) } } + ?: Contact(numbers = RealmList(PhoneNumber(address))) + } + } + + // GroupAvatarView only accepts recipients, so map the phone numbers to recipients + view.avatars.contacts = message.recipients.map { address -> Recipient(address = address) } + + view.recipients.text = message.recipients.joinToString(",") { address -> + contactMap[address]?.name?.takeIf { it.isNotBlank() } ?: address + } + + view.date.text = dateFormatter.getScheduledTimestamp(message.date) + view.body.text = message.body + } + +} \ No newline at end of file diff --git a/presentation/src/main/res/layout/drawer_view.xml b/presentation/src/main/res/layout/drawer_view.xml index d134c61d..d419b497 100644 --- a/presentation/src/main/res/layout/drawer_view.xml +++ b/presentation/src/main/res/layout/drawer_view.xml @@ -60,8 +60,7 @@ + style="@style/DrawerRow"> + + + + + + + + + + + + \ No newline at end of file