mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-26 23:25:20 +03:00
Refactor - extracted common method to load avatars for notifications
Signed-off-by: Dariusz Olszewski <starypatyk@users.noreply.github.com>
This commit is contained in:
parent
3b7ca4a31a
commit
d4bdd88588
3 changed files with 43 additions and 72 deletions
|
@ -37,14 +37,6 @@ import android.util.Base64;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare;
|
import com.bluelinelabs.logansquare.LoganSquare;
|
||||||
import com.facebook.common.executors.UiThreadImmediateExecutorService;
|
|
||||||
import com.facebook.common.references.CloseableReference;
|
|
||||||
import com.facebook.datasource.DataSource;
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
|
||||||
import com.facebook.imagepipeline.image.CloseableImage;
|
|
||||||
import com.facebook.imagepipeline.postprocessors.RoundAsCirclePostprocessor;
|
|
||||||
import com.facebook.imagepipeline.request.ImageRequest;
|
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.activities.CallActivity;
|
import com.nextcloud.talk.activities.CallActivity;
|
||||||
import com.nextcloud.talk.activities.MainActivity;
|
import com.nextcloud.talk.activities.MainActivity;
|
||||||
|
@ -61,7 +53,6 @@ import com.nextcloud.talk.models.json.push.DecryptedPushMessage;
|
||||||
import com.nextcloud.talk.models.json.push.NotificationUser;
|
import com.nextcloud.talk.models.json.push.NotificationUser;
|
||||||
import com.nextcloud.talk.receivers.DirectReplyReceiver;
|
import com.nextcloud.talk.receivers.DirectReplyReceiver;
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
import com.nextcloud.talk.utils.ApiUtils;
|
||||||
import com.nextcloud.talk.utils.DisplayUtils;
|
|
||||||
import com.nextcloud.talk.utils.DoNotDisturbUtils;
|
import com.nextcloud.talk.utils.DoNotDisturbUtils;
|
||||||
import com.nextcloud.talk.utils.NotificationUtils;
|
import com.nextcloud.talk.utils.NotificationUtils;
|
||||||
import com.nextcloud.talk.utils.PushUtils;
|
import com.nextcloud.talk.utils.PushUtils;
|
||||||
|
@ -93,7 +84,6 @@ import androidx.core.app.NotificationCompat.MessagingStyle;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
import androidx.core.app.Person;
|
import androidx.core.app.Person;
|
||||||
import androidx.core.app.RemoteInput;
|
import androidx.core.app.RemoteInput;
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
|
||||||
import androidx.emoji.text.EmojiCompat;
|
import androidx.emoji.text.EmojiCompat;
|
||||||
import androidx.work.Data;
|
import androidx.work.Data;
|
||||||
import androidx.work.Worker;
|
import androidx.work.Worker;
|
||||||
|
@ -395,9 +385,10 @@ public class NotificationWorker extends Worker {
|
||||||
final NotificationUser notificationUser = decryptedPushMessage.getNotificationUser();
|
final NotificationUser notificationUser = decryptedPushMessage.getNotificationUser();
|
||||||
final String userType = notificationUser.getType();
|
final String userType = notificationUser.getType();
|
||||||
|
|
||||||
MessagingStyle style = activeStatusBarNotification != null ?
|
MessagingStyle style = null;
|
||||||
MessagingStyle.extractMessagingStyleFromNotification(activeStatusBarNotification.getNotification()) :
|
if (activeStatusBarNotification != null) {
|
||||||
null;
|
style = MessagingStyle.extractMessagingStyleFromNotification(activeStatusBarNotification.getNotification());
|
||||||
|
}
|
||||||
|
|
||||||
Person.Builder person =
|
Person.Builder person =
|
||||||
new Person.Builder()
|
new Person.Builder()
|
||||||
|
@ -413,31 +404,11 @@ public class NotificationWorker extends Worker {
|
||||||
String avatarUrl = "user".equals(userType) ?
|
String avatarUrl = "user".equals(userType) ?
|
||||||
ApiUtils.getUrlForAvatar(baseUrl, notificationUser.getId(), false) :
|
ApiUtils.getUrlForAvatar(baseUrl, notificationUser.getId(), false) :
|
||||||
ApiUtils.getUrlForGuestAvatar(baseUrl, notificationUser.getName(), false);
|
ApiUtils.getUrlForGuestAvatar(baseUrl, notificationUser.getName(), false);
|
||||||
|
person.setIcon(NotificationUtils.INSTANCE.loadAvatarSync(avatarUrl));
|
||||||
ImageRequest imageRequest = DisplayUtils.getImageRequestForUrl(avatarUrl, null);
|
|
||||||
Fresco.getImagePipeline().fetchDecodedImage(imageRequest, context).subscribe(
|
|
||||||
new BaseBitmapDataSubscriber() {
|
|
||||||
@Override
|
|
||||||
protected void onNewResultImpl(Bitmap bitmap) {
|
|
||||||
if (bitmap != null) {
|
|
||||||
new RoundAsCirclePostprocessor(true).process(bitmap);
|
|
||||||
person.setIcon(IconCompat.createWithBitmap(bitmap));
|
|
||||||
notificationBuilder.setStyle(getStyle(person.build(), style));
|
|
||||||
sendNotificationWithId(notificationId, notificationBuilder.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
|
|
||||||
notificationBuilder.setStyle(getStyle(person.build(), style));
|
|
||||||
sendNotificationWithId(notificationId, notificationBuilder.build());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
UiThreadImmediateExecutorService.getInstance());
|
|
||||||
} else {
|
|
||||||
notificationBuilder.setStyle(getStyle(person.build(), style));
|
|
||||||
sendNotificationWithId(notificationId, notificationBuilder.build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notificationBuilder.setStyle(getStyle(person.build(), style));
|
||||||
|
sendNotificationWithId(notificationId, notificationBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addReplyAction(NotificationCompat.Builder notificationBuilder, int notificationId) {
|
private void addReplyAction(NotificationCompat.Builder notificationBuilder, int notificationId) {
|
||||||
|
|
|
@ -25,28 +25,18 @@ import android.app.NotificationManager
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.app.Person
|
import androidx.core.app.Person
|
||||||
import androidx.core.app.RemoteInput
|
import androidx.core.app.RemoteInput
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.facebook.common.executors.UiThreadImmediateExecutorService
|
|
||||||
import com.facebook.common.references.CloseableReference
|
|
||||||
import com.facebook.datasource.DataSource
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
|
||||||
import com.facebook.imagepipeline.image.CloseableImage
|
|
||||||
import com.facebook.imagepipeline.postprocessors.RoundAsCirclePostprocessor
|
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.models.database.UserEntity
|
import com.nextcloud.talk.models.database.UserEntity
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.NotificationUtils
|
import com.nextcloud.talk.utils.NotificationUtils
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_ID
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_ID
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||||
|
@ -110,7 +100,7 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
override fun onNext(genericOverall: GenericOverall) {
|
override fun onNext(genericOverall: GenericOverall) {
|
||||||
loadAvatar(::confirmReplySent)
|
confirmReplySent()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
|
@ -124,27 +114,6 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAvatar(callback: (avatarIcon: IconCompat) -> Unit) {
|
|
||||||
val avatarUrl = ApiUtils.getUrlForAvatar(currentUser.baseUrl, currentUser.userId, false)
|
|
||||||
val imageRequest = DisplayUtils.getImageRequestForUrl(avatarUrl, currentUser)
|
|
||||||
val dataSource = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, null)
|
|
||||||
dataSource.subscribe(
|
|
||||||
object : BaseBitmapDataSubscriber() {
|
|
||||||
override fun onNewResultImpl(bitmap: Bitmap?) {
|
|
||||||
if (bitmap != null) {
|
|
||||||
RoundAsCirclePostprocessor(true).process(bitmap)
|
|
||||||
callback(IconCompat.createWithBitmap(bitmap))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage?>>) {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
},
|
|
||||||
UiThreadImmediateExecutorService.getInstance()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
private fun findActiveNotification(notificationId: Int): Notification? {
|
private fun findActiveNotification(notificationId: Int): Notification? {
|
||||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
@ -152,7 +121,7 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
private fun confirmReplySent(avatarIcon: IconCompat) {
|
private fun confirmReplySent() {
|
||||||
// Implementation inspired by the SO question and article below:
|
// Implementation inspired by the SO question and article below:
|
||||||
// https://stackoverflow.com/questions/51549456/android-o-notification-for-direct-reply-message
|
// https://stackoverflow.com/questions/51549456/android-o-notification-for-direct-reply-message
|
||||||
// https://medium.com/@sidorovroman3/android-how-to-use-messagingstyle-for-notifications-without-caching-messages-c414ef2b816c
|
// https://medium.com/@sidorovroman3/android-how-to-use-messagingstyle-for-notifications-without-caching-messages-c414ef2b816c
|
||||||
|
@ -171,10 +140,10 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
||||||
.extractMessagingStyleFromNotification(previousNotification)
|
.extractMessagingStyleFromNotification(previousNotification)
|
||||||
|
|
||||||
// Add reply
|
// Add reply
|
||||||
|
val avatarUrl = ApiUtils.getUrlForAvatar(currentUser.baseUrl, currentUser.userId, false)
|
||||||
val me = Person.Builder()
|
val me = Person.Builder()
|
||||||
.setName(currentUser.displayName)
|
.setName(currentUser.displayName)
|
||||||
// .setIcon(IconCompat.createWithResource(context, R.drawable.ic_user))
|
.setIcon(NotificationUtils.loadAvatarSync(avatarUrl))
|
||||||
.setIcon(avatarIcon)
|
|
||||||
.build()
|
.build()
|
||||||
val message = NotificationCompat.MessagingStyle.Message(replyMessage, System.currentTimeMillis(), me)
|
val message = NotificationCompat.MessagingStyle.Message(replyMessage, System.currentTimeMillis(), me)
|
||||||
previousStyle?.addMessage(message)
|
previousStyle?.addMessage(message)
|
||||||
|
|
|
@ -32,7 +32,13 @@ import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.service.notification.StatusBarNotification
|
import android.service.notification.StatusBarNotification
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
|
import com.facebook.common.references.CloseableReference
|
||||||
|
import com.facebook.datasource.DataSources
|
||||||
|
import com.facebook.drawee.backends.pipeline.Fresco
|
||||||
|
import com.facebook.imagepipeline.image.CloseableBitmap
|
||||||
|
import com.facebook.imagepipeline.postprocessors.RoundAsCirclePostprocessor
|
||||||
import com.nextcloud.talk.BuildConfig
|
import com.nextcloud.talk.BuildConfig
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.models.RingtoneSettings
|
import com.nextcloud.talk.models.RingtoneSettings
|
||||||
|
@ -297,6 +303,31 @@ object NotificationUtils {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Load user avatar synchronously.
|
||||||
|
* Inspired by:
|
||||||
|
* https://frescolib.org/docs/using-image-pipeline.html
|
||||||
|
* https://github.com/facebook/fresco/issues/830
|
||||||
|
* https://localcoder.org/using-facebooks-fresco-to-load-a-bitmap
|
||||||
|
*/
|
||||||
|
fun loadAvatarSync(avatarUrl: String): IconCompat? {
|
||||||
|
// TODO - how to handle errors here?
|
||||||
|
var avatarIcon: IconCompat? = null
|
||||||
|
val imageRequest = DisplayUtils.getImageRequestForUrl(avatarUrl, null)
|
||||||
|
val dataSource = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, null)
|
||||||
|
val closeableImageRef = DataSources.waitForFinalResult(dataSource) as CloseableReference<CloseableBitmap>?
|
||||||
|
val bitmap = closeableImageRef?.get()?.underlyingBitmap
|
||||||
|
if (bitmap != null) {
|
||||||
|
// According to Fresco documentation a copy of the bitmap should be made before closing the references.
|
||||||
|
// However, it seems to work without making a copy... ;-)
|
||||||
|
RoundAsCirclePostprocessor(true).process(bitmap)
|
||||||
|
avatarIcon = IconCompat.createWithBitmap(bitmap)
|
||||||
|
}
|
||||||
|
CloseableReference.closeSafely(closeableImageRef)
|
||||||
|
dataSource.close()
|
||||||
|
return avatarIcon
|
||||||
|
}
|
||||||
|
|
||||||
private data class Channel(
|
private data class Channel(
|
||||||
val id: String,
|
val id: String,
|
||||||
val name: String,
|
val name: String,
|
||||||
|
|
Loading…
Reference in a new issue