From 0ab85419af8f07e9ffd623dcc603d25d5146fb92 Mon Sep 17 00:00:00 2001 From: Naveen Date: Sun, 4 Dec 2022 00:49:41 +0530 Subject: [PATCH 01/10] Improve and organise notification related code Improvements related to the "Mark as read" button but it's not completely fixed yet. There's still a minor issue on android 13 devices ### Changes: - Move notification related code to a separate helper - Update notification instead of cancelling when using inline replies - Disable sound on inline replies - Reuse existing transaction api extensions for sending inline replies --- .../smsmessenger/extensions/Context.kt | 161 +++------------ .../helpers/NotificationHelper.kt | 194 ++++++++++++++++++ .../receivers/DirectReplyReceiver.kt | 50 ++--- .../smsmessenger/receivers/SmsReceiver.kt | 30 +-- .../receivers/SmsStatusSentReceiver.kt | 70 +------ 5 files changed, 247 insertions(+), 258 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt index bbd6a645..c02f99e5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt @@ -1,22 +1,13 @@ package com.simplemobiletools.smsmessenger.extensions import android.annotation.SuppressLint -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.app.PendingIntent import android.content.ContentResolver import android.content.ContentValues import android.content.Context -import android.content.Intent import android.database.Cursor import android.graphics.Bitmap import android.graphics.BitmapFactory -import android.media.AudioAttributes -import android.media.AudioManager -import android.media.RingtoneManager import android.net.Uri -import android.os.Bundle import android.os.Handler import android.os.Looper import android.provider.ContactsContract.PhoneLookup @@ -24,15 +15,15 @@ import android.provider.OpenableColumns import android.provider.Telephony.* import android.telephony.SubscriptionManager import android.text.TextUtils -import androidx.core.app.NotificationCompat -import androidx.core.app.RemoteInput +import com.bumptech.glide.Glide +import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.request.RequestOptions import com.klinker.android.send_message.Transaction.getAddressSeparator import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.models.PhoneNumber import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.smsmessenger.R -import com.simplemobiletools.smsmessenger.activities.ThreadActivity import com.simplemobiletools.smsmessenger.databases.MessagesDatabase import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.AttachmentUtils.parseAttachmentNames @@ -41,8 +32,6 @@ import com.simplemobiletools.smsmessenger.interfaces.ConversationsDao import com.simplemobiletools.smsmessenger.interfaces.MessageAttachmentsDao import com.simplemobiletools.smsmessenger.interfaces.MessagesDao import com.simplemobiletools.smsmessenger.models.* -import com.simplemobiletools.smsmessenger.receivers.DirectReplyReceiver -import com.simplemobiletools.smsmessenger.receivers.MarkAsReadReceiver import me.leolin.shortcutbadger.ShortcutBadger import java.io.FileNotFoundException @@ -58,6 +47,8 @@ val Context.messageAttachmentsDB: MessageAttachmentsDao get() = getMessagesDB(). val Context.messagesDB: MessagesDao get() = getMessagesDB().MessagesDao() +val Context.notificationHelper get() = NotificationHelper(this) + fun Context.getMessages( threadId: Long, getImageResolutions: Boolean, @@ -713,12 +704,12 @@ fun Context.getThreadId(addresses: Set): Long { } fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) { - val privateCursor = getMyContactsCursor(false, true) + val privateCursor = getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true) ensureBackgroundThread { val senderName = getNameFromAddress(address, privateCursor) Handler(Looper.getMainLooper()).post { - showMessageNotification(address, body, threadId, bitmap, senderName) + notificationHelper.showMessageNotification(address, body, threadId, bitmap, senderName) } } } @@ -746,130 +737,26 @@ fun Context.getContactFromAddress(address: String, callback: ((contact: SimpleCo } } -@SuppressLint("NewApi") -fun Context.showMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?, sender: String) { - val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) - if (isOreoPlus()) { - val audioAttributes = AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_NOTIFICATION) - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setLegacyStreamType(AudioManager.STREAM_NOTIFICATION) - .build() - - val name = getString(R.string.channel_received_sms) - val importance = NotificationManager.IMPORTANCE_HIGH - NotificationChannel(NOTIFICATION_CHANNEL, name, importance).apply { - setBypassDnd(false) - enableLights(true) - setSound(soundUri, audioAttributes) - enableVibration(true) - notificationManager.createNotificationChannel(this) - } +fun Context.getNotificationBitmap(photoUri: String): Bitmap? { + val size = resources.getDimension(R.dimen.notification_large_icon_size).toInt() + if (photoUri.isEmpty()) { + return null } - val intent = Intent(this, ThreadActivity::class.java).apply { - putExtra(THREAD_ID, threadId) - } + val options = RequestOptions() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .centerCrop() - val pendingIntent = PendingIntent.getActivity(this, threadId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE) - val summaryText = getString(R.string.new_message) - val markAsReadIntent = Intent(this, MarkAsReadReceiver::class.java).apply { - action = MARK_AS_READ - putExtra(THREAD_ID, threadId) - } - - val markAsReadPendingIntent = - PendingIntent.getBroadcast(this, threadId.hashCode(), markAsReadIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE) - var replyAction: NotificationCompat.Action? = null - - if (isNougatPlus()) { - val replyLabel = getString(R.string.reply) - val remoteInput = RemoteInput.Builder(REPLY) - .setLabel(replyLabel) - .build() - - val replyIntent = Intent(this, DirectReplyReceiver::class.java).apply { - putExtra(THREAD_ID, threadId) - putExtra(THREAD_NUMBER, address) - } - - val replyPendingIntent = - PendingIntent.getBroadcast(applicationContext, threadId.hashCode(), replyIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE) - replyAction = NotificationCompat.Action.Builder(R.drawable.ic_send_vector, replyLabel, replyPendingIntent) - .addRemoteInput(remoteInput) - .build() - } - - val largeIcon = bitmap ?: SimpleContactsHelper(this).getContactLetterIcon(sender) - val builder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL).apply { - when (config.lockScreenVisibilitySetting) { - LOCK_SCREEN_SENDER_MESSAGE -> { - setLargeIcon(largeIcon) - setStyle(getMessagesStyle(notificationManager, threadId, sender, body)) - } - LOCK_SCREEN_SENDER -> { - setContentTitle(sender) - setLargeIcon(largeIcon) - setStyle(NotificationCompat.BigTextStyle().setSummaryText(summaryText).bigText(body)) - } - } - - color = getProperPrimaryColor() - setSmallIcon(R.drawable.ic_messenger) - setContentIntent(pendingIntent) - priority = NotificationCompat.PRIORITY_MAX - setDefaults(Notification.DEFAULT_LIGHTS) - setCategory(Notification.CATEGORY_MESSAGE) - setAutoCancel(true) - setSound(soundUri, AudioManager.STREAM_NOTIFICATION) - } - - if (replyAction != null && config.lockScreenVisibilitySetting == LOCK_SCREEN_SENDER_MESSAGE) { - builder.addAction(replyAction) - } - - builder.addAction(R.drawable.ic_check_vector, getString(R.string.mark_as_read), markAsReadPendingIntent) - .setChannelId(NOTIFICATION_CHANNEL) - - notificationManager.notify(threadId.hashCode(), builder.build()) -} - -private fun Context.getMessagesStyle( - notificationManager: NotificationManager, - threadId: Long, - sender: String, - body: String -): NotificationCompat.MessagingStyle { - val oldMessages = getOldMessages(notificationManager, threadId) - val messages = NotificationCompat.MessagingStyle(getString(R.string.me)) - oldMessages.forEach { - messages.addMessage(it) - } - val currentMessage = NotificationCompat.MessagingStyle.Message(body, System.currentTimeMillis(), sender) - messages.addMessage(currentMessage) - return messages -} - -private fun getOldMessages(notificationManager: NotificationManager, threadId: Long): List { - if (!isNougatPlus()) { - return arrayListOf() - } - val currentNotification = notificationManager.activeNotifications.find { it.id == threadId.hashCode() } - return if (currentNotification != null) { - val messages = currentNotification.notification.extras.getParcelableArray(NotificationCompat.EXTRA_MESSAGES) - val result = arrayListOf() - messages?.forEach { - val bundle = it as Bundle - val sender = bundle.getCharSequence("sender") - val text = bundle.getCharSequence("text") - val time = bundle.getLong("time") - val message = NotificationCompat.MessagingStyle.Message(text, time, sender) - result.add(message) - } - return result - } else { - arrayListOf() + return try { + Glide.with(this) + .asBitmap() + .load(photoUri) + .apply(options) + .apply(RequestOptions.circleCropTransform()) + .into(size, size) + .get() + } catch (e: Exception) { + null } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt new file mode 100644 index 00000000..a8d56678 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt @@ -0,0 +1,194 @@ +package com.simplemobiletools.smsmessenger.helpers + +import android.annotation.SuppressLint +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager.IMPORTANCE_HIGH +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.media.AudioAttributes +import android.media.AudioManager +import android.media.RingtoneManager +import androidx.core.app.NotificationCompat +import androidx.core.app.Person +import androidx.core.app.RemoteInput +import com.simplemobiletools.commons.extensions.getProperPrimaryColor +import com.simplemobiletools.commons.extensions.notificationManager +import com.simplemobiletools.commons.helpers.SimpleContactsHelper +import com.simplemobiletools.commons.helpers.isNougatPlus +import com.simplemobiletools.commons.helpers.isOreoPlus +import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.activities.ThreadActivity +import com.simplemobiletools.smsmessenger.extensions.config +import com.simplemobiletools.smsmessenger.receivers.DirectReplyReceiver +import com.simplemobiletools.smsmessenger.receivers.MarkAsReadReceiver + +class NotificationHelper(private val context: Context) { + + private val notificationManager = context.notificationManager + private val soundUri get() = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) + private val user = Person.Builder() + .setName(context.getString(R.string.me)) + .build() + + @SuppressLint("NewApi") + fun showMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?, sender: String?, alertOnlyOnce: Boolean = false) { + maybeCreateChannel(name = context.getString(R.string.channel_received_sms)) + + val notificationId = threadId.hashCode() + val contentIntent = Intent(context, ThreadActivity::class.java).apply { + putExtra(THREAD_ID, threadId) + } + val contentPendingIntent = + PendingIntent.getActivity(context, notificationId, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE) + + val markAsReadIntent = Intent(context, MarkAsReadReceiver::class.java).apply { + action = MARK_AS_READ + putExtra(THREAD_ID, threadId) + } + val markAsReadPendingIntent = + PendingIntent.getBroadcast(context, notificationId, markAsReadIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE) + + var replyAction: NotificationCompat.Action? = null + if (isNougatPlus()) { + val replyLabel = context.getString(R.string.reply) + val remoteInput = RemoteInput.Builder(REPLY) + .setLabel(replyLabel) + .build() + + val replyIntent = Intent(context, DirectReplyReceiver::class.java).apply { + putExtra(THREAD_ID, threadId) + putExtra(THREAD_NUMBER, address) + } + + val replyPendingIntent = + PendingIntent.getBroadcast( + context.applicationContext, + notificationId, + replyIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE + ) + replyAction = NotificationCompat.Action.Builder(R.drawable.ic_send_vector, replyLabel, replyPendingIntent) + .addRemoteInput(remoteInput) + .build() + } + + val largeIcon = bitmap ?: if (sender != null) { + SimpleContactsHelper(context).getContactLetterIcon(sender) + } else { + null + } + val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL).apply { + when (context.config.lockScreenVisibilitySetting) { + LOCK_SCREEN_SENDER_MESSAGE -> { + setLargeIcon(largeIcon) + setStyle(getMessagesStyle(address, body, notificationId, sender)) + } + LOCK_SCREEN_SENDER -> { + setContentTitle(sender) + setLargeIcon(largeIcon) + val summaryText = context.getString(R.string.new_message) + setStyle(NotificationCompat.BigTextStyle().setSummaryText(summaryText).bigText(body)) + } + } + + color = context.getProperPrimaryColor() + setSmallIcon(R.drawable.ic_messenger) + setContentIntent(contentPendingIntent) + priority = NotificationCompat.PRIORITY_MAX + setDefaults(Notification.DEFAULT_LIGHTS) + setCategory(Notification.CATEGORY_MESSAGE) + setAutoCancel(true) + setOnlyAlertOnce(alertOnlyOnce) + setSound(soundUri, AudioManager.STREAM_NOTIFICATION) + } + + if (replyAction != null && context.config.lockScreenVisibilitySetting == LOCK_SCREEN_SENDER_MESSAGE) { + builder.addAction(replyAction) + } + + builder.addAction(R.drawable.ic_check_vector, context.getString(R.string.mark_as_read), markAsReadPendingIntent) + .setChannelId(NOTIFICATION_CHANNEL) + + notificationManager.notify(notificationId, builder.build()) + } + + @SuppressLint("NewApi") + fun showSendingFailedNotification(recipientName: String, threadId: Long) { + maybeCreateChannel(name = context.getString(R.string.message_not_sent_short)) + + val notificationId = threadId.hashCode() + val intent = Intent(context, ThreadActivity::class.java).apply { + putExtra(THREAD_ID, threadId) + } + val contentPendingIntent = PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE) + + val summaryText = String.format(context.getString(R.string.message_sending_error), recipientName) + val largeIcon = SimpleContactsHelper(context).getContactLetterIcon(recipientName) + val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL) + .setContentTitle(context.getString(R.string.message_not_sent_short)) + .setContentText(summaryText) + .setColor(context.getProperPrimaryColor()) + .setSmallIcon(R.drawable.ic_messenger) + .setLargeIcon(largeIcon) + .setStyle(NotificationCompat.BigTextStyle().bigText(summaryText)) + .setContentIntent(contentPendingIntent) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setDefaults(Notification.DEFAULT_LIGHTS) + .setCategory(Notification.CATEGORY_MESSAGE) + .setAutoCancel(true) + .setChannelId(NOTIFICATION_CHANNEL) + + notificationManager.notify(notificationId, builder.build()) + } + + private fun maybeCreateChannel(name: String) { + if (isOreoPlus()) { + val audioAttributes = AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_NOTIFICATION) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setLegacyStreamType(AudioManager.STREAM_NOTIFICATION) + .build() + + NotificationChannel(NOTIFICATION_CHANNEL, name, IMPORTANCE_HIGH).apply { + setBypassDnd(false) + enableLights(true) + setSound(soundUri, audioAttributes) + enableVibration(true) + notificationManager.createNotificationChannel(this) + } + } + } + + private fun getMessagesStyle(address: String, body: String, notificationId: Int, name: String?): NotificationCompat.MessagingStyle { + val sender = if (name != null) { + Person.Builder() + .setName(name) + .setKey(address) + .build() + } else null + + return NotificationCompat.MessagingStyle(user).also { style -> + getOldMessages(notificationId).forEach { + style.addMessage(it) + } + val newMessage = NotificationCompat.MessagingStyle.Message(body, System.currentTimeMillis(), sender) + style.addMessage(newMessage) + } + } + + private fun getOldMessages(notificationId: Int): List { + if (!isNougatPlus()) { + return emptyList() + } + val currentNotification = notificationManager.activeNotifications.find { it.id == notificationId } + return if (currentNotification != null) { + val activeStyle = NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification(currentNotification.notification) + return activeStyle?.messages.orEmpty() + } else { + emptyList() + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt index be412fb7..23e9299d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt @@ -4,58 +4,58 @@ import android.annotation.SuppressLint import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.os.Handler +import android.os.Looper import androidx.core.app.RemoteInput -import com.klinker.android.send_message.Transaction -import com.simplemobiletools.commons.extensions.notificationManager import com.simplemobiletools.commons.extensions.showErrorToast +import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.helpers.REPLY import com.simplemobiletools.smsmessenger.helpers.THREAD_ID import com.simplemobiletools.smsmessenger.helpers.THREAD_NUMBER -import com.simplemobiletools.smsmessenger.helpers.getSendMessageSettings +import com.simplemobiletools.smsmessenger.helpers.sendMessage class DirectReplyReceiver : BroadcastReceiver() { @SuppressLint("MissingPermission") override fun onReceive(context: Context, intent: Intent) { val address = intent.getStringExtra(THREAD_NUMBER) val threadId = intent.getLongExtra(THREAD_ID, 0L) - var msg = RemoteInput.getResultsFromIntent(intent)?.getCharSequence(REPLY)?.toString() ?: return + var body = RemoteInput.getResultsFromIntent(intent)?.getCharSequence(REPLY)?.toString() ?: return - msg = context.removeDiacriticsIfNeeded(msg) + body = context.removeDiacriticsIfNeeded(body) - val settings = context.getSendMessageSettings() if (address != null) { + var subscriptionId: Int? = null val availableSIMs = context.subscriptionManagerCompat().activeSubscriptionInfoList if ((availableSIMs?.size ?: 0) > 1) { val currentSIMCardIndex = context.config.getUseSIMIdAtNumber(address) val wantedId = availableSIMs.getOrNull(currentSIMCardIndex) if (wantedId != null) { - settings.subscriptionId = wantedId.subscriptionId + subscriptionId = wantedId.subscriptionId } } - } - val transaction = Transaction(context, settings) - val message = com.klinker.android.send_message.Message(msg, address) + ensureBackgroundThread { + try { + context.sendMessage(body, listOf(address), subscriptionId, emptyList()) + val message = context.getMessages(threadId, getImageResolutions = false, includeScheduledMessages = false, limit = 1).firstOrNull() + if (message != null) { + context.messagesDB.insertOrUpdate(message) + } + } catch (e: Exception) { + context.showErrorToast(e) + } - ensureBackgroundThread { - try { - val smsSentIntent = Intent(context, SmsStatusSentReceiver::class.java) - val deliveredIntent = Intent(context, SmsStatusDeliveredReceiver::class.java) + val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address) + val bitmap = context.getNotificationBitmap(photoUri) + Handler(Looper.getMainLooper()).post { + context.notificationHelper.showMessageNotification(address, body, threadId, bitmap, sender = null, alertOnlyOnce = true) + } - transaction.setExplicitBroadcastForSentSms(smsSentIntent) - transaction.setExplicitBroadcastForDeliveredSms(deliveredIntent) - - transaction.sendNewMessage(message) - } catch (e: Exception) { - context.showErrorToast(e) + context.markThreadMessagesRead(threadId) + context.conversationsDB.markRead(threadId) } - - context.notificationManager.cancel(threadId.hashCode()) - - context.markThreadMessagesRead(threadId) - context.conversationsDB.markRead(threadId) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsReceiver.kt index 223326ba..bded30f1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsReceiver.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsReceiver.kt @@ -3,13 +3,9 @@ package com.simplemobiletools.smsmessenger.receivers import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.graphics.Bitmap import android.os.Handler import android.os.Looper import android.provider.Telephony -import com.bumptech.glide.Glide -import com.bumptech.glide.load.engine.DiskCacheStrategy -import com.bumptech.glide.request.RequestOptions import com.simplemobiletools.commons.extensions.baseConfig import com.simplemobiletools.commons.extensions.getMyContactsCursor import com.simplemobiletools.commons.extensions.isNumberBlocked @@ -17,7 +13,6 @@ import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.models.PhoneNumber import com.simplemobiletools.commons.models.SimpleContact -import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.helpers.refreshMessages import com.simplemobiletools.smsmessenger.models.Message @@ -63,7 +58,7 @@ class SmsReceiver : BroadcastReceiver() { context: Context, address: String, subject: String, body: String, date: Long, read: Int, threadId: Long, type: Int, subscriptionId: Int, status: Int ) { val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address) - val bitmap = getPhotoForNotification(photoUri, context) + val bitmap = context.getNotificationBitmap(photoUri) Handler(Looper.getMainLooper()).post { if (!context.isNumberBlocked(address)) { val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true) @@ -97,27 +92,4 @@ class SmsReceiver : BroadcastReceiver() { } } } - - private fun getPhotoForNotification(photoUri: String, context: Context): Bitmap? { - val size = context.resources.getDimension(R.dimen.notification_large_icon_size).toInt() - if (photoUri.isEmpty()) { - return null - } - - val options = RequestOptions() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - - return try { - Glide.with(context) - .asBitmap() - .load(photoUri) - .apply(options) - .apply(RequestOptions.circleCropTransform()) - .into(size, size) - .get() - } catch (e: Exception) { - null - } - } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt index 24c0486e..1c5635a5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt @@ -1,31 +1,15 @@ package com.simplemobiletools.smsmessenger.receivers -import android.annotation.SuppressLint -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.app.PendingIntent import android.content.Context import android.content.Intent -import android.media.AudioAttributes -import android.media.AudioManager -import android.media.RingtoneManager import android.net.Uri import android.os.Handler import android.os.Looper import android.provider.Telephony -import androidx.core.app.NotificationCompat import com.klinker.android.send_message.SentReceiver import com.simplemobiletools.commons.extensions.getMyContactsCursor -import com.simplemobiletools.commons.extensions.getProperPrimaryColor -import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.ensureBackgroundThread -import com.simplemobiletools.commons.helpers.isOreoPlus -import com.simplemobiletools.smsmessenger.R -import com.simplemobiletools.smsmessenger.activities.ThreadActivity import com.simplemobiletools.smsmessenger.extensions.* -import com.simplemobiletools.smsmessenger.helpers.NOTIFICATION_CHANNEL -import com.simplemobiletools.smsmessenger.helpers.THREAD_ID import com.simplemobiletools.smsmessenger.helpers.refreshMessages class SmsStatusSentReceiver : SentReceiver() { @@ -59,61 +43,13 @@ class SmsStatusSentReceiver : SentReceiver() { private fun showSendingFailedNotification(context: Context, messageId: Long) { Handler(Looper.getMainLooper()).post { - val privateCursor = context.getMyContactsCursor(false, true) + val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true) ensureBackgroundThread { val address = context.getMessageRecipientAddress(messageId) val threadId = context.getThreadId(address) - val senderName = context.getNameFromAddress(address, privateCursor) - showNotification(context, senderName, threadId) + val recipientName = context.getNameFromAddress(address, privateCursor) + context.notificationHelper.showSendingFailedNotification(recipientName, threadId) } } } - - @SuppressLint("NewApi") - private fun showNotification(context: Context, recipientName: String, threadId: Long) { - val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) - if (isOreoPlus()) { - val audioAttributes = AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_NOTIFICATION) - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setLegacyStreamType(AudioManager.STREAM_NOTIFICATION) - .build() - - val name = context.getString(R.string.message_not_sent_short) - val importance = NotificationManager.IMPORTANCE_HIGH - NotificationChannel(NOTIFICATION_CHANNEL, name, importance).apply { - setBypassDnd(false) - enableLights(true) - setSound(soundUri, audioAttributes) - enableVibration(true) - notificationManager.createNotificationChannel(this) - } - } - - val intent = Intent(context, ThreadActivity::class.java).apply { - putExtra(THREAD_ID, threadId) - } - - val pendingIntent = PendingIntent.getActivity(context, threadId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE) - val summaryText = String.format(context.getString(R.string.message_sending_error), recipientName) - - val largeIcon = SimpleContactsHelper(context).getContactLetterIcon(recipientName) - val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL) - .setContentTitle(context.getString(R.string.message_not_sent_short)) - .setContentText(summaryText) - .setColor(context.getProperPrimaryColor()) - .setSmallIcon(R.drawable.ic_messenger) - .setLargeIcon(largeIcon) - .setStyle(NotificationCompat.BigTextStyle().bigText(summaryText)) - .setContentIntent(pendingIntent) - .setPriority(NotificationCompat.PRIORITY_MAX) - .setDefaults(Notification.DEFAULT_LIGHTS) - .setCategory(Notification.CATEGORY_MESSAGE) - .setAutoCancel(true) - .setSound(soundUri, AudioManager.STREAM_NOTIFICATION) - .setChannelId(NOTIFICATION_CHANNEL) - - notificationManager.notify(threadId.hashCode(), builder.build()) - } } From 453d879c82ff8344251568eadad2b2944e2f76bf Mon Sep 17 00:00:00 2001 From: Naveen Date: Sun, 4 Dec 2022 00:57:14 +0530 Subject: [PATCH 02/10] Minor readability improvement --- .../smsmessenger/helpers/NotificationHelper.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt index a8d56678..45fcae7b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt @@ -152,7 +152,9 @@ class NotificationHelper(private val context: Context) { .setLegacyStreamType(AudioManager.STREAM_NOTIFICATION) .build() - NotificationChannel(NOTIFICATION_CHANNEL, name, IMPORTANCE_HIGH).apply { + val id = NOTIFICATION_CHANNEL + val importance = IMPORTANCE_HIGH + NotificationChannel(id, name, importance).apply { setBypassDnd(false) enableLights(true) setSound(soundUri, audioAttributes) From 860e6c255bc5a93d2845fca0bea2bc87ea9bdf6a Mon Sep 17 00:00:00 2001 From: Naveen Date: Sun, 4 Dec 2022 23:23:16 +0530 Subject: [PATCH 03/10] Minor code improvement --- .../smsmessenger/helpers/NotificationHelper.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt index 45fcae7b..0a226824 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt @@ -170,7 +170,9 @@ class NotificationHelper(private val context: Context) { .setName(name) .setKey(address) .build() - } else null + } else { + null + } return NotificationCompat.MessagingStyle(user).also { style -> getOldMessages(notificationId).forEach { @@ -188,7 +190,7 @@ class NotificationHelper(private val context: Context) { val currentNotification = notificationManager.activeNotifications.find { it.id == notificationId } return if (currentNotification != null) { val activeStyle = NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification(currentNotification.notification) - return activeStyle?.messages.orEmpty() + activeStyle?.messages.orEmpty() } else { emptyList() } From 6e7dbb90561b63589e7a6aa88b7738d2b0ebba89 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 7 Dec 2022 22:39:04 +0530 Subject: [PATCH 04/10] Properly update sent message type --- .../smsmessenger/receivers/SmsStatusSentReceiver.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt index 1c5635a5..32db10ea 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt @@ -1,5 +1,6 @@ package com.simplemobiletools.smsmessenger.receivers +import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri @@ -19,11 +20,13 @@ class SmsStatusSentReceiver : SentReceiver() { val uri = Uri.parse(intent.getStringExtra("message_uri")) val messageId = uri?.lastPathSegment?.toLong() ?: 0L ensureBackgroundThread { - val type = if (intent.extras!!.containsKey("errorCode")) { + if (intent.extras!!.containsKey("errorCode")) { showSendingFailedNotification(context, messageId) - Telephony.Sms.MESSAGE_TYPE_FAILED - } else { + } + val type = if (receiverResultCode == Activity.RESULT_OK) { Telephony.Sms.MESSAGE_TYPE_SENT + } else { + Telephony.Sms.MESSAGE_TYPE_FAILED } context.updateMessageType(messageId, type) From 2fc70b2dc5799d6ad57c19b878a70d68972aa410 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 7 Dec 2022 23:43:31 +0530 Subject: [PATCH 05/10] Fetch drafts on a background thread --- .../adapters/ConversationsAdapter.kt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt index bca75629..cdaffab0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt @@ -40,7 +40,9 @@ class ConversationsAdapter( init { setupDragListener(true) - fetchDrafts(drafts) + ensureBackgroundThread { + fetchDrafts(drafts) + } setHasStableIds(true) registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { @@ -314,11 +316,15 @@ class ConversationsAdapter( } fun updateDrafts() { - val newDrafts = HashMap() - fetchDrafts(newDrafts) - if (drafts.hashCode() != newDrafts.hashCode()) { - drafts = newDrafts - notifyDataSetChanged() + ensureBackgroundThread { + val newDrafts = HashMap() + fetchDrafts(newDrafts) + if (drafts.hashCode() != newDrafts.hashCode()) { + drafts = newDrafts + activity.runOnUiThread { + notifyDataSetChanged() + } + } } } From 0523d9324325fc2c43a19eca4d0574951f156845 Mon Sep 17 00:00:00 2001 From: Naveen Date: Thu, 8 Dec 2022 01:40:34 +0530 Subject: [PATCH 06/10] Only show failure notification when in background --- app/build.gradle | 1 + .../smsmessenger/receivers/SmsStatusSentReceiver.kt | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1ef38dc6..db58dfb2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -70,6 +70,7 @@ dependencies { implementation "me.leolin:ShortcutBadger:1.1.22" implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'com.googlecode.ez-vcard:ez-vcard:0.11.3' + implementation 'androidx.lifecycle:lifecycle-process:2.5.1' kapt "androidx.room:room-compiler:2.4.3" implementation "androidx.room:room-runtime:2.4.3" diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt index 32db10ea..3b324d63 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt @@ -7,6 +7,8 @@ import android.net.Uri import android.os.Handler import android.os.Looper import android.provider.Telephony +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.ProcessLifecycleOwner import com.klinker.android.send_message.SentReceiver import com.simplemobiletools.commons.extensions.getMyContactsCursor import com.simplemobiletools.commons.helpers.ensureBackgroundThread @@ -20,12 +22,10 @@ class SmsStatusSentReceiver : SentReceiver() { val uri = Uri.parse(intent.getStringExtra("message_uri")) val messageId = uri?.lastPathSegment?.toLong() ?: 0L ensureBackgroundThread { - if (intent.extras!!.containsKey("errorCode")) { - showSendingFailedNotification(context, messageId) - } val type = if (receiverResultCode == Activity.RESULT_OK) { Telephony.Sms.MESSAGE_TYPE_SENT } else { + showSendingFailedNotification(context, messageId) Telephony.Sms.MESSAGE_TYPE_FAILED } @@ -46,6 +46,9 @@ class SmsStatusSentReceiver : SentReceiver() { private fun showSendingFailedNotification(context: Context, messageId: Long) { Handler(Looper.getMainLooper()).post { + if (ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) { + return@post + } val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true) ensureBackgroundThread { val address = context.getMessageRecipientAddress(messageId) From 35e914188850bee52ec4e3af181e344453bf196b Mon Sep 17 00:00:00 2001 From: Naveen Date: Thu, 8 Dec 2022 01:42:43 +0530 Subject: [PATCH 07/10] Use a separate notification id for failure notifications This way failure notifications won't overwrite the existing chat notifications (if there are any) as they also use thread id as notification id --- .../smsmessenger/helpers/NotificationHelper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt index 0a226824..827cc804 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/NotificationHelper.kt @@ -119,7 +119,7 @@ class NotificationHelper(private val context: Context) { fun showSendingFailedNotification(recipientName: String, threadId: Long) { maybeCreateChannel(name = context.getString(R.string.message_not_sent_short)) - val notificationId = threadId.hashCode() + val notificationId = generateRandomId().hashCode() val intent = Intent(context, ThreadActivity::class.java).apply { putExtra(THREAD_ID, threadId) } From f1f27eeb9dc57cb3dd73f1be077189d963e73f36 Mon Sep 17 00:00:00 2001 From: Naveen Date: Thu, 8 Dec 2022 02:06:20 +0530 Subject: [PATCH 08/10] Update message in local db when using inline replies --- .../smsmessenger/receivers/DirectReplyReceiver.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt index 23e9299d..496e0a63 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt @@ -39,7 +39,7 @@ class DirectReplyReceiver : BroadcastReceiver() { ensureBackgroundThread { try { context.sendMessage(body, listOf(address), subscriptionId, emptyList()) - val message = context.getMessages(threadId, getImageResolutions = false, includeScheduledMessages = false, limit = 1).firstOrNull() + val message = context.getMessages(threadId, getImageResolutions = false, includeScheduledMessages = false, limit = 1).lastOrNull() if (message != null) { context.messagesDB.insertOrUpdate(message) } From 716ebad21ed758c1fccd0f70448048473619d63a Mon Sep 17 00:00:00 2001 From: Naveen Date: Fri, 9 Dec 2022 02:08:35 +0530 Subject: [PATCH 09/10] Remove fade effect as items are already animated --- .../smsmessenger/adapters/ThreadAdapter.kt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ThreadAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ThreadAdapter.kt index 92cd84ed..4d2ccf76 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ThreadAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ThreadAdapter.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.content.Intent import android.graphics.Color import android.graphics.Typeface +import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import android.util.Size @@ -18,7 +19,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.load.resource.bitmap.CenterCrop import com.bumptech.glide.load.resource.bitmap.FitCenter -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.Target @@ -291,7 +291,20 @@ class ThreadAdapter( thread_message_body.setLinkTextColor(context.getProperPrimaryColor()) if (!activity.isFinishing && !activity.isDestroyed) { - SimpleContactsHelper(context).loadContactImage(message.senderPhotoUri, thread_message_sender_photo, message.senderName) + val contactLetterIcon = SimpleContactsHelper(context).getContactLetterIcon(message.senderName) + val placeholder = BitmapDrawable(context.resources, contactLetterIcon) + + val options = RequestOptions() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .error(placeholder) + .centerCrop() + + Glide.with(context) + .load(message.senderPhotoUri) + .placeholder(placeholder) + .apply(options) + .apply(RequestOptions.circleCropTransform()) + .into(thread_message_sender_photo) } } } @@ -341,7 +354,6 @@ class ThreadAdapter( var builder = Glide.with(context) .load(uri) - .transition(DrawableTransitionOptions.withCrossFade()) .apply(options) .listener(object : RequestListener { override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { From 7f9f925da4787a15cc693294abbbbe526bb1d1e6 Mon Sep 17 00:00:00 2001 From: Naveen Date: Sun, 11 Dec 2022 14:45:47 +0530 Subject: [PATCH 10/10] Properly update text colors on theme change and some code improvements --- .../smsmessenger/activities/MainActivity.kt | 78 ++++++++++++------- .../adapters/ConversationsAdapter.kt | 6 +- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt index b1a072b9..08753e03 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt @@ -89,15 +89,18 @@ class MainActivity : SimpleActivity() { super.onResume() setupToolbar(main_toolbar) - if (storedTextColor != getProperTextColor()) { - (conversations_list.adapter as? ConversationsAdapter)?.updateTextColor(getProperTextColor()) + getOrCreateConversationsAdapter().apply { + if (storedTextColor != getProperTextColor()) { + updateTextColor(getProperTextColor()) + } + + if (storedFontSize != config.fontSize) { + updateFontSize() + } + + updateDrafts() } - if (storedFontSize != config.fontSize) { - (conversations_list.adapter as? ConversationsAdapter)?.updateFontSize() - } - - (conversations_list.adapter as? ConversationsAdapter)?.updateDrafts() updateTextColors(main_coordinator) val properPrimaryColor = getProperPrimaryColor() @@ -285,6 +288,25 @@ class MainActivity : SimpleActivity() { } } + private fun getOrCreateConversationsAdapter(): ConversationsAdapter { + var currAdapter = conversations_list.adapter + if (currAdapter == null) { + hideKeyboard() + currAdapter = ConversationsAdapter( + activity = this, + recyclerView = conversations_list, + onRefresh = { notifyDatasetChanged() }, + itemClick = { handleConversationClick(it) } + ) + + conversations_list.adapter = currAdapter + if (areSystemAnimationsEnabled) { + conversations_list.scheduleLayoutAnimation() + } + } + return currAdapter as ConversationsAdapter + } + private fun setupConversations(conversations: ArrayList) { val hasConversations = conversations.isNotEmpty() val sortedConversations = conversations.sortedWith( @@ -301,36 +323,32 @@ class MainActivity : SimpleActivity() { no_conversations_placeholder_2.beGone() } - val currAdapter = conversations_list.adapter - if (currAdapter == null) { - hideKeyboard() - ConversationsAdapter(this, conversations_list) { - Intent(this, ThreadActivity::class.java).apply { - val conversation = it as Conversation - putExtra(THREAD_ID, conversation.threadId) - putExtra(THREAD_TITLE, conversation.title) - startActivity(this) - } - }.apply { - conversations_list.adapter = this - updateConversations(sortedConversations) - } - - if (areSystemAnimationsEnabled) { - conversations_list.scheduleLayoutAnimation() - } - } else { - try { - (currAdapter as ConversationsAdapter).updateConversations(sortedConversations) { - if (currAdapter.currentList.isEmpty()) { + try { + getOrCreateConversationsAdapter().apply { + updateConversations(sortedConversations) { + if (currentList.isEmpty()) { conversations_fastscroller.beGone() no_conversations_placeholder.text = getString(R.string.no_conversations_found) no_conversations_placeholder.beVisible() no_conversations_placeholder_2.beVisible() } } - } catch (ignored: Exception) { } + } catch (ignored: Exception) { + } + } + + @SuppressLint("NotifyDataSetChanged") + private fun notifyDatasetChanged() { + getOrCreateConversationsAdapter().notifyDataSetChanged() + } + + private fun handleConversationClick(any: Any) { + Intent(this, ThreadActivity::class.java).apply { + val conversation = any as Conversation + putExtra(THREAD_ID, conversation.threadId) + putExtra(THREAD_TITLE, conversation.title) + startActivity(this) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt index cdaffab0..4797800e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt @@ -1,5 +1,6 @@ package com.simplemobiletools.smsmessenger.adapters +import android.annotation.SuppressLint import android.content.Intent import android.graphics.Typeface import android.os.Parcelable @@ -31,8 +32,9 @@ import com.simplemobiletools.smsmessenger.models.Conversation import kotlinx.android.synthetic.main.item_conversation.view.* class ConversationsAdapter( - activity: SimpleActivity, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit -) : MyRecyclerViewListAdapter(activity, recyclerView, ConversationDiffCallback(), itemClick), RecyclerViewFastScroller.OnPopupTextUpdate { + activity: SimpleActivity, recyclerView: MyRecyclerView, onRefresh: () -> Unit, itemClick: (Any) -> Unit +) : MyRecyclerViewListAdapter(activity, recyclerView, ConversationDiffCallback(), itemClick, onRefresh), + RecyclerViewFastScroller.OnPopupTextUpdate { private var fontSize = activity.getTextSize() private var drafts = HashMap()