WIP: se agrega notificacion de nuevo seguidor y accion a notificacion de like

This commit is contained in:
erik-everardo 2024-03-05 23:17:57 -06:00
parent 049d97aeb8
commit bd994a17e8
6 changed files with 135 additions and 18 deletions

View File

@ -30,10 +30,11 @@
<activity android:name=".login.LogInActivity" android:theme="@style/Theme.Isolaatti" /> <activity android:name=".login.LogInActivity" android:theme="@style/Theme.Isolaatti" />
<activity android:name=".profile.ui.ProfileActivity" <activity android:name=".profile.ui.ProfileActivity"
android:theme="@style/Theme.Isolaatti" android:theme="@style/Theme.Isolaatti"
android:parentActivityName=".MainActivity"/> android:parentActivityName=".home.HomeActivity"/>
<activity android:name=".settings.ui.SettingsActivity" android:theme="@style/Theme.Isolaatti"/> <activity android:name=".settings.ui.SettingsActivity" android:theme="@style/Theme.Isolaatti"/>
<activity android:name=".posting.posts.ui.CreatePostActivity" android:theme="@style/Theme.Isolaatti" android:windowSoftInputMode="adjustResize"/> <activity android:name=".posting.posts.ui.CreatePostActivity" android:theme="@style/Theme.Isolaatti" android:windowSoftInputMode="adjustResize"/>
<activity android:name=".posting.posts.viewer.ui.PostViewerActivity" android:theme="@style/Theme.Isolaatti"/> <activity android:name=".posting.posts.viewer.ui.PostViewerActivity" android:theme="@style/Theme.Isolaatti"
android:parentActivityName=".home.HomeActivity"/>
<activity android:name=".drafts.ui.DraftsActivity" android:theme="@style/Theme.Isolaatti"/> <activity android:name=".drafts.ui.DraftsActivity" android:theme="@style/Theme.Isolaatti"/>
<activity android:name=".about.AboutActivity" android:theme="@style/Theme.Isolaatti"/> <activity android:name=".about.AboutActivity" android:theme="@style/Theme.Isolaatti"/>
<activity android:name=".images.picture_viewer.ui.PictureViewerActivity" android:theme="@style/Theme.Isolaatti"/> <activity android:name=".images.picture_viewer.ui.PictureViewerActivity" android:theme="@style/Theme.Isolaatti"/>

View File

@ -41,7 +41,7 @@ class LikeNotification(id: Long, date: ZonedDateTime, userId: Int, read: Boolean
class FollowNotification(id: Long, date: ZonedDateTime, userId: Int, read: Boolean) : Notification(id, date, userId, read) { class FollowNotification(id: Long, date: ZonedDateTime, userId: Int, read: Boolean) : Notification(id, date, userId, read) {
companion object { companion object {
const val TYPE = "follow" const val TYPE = "follower"
} }
override fun ingestPayload(notificationPayload: NotificationPayload) { override fun ingestPayload(notificationPayload: NotificationPayload) {

View File

@ -1,9 +1,12 @@
package com.isolaatti.posting.posts.viewer.ui package com.isolaatti.posting.posts.viewer.ui
import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.util.Log
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.app.TaskStackBuilder
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import coil.imageLoader import coil.imageLoader
import coil.load import coil.load
@ -28,10 +31,23 @@ import kotlinx.coroutines.launch
class PostViewerActivity : IsolaattiBaseActivity() { class PostViewerActivity : IsolaattiBaseActivity() {
companion object { companion object {
const val POST_ID = "postId" const val POST_ID = "postId"
fun startActivity(context: Context, postId: Long) { const val LOG_TAG = "PostViewerActivity"
context.startActivity(Intent(context, PostViewerActivity::class.java).apply {
fun getIntent(context: Context, postId: Long): Intent {
return Intent(context, PostViewerActivity::class.java).apply {
putExtra(POST_ID, postId) putExtra(POST_ID, postId)
}) }
}
fun startActivity(context: Context, postId: Long) {
context.startActivity(getIntent(context, postId))
}
fun getPendingIntent(context: Context, postId: Long): PendingIntent? {
return TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(Companion.getIntent(context, postId))
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
} }
} }
@ -106,9 +122,21 @@ class PostViewerActivity : IsolaattiBaseActivity() {
} }
} }
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.getLongExtra(POST_ID, 0)?.let {
postId = it
viewModel.postId = postId
viewModel.getPost()
}
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
postId = intent.getLongExtra(POST_ID, 0) postId = intent.getLongExtra(POST_ID, 0)
Log.d(LOG_TAG, "Post id: $postId")
binding = ActivityPostViewerBinding.inflate(layoutInflater) binding = ActivityPostViewerBinding.inflate(layoutInflater)
markwon = Markwon.builder(this) markwon = Markwon.builder(this)

View File

@ -1,8 +1,10 @@
package com.isolaatti.profile.ui package com.isolaatti.profile.ui
import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.core.app.TaskStackBuilder
import com.isolaatti.common.IsolaattiBaseActivity import com.isolaatti.common.IsolaattiBaseActivity
import com.isolaatti.databinding.ActivityProfileBinding import com.isolaatti.databinding.ActivityProfileBinding
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -22,10 +24,22 @@ class ProfileActivity : IsolaattiBaseActivity() {
companion object { companion object {
const val EXTRA_USER_ID = "user_id" const val EXTRA_USER_ID = "user_id"
fun startActivity(context: Context, userId: Int) { fun getIntent(context: Context, userId: Int): Intent {
context.startActivity(Intent(context, ProfileActivity::class.java).apply { return Intent(context, ProfileActivity::class.java).apply {
putExtra(EXTRA_USER_ID, userId) putExtra(EXTRA_USER_ID, userId)
}) }
}
fun startActivity(context: Context, userId: Int) {
context.startActivity(getIntent(context, userId))
}
fun getPendingIntent(context: Context, userId: Int): PendingIntent? {
return TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(getIntent(context, userId))
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
} }
} }
} }

View File

@ -7,23 +7,23 @@ import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import coil.Coil
import coil.request.ImageRequest import coil.request.ImageRequest
import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage import com.google.firebase.messaging.RemoteMessage
import com.isolaatti.MyApplication import com.isolaatti.MyApplication
import com.isolaatti.R import com.isolaatti.R
import com.isolaatti.common.CoilImageLoader import com.isolaatti.common.CoilImageLoader
import com.isolaatti.notifications.domain.FollowNotification
import com.isolaatti.notifications.domain.LikeNotification import com.isolaatti.notifications.domain.LikeNotification
import com.isolaatti.posting.posts.viewer.ui.PostViewerActivity
import com.isolaatti.profile.ui.ProfileActivity
import com.isolaatti.utils.UrlGen import com.isolaatti.utils.UrlGen
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody.Companion.toResponseBody
import retrofit2.awaitResponse import retrofit2.awaitResponse
import retrofit2.http.Url
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
@ -45,6 +45,11 @@ class FcmService : FirebaseMessagingService() {
const val AUTHOR_ID = "authorId" const val AUTHOR_ID = "authorId"
const val AUTHOR_NAME = "authorName" const val AUTHOR_NAME = "authorName"
} }
object NewFollowerNotificationConstants {
const val FOLLOWER_USER_ID = "followerUserId"
const val FOLLOWER_NAME = "followerName"
}
} }
} }
@ -67,6 +72,7 @@ class FcmService : FirebaseMessagingService() {
when(type) { when(type) {
LikeNotification.TYPE -> showLikeNotification(message.data) LikeNotification.TYPE -> showLikeNotification(message.data)
FollowNotification.TYPE -> showNewFollowerNotification(message.data)
else -> { else -> {
Log.i(LOG_TAG, "Not showing notification of unknown type: ${message.data}") Log.i(LOG_TAG, "Not showing notification of unknown type: ${message.data}")
@ -78,11 +84,18 @@ class FcmService : FirebaseMessagingService() {
val notificationId = data[NotificationsConstants.NOTIFICATION_ID]?.toIntOrNull() val notificationId = data[NotificationsConstants.NOTIFICATION_ID]?.toIntOrNull()
val relatedNotifications = data[NotificationsConstants.RELATED_NOTIFICATIONS]?.trimStart('[')?.trimEnd(']')?.split(",") val relatedNotifications = data[NotificationsConstants.RELATED_NOTIFICATIONS]?.trimStart('[')?.trimEnd(']')?.split(",")
val likeId = data[NotificationsConstants.LikeNotificationConstants.LIKE_ID] val likeId = data[NotificationsConstants.LikeNotificationConstants.LIKE_ID]
val postId = data[NotificationsConstants.LikeNotificationConstants.POST_ID] val postId = data[NotificationsConstants.LikeNotificationConstants.POST_ID]?.toLongOrNull()
val authorId = data[NotificationsConstants.LikeNotificationConstants.AUTHOR_ID]?.toIntOrNull() val authorId = data[NotificationsConstants.LikeNotificationConstants.AUTHOR_ID]?.toIntOrNull()
val authorName = data[NotificationsConstants.LikeNotificationConstants.AUTHOR_NAME] val authorName = data[NotificationsConstants.LikeNotificationConstants.AUTHOR_NAME]
// notificationId should never be null
if(notificationId == null) {
Log.e(LOG_TAG, "notification id is null")
return
}
Log.v(LOG_TAG, "Notification id: $notificationId")
val imageUrl = authorId?.let { UrlGen.userProfileImage(it, true) } val imageUrl = authorId?.let { UrlGen.userProfileImage(it, true) }
Log.d(LOG_TAG, data.toString()) Log.d(LOG_TAG, data.toString())
@ -98,16 +111,18 @@ class FcmService : FirebaseMessagingService() {
.setContentText(getString(R.string.like_notification_text)) .setContentText(getString(R.string.like_notification_text))
.setPriority(NotificationCompat.PRIORITY_DEFAULT) .setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setLargeIcon(drawable.toBitmap()) .setLargeIcon(drawable.toBitmap())
.setAutoCancel(true)
Log.v(LOG_TAG, "Post liked: $postId")
if(postId != null) {
notificationBuilder.setContentIntent(PostViewerActivity.getPendingIntent(this, postId))
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
return@target return@target
} }
Log.v(LOG_TAG, "Notification id: $notificationId")
// notificationId should never be null
if(notificationId == null) {
return@target
}
NotificationManagerCompat.from(this).run { NotificationManagerCompat.from(this).run {
relatedNotifications?.forEach { relatedNotifications?.forEach {
it.toIntOrNull()?.let { relatedNotificationId -> cancel(relatedNotificationId) } it.toIntOrNull()?.let { relatedNotificationId -> cancel(relatedNotificationId) }
@ -121,4 +136,61 @@ class FcmService : FirebaseMessagingService() {
CoilImageLoader.getImageLoader(this).enqueue(imageRequest) CoilImageLoader.getImageLoader(this).enqueue(imageRequest)
} }
private fun showNewFollowerNotification(data: Map<String, String>) {
val notificationId = data[NotificationsConstants.NOTIFICATION_ID]?.toIntOrNull()
val relatedNotifications = data[NotificationsConstants.RELATED_NOTIFICATIONS]?.trimStart('[')?.trimEnd(']')?.split(",")
val followerUserId = data[NotificationsConstants.NewFollowerNotificationConstants.FOLLOWER_USER_ID]?.toIntOrNull()
val followerName = data[NotificationsConstants.NewFollowerNotificationConstants.FOLLOWER_NAME]
// notificationId should never be null
if(notificationId == null) {
Log.e(LOG_TAG, "notification id is null")
return
}
if(followerUserId == null) {
Log.e(LOG_TAG, "followerUserId is not present or is not valid")
}
val imageUrl = followerUserId?.let { UrlGen.userProfileImage(it, true) }
val imageRequest = ImageRequest
.Builder(this)
.data(imageUrl)
.fallback(R.drawable.baseline_person_24)
.target { drawable ->
val notificationBuilder = NotificationCompat.Builder(this, MyApplication.LIKES_NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.new_follower_notification_title, followerName ?: ""))
.setContentText(getString(R.string.new_follower_notification_text))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setLargeIcon(drawable.toBitmap())
.setAutoCancel(true)
if(followerUserId != null) {
notificationBuilder.setContentIntent(ProfileActivity.getPendingIntent(this, followerUserId))
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
return@target
}
NotificationManagerCompat.from(this).run {
relatedNotifications?.forEach {
it.toIntOrNull()?.let { relatedNotificationId -> cancel(relatedNotificationId) }
}
notify(notificationId, notificationBuilder.build())
}
}.build()
CoilImageLoader.getImageLoader(this).enqueue(imageRequest)
}
} }

View File

@ -193,4 +193,6 @@
<string name="likes_notification_channel_description">Get notified when someone likes your posts.</string> <string name="likes_notification_channel_description">Get notified when someone likes your posts.</string>
<string name="like_notification_title">%s claps to your post</string> <string name="like_notification_title">%s claps to your post</string>
<string name="like_notification_text">Tap this notification to go to the post.</string> <string name="like_notification_text">Tap this notification to go to the post.</string>
<string name="new_follower_notification_title">%s is now following you</string>
<string name="new_follower_notification_text">Tap this notification to see their profile.</string>
</resources> </resources>