Refine notification fetching
This commit is contained in:
parent
8f5e4e2317
commit
df016a524f
|
@ -49,6 +49,7 @@ import org.pixeldroid.app.utils.hasInternet
|
||||||
import org.pixeldroid.app.utils.notificationsWorker.NotificationsWorker.Companion.INSTANCE_NOTIFICATION_TAG
|
import org.pixeldroid.app.utils.notificationsWorker.NotificationsWorker.Companion.INSTANCE_NOTIFICATION_TAG
|
||||||
import org.pixeldroid.app.utils.notificationsWorker.NotificationsWorker.Companion.SHOW_NOTIFICATION_TAG
|
import org.pixeldroid.app.utils.notificationsWorker.NotificationsWorker.Companion.SHOW_NOTIFICATION_TAG
|
||||||
import org.pixeldroid.app.utils.notificationsWorker.NotificationsWorker.Companion.USER_NOTIFICATION_TAG
|
import org.pixeldroid.app.utils.notificationsWorker.NotificationsWorker.Companion.USER_NOTIFICATION_TAG
|
||||||
|
import org.pixeldroid.app.utils.notificationsWorker.removeNotificationChannelsFromAccount
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@ class MainActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Checks if the activity was launched from a notification from another account than the
|
// Checks if the activity was launched from a notification from another account than the
|
||||||
// current active one, and if so switches to that account
|
// current active one, and if so switches to that account
|
||||||
private fun notificationFromOtherUser(): Boolean {
|
private fun notificationFromOtherUser(): Boolean {
|
||||||
val userOfNotification: String? = intent.extras?.getString(USER_NOTIFICATION_TAG)
|
val userOfNotification: String? = intent.extras?.getString(USER_NOTIFICATION_TAG)
|
||||||
|
@ -214,6 +215,9 @@ class MainActivity : BaseActivity() {
|
||||||
|
|
||||||
private fun logOut(){
|
private fun logOut(){
|
||||||
finish()
|
finish()
|
||||||
|
|
||||||
|
removeNotificationChannelsFromAccount(applicationContext, user)
|
||||||
|
|
||||||
db.runInTransaction {
|
db.runInTransaction {
|
||||||
db.userDao().deleteActiveUsers()
|
db.userDao().deleteActiveUsers()
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.app.NotificationManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.Color
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
@ -25,7 +26,6 @@ import org.pixeldroid.app.utils.di.PixelfedAPIHolder
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,13 +48,16 @@ class NotificationsWorker(
|
||||||
val users: List<UserDatabaseEntity> = db.userDao().getAll()
|
val users: List<UserDatabaseEntity> = db.userDao().getAll()
|
||||||
|
|
||||||
for (user in users){
|
for (user in users){
|
||||||
val channelId = user.instance_uri + user.user_id
|
val uniqueUserId = makeChannelGroupId(user)
|
||||||
|
|
||||||
createNotificationChannels(
|
val notificationsEnabledForUser = makeNotificationChannels(
|
||||||
"@${user.username}@${user.instance_uri.removePrefix("https://")}",
|
"@${user.username}@${user.instance_uri.removePrefix("https://")}",
|
||||||
channelId
|
uniqueUserId
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//if notifications are disabled for this user, move on to next user
|
||||||
|
if(!notificationsEnabledForUser) continue
|
||||||
|
|
||||||
// Get newest notification from database
|
// Get newest notification from database
|
||||||
var previouslyLatestNotification: Notification? = db.notificationDao().latestNotification(user.user_id, user.instance_uri)
|
var previouslyLatestNotification: Notification? = db.notificationDao().latestNotification(user.user_id, user.instance_uri)
|
||||||
|
|
||||||
|
@ -81,7 +84,7 @@ class NotificationsWorker(
|
||||||
|
|
||||||
// Launch new notifications
|
// Launch new notifications
|
||||||
filteredNewNotifications.forEach {
|
filteredNewNotifications.forEach {
|
||||||
showNotification(it, user, channelId)
|
showNotification(it, user, uniqueUserId)
|
||||||
}
|
}
|
||||||
|
|
||||||
previouslyLatestNotification =
|
previouslyLatestNotification =
|
||||||
|
@ -105,10 +108,8 @@ class NotificationsWorker(
|
||||||
private fun showNotification(
|
private fun showNotification(
|
||||||
notification: Notification,
|
notification: Notification,
|
||||||
user: UserDatabaseEntity,
|
user: UserDatabaseEntity,
|
||||||
channelIdPrefix: String
|
uniqueUserId: String
|
||||||
) {
|
) {
|
||||||
val channelId = channelIdPrefix + (notification.type ?: "other").toString()
|
|
||||||
|
|
||||||
val intent: Intent = when (notification.type) {
|
val intent: Intent = when (notification.type) {
|
||||||
mention -> notification.status?.let {
|
mention -> notification.status?.let {
|
||||||
Intent(applicationContext, PostActivity::class.java).apply {
|
Intent(applicationContext, PostActivity::class.java).apply {
|
||||||
|
@ -128,7 +129,7 @@ class NotificationsWorker(
|
||||||
.putExtra(INSTANCE_NOTIFICATION_TAG, user.instance_uri)
|
.putExtra(INSTANCE_NOTIFICATION_TAG, user.instance_uri)
|
||||||
|
|
||||||
|
|
||||||
val builder = NotificationCompat.Builder(applicationContext, channelId)
|
val builder = NotificationCompat.Builder(applicationContext, makeChannelId(uniqueUserId, notification.type))
|
||||||
.setSmallIcon(
|
.setSmallIcon(
|
||||||
when (notification.type) {
|
when (notification.type) {
|
||||||
follow -> R.drawable.ic_follow
|
follow -> R.drawable.ic_follow
|
||||||
|
@ -140,6 +141,7 @@ class NotificationsWorker(
|
||||||
null -> R.drawable.ic_comment_empty
|
null -> R.drawable.ic_comment_empty
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
.setColor(Color.parseColor("#6200EE"))
|
||||||
.setContentTitle(
|
.setContentTitle(
|
||||||
notification.account?.username?.let { username ->
|
notification.account?.username?.let { username ->
|
||||||
applicationContext.getString(
|
applicationContext.getString(
|
||||||
|
@ -166,39 +168,59 @@ class NotificationsWorker(
|
||||||
builder.setContentText(notification.status?.content)
|
builder.setContentText(notification.status?.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.setGroup(uniqueUserId)
|
||||||
|
|
||||||
with(NotificationManagerCompat.from(applicationContext)) {
|
with(NotificationManagerCompat.from(applicationContext)) {
|
||||||
// notificationId is a unique int for each notification
|
// notificationId is a unique int for each notification
|
||||||
notify((user.instance_uri + user.user_id + notification.id).hashCode(), builder.build())
|
notify((uniqueUserId + notification.id).hashCode(), builder.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNotificationChannels(handle: String, channelId: String) {
|
private fun makeNotificationChannels(handle: String, channelGroupId: String): Boolean {
|
||||||
|
val notificationManager: NotificationManager =
|
||||||
|
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
// Create the NotificationChannel, but only on API 26+ because
|
// Create the NotificationChannel, but only on API 26+ because
|
||||||
// the NotificationChannel class is new and not in the support library
|
// the NotificationChannel class is new and not in the support library
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
// The id of the group.
|
// The id of the group, hashed (since when creating the group, it may be truncated if too long)
|
||||||
val notificationManager: NotificationManager =
|
val hashedGroupId = channelGroupId.hashCode().toString()
|
||||||
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
notificationManager.createNotificationChannelGroup(NotificationChannelGroup(hashedGroupId, handle))
|
||||||
notificationManager.createNotificationChannelGroup(NotificationChannelGroup(channelId, handle))
|
|
||||||
|
|
||||||
val importance = NotificationManager.IMPORTANCE_DEFAULT
|
val importance = NotificationManager.IMPORTANCE_DEFAULT
|
||||||
|
|
||||||
val followsChannel = NotificationChannel(channelId + follow.toString(), "New followers", importance).apply { group = channelId }
|
val channels: List<NotificationChannel> = listOf(
|
||||||
val mentionChannel = NotificationChannel(channelId + mention.toString(), "Mentions", importance).apply { group = channelId }
|
NotificationChannel(makeChannelId(channelGroupId, follow), applicationContext.getString(R.string.followed_notification_channel), importance),
|
||||||
val sharesChannel = NotificationChannel(channelId + reblog.toString(), "Shares", importance).apply { group = channelId }
|
NotificationChannel(makeChannelId(channelGroupId, mention), applicationContext.getString(R.string.mention_notification_channel), importance),
|
||||||
val likesChannel = NotificationChannel(channelId + favourite.toString(), "Likes", importance).apply { group = channelId }
|
NotificationChannel(makeChannelId(channelGroupId, reblog), applicationContext.getString(R.string.shared_notification_channel), importance),
|
||||||
val commentsChannel = NotificationChannel(channelId + comment.toString(), "Comments", importance).apply { group = channelId }
|
NotificationChannel(makeChannelId(channelGroupId, favourite), applicationContext.getString(R.string.liked_notification_channel), importance),
|
||||||
val pollsChannel = NotificationChannel(channelId + poll.toString(), "Polls", importance).apply { group = channelId }
|
NotificationChannel(makeChannelId(channelGroupId, comment), applicationContext.getString(R.string.comment_notification_channel), importance),
|
||||||
val othersChannel = NotificationChannel(channelId + "other", "Other", importance).apply { group = channelId }
|
NotificationChannel(makeChannelId(channelGroupId, poll), applicationContext.getString(R.string.poll_notification_channel), importance),
|
||||||
|
NotificationChannel(makeChannelId(channelGroupId, null), applicationContext.getString(R.string.other_notification_channel), importance),
|
||||||
|
).map {
|
||||||
|
it.apply { group = hashedGroupId }
|
||||||
|
}
|
||||||
|
|
||||||
// Register the channels with the system
|
// Register the channels with the system
|
||||||
notificationManager.createNotificationChannel(followsChannel)
|
notificationManager.createNotificationChannels(channels)
|
||||||
notificationManager.createNotificationChannel(mentionChannel)
|
|
||||||
notificationManager.createNotificationChannel(sharesChannel)
|
//Return true if notifications are enabled, false if disabled
|
||||||
notificationManager.createNotificationChannel(likesChannel)
|
return notificationManager.areNotificationsEnabled() and
|
||||||
notificationManager.createNotificationChannel(commentsChannel)
|
(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
notificationManager.createNotificationChannel(pollsChannel)
|
val channelGroup =
|
||||||
notificationManager.createNotificationChannel(othersChannel)
|
notificationManager.getNotificationChannelGroup(hashedGroupId)
|
||||||
|
!channelGroup.isBlocked
|
||||||
|
} else true) and
|
||||||
|
(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
!notificationManager.areNotificationsPaused()
|
||||||
|
} else true) and
|
||||||
|
!channels.all {
|
||||||
|
notificationManager.getNotificationChannel(it.id).importance <= NotificationManager.IMPORTANCE_NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
notificationManager.areNotificationsEnabled()
|
||||||
|
} else {
|
||||||
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +228,39 @@ class NotificationsWorker(
|
||||||
const val SHOW_NOTIFICATION_TAG = "org.pixeldroid.app.SHOW_NOTIFICATION"
|
const val SHOW_NOTIFICATION_TAG = "org.pixeldroid.app.SHOW_NOTIFICATION"
|
||||||
const val INSTANCE_NOTIFICATION_TAG = "org.pixeldroid.app.USER_NOTIFICATION"
|
const val INSTANCE_NOTIFICATION_TAG = "org.pixeldroid.app.USER_NOTIFICATION"
|
||||||
const val USER_NOTIFICATION_TAG = "org.pixeldroid.app.INSTANCE_NOTIFICATION"
|
const val USER_NOTIFICATION_TAG = "org.pixeldroid.app.INSTANCE_NOTIFICATION"
|
||||||
|
|
||||||
|
const val otherNotificationType = "other"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [channelGroupId] is the id used to uniquely identify the group: for us it is a unique id
|
||||||
|
* identifying a user consisting of the concatenation of the instance uri and user id.
|
||||||
|
*/
|
||||||
|
private fun makeChannelId(channelGroupId: String, type: Notification.NotificationType?): String =
|
||||||
|
(channelGroupId + (type ?: NotificationsWorker.otherNotificationType)).hashCode().toString()
|
||||||
|
|
||||||
|
private fun makeChannelGroupId(user: UserDatabaseEntity) = user.instance_uri + user.user_id
|
||||||
|
|
||||||
|
|
||||||
|
fun removeNotificationChannelsFromAccount(context: Context, user: UserDatabaseEntity?) = user?.let {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val notificationManager: NotificationManager =
|
||||||
|
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
||||||
|
val channelGroupId = makeChannelGroupId(user)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
notificationManager.deleteNotificationChannelGroup(channelGroupId.hashCode().toString())
|
||||||
|
} else {
|
||||||
|
val types: MutableList<Notification.NotificationType?> =
|
||||||
|
Notification.NotificationType.values().toMutableList()
|
||||||
|
types += null
|
||||||
|
|
||||||
|
types.forEach {
|
||||||
|
notificationManager.deleteNotificationChannel(makeChannelId(channelGroupId, it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/colorDrawing"
|
||||||
|
android:pathData="M7.58,4.08L6.15,2.65C3.75,4.48 2.17,7.3 2.03,10.5h2c0.15,-2.65 1.51,-4.97 3.55,-6.42zM19.97,10.5h2c-0.15,-3.2 -1.73,-6.02 -4.12,-7.85l-1.42,1.43c2.02,1.45 3.39,3.77 3.54,6.42zM18,11c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2v-5zM12,22c0.14,0 0.27,-0.01 0.4,-0.04 0.65,-0.14 1.18,-0.58 1.44,-1.18 0.1,-0.24 0.15,-0.5 0.15,-0.78h-4c0.01,1.1 0.9,2 2.01,2z"/>
|
||||||
|
</vector>
|
|
@ -47,15 +47,25 @@
|
||||||
<!-- Notifications: like (favourite) notification -->
|
<!-- Notifications: like (favourite) notification -->
|
||||||
<string name="liked_notification">%1$s liked your post</string>
|
<string name="liked_notification">%1$s liked your post</string>
|
||||||
|
|
||||||
<!-- Notifications: end of poll notification -->
|
|
||||||
<string name="poll_notification">"%1$s's poll has ended"</string>
|
|
||||||
|
|
||||||
<!-- Notifications: comment notification -->
|
<!-- Notifications: comment notification -->
|
||||||
<string name="comment_notification">%1$s commented on your post</string>
|
<string name="comment_notification">%1$s commented on your post</string>
|
||||||
|
|
||||||
|
<!-- Notifications: end of poll notification -->
|
||||||
|
<string name="poll_notification">"%1$s's poll has ended"</string>
|
||||||
|
|
||||||
<!-- Notifications: other notification -->
|
<!-- Notifications: other notification -->
|
||||||
<string name="other_notification">"Notification from %1$s"</string>
|
<string name="other_notification">"Notification from %1$s"</string>
|
||||||
|
|
||||||
|
<string name="followed_notification_channel">"New followers"</string>
|
||||||
|
<string name="mention_notification_channel">"Mentions"</string>
|
||||||
|
<string name="shared_notification_channel">"Shares"</string>
|
||||||
|
<string name="liked_notification_channel">"Likes"</string>
|
||||||
|
<string name="comment_notification_channel">"Comments"</string>
|
||||||
|
<string name="poll_notification_channel">"Polls"</string>
|
||||||
|
<string name="other_notification_channel">"Other"</string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Login page -->
|
<!-- Login page -->
|
||||||
<string name="whats_an_instance">"What's an instance?"</string>
|
<string name="whats_an_instance">"What's an instance?"</string>
|
||||||
<string name="whats_an_instance_explanation">"You might be confused by the text field asking for the domain of your 'instance'.
|
<string name="whats_an_instance_explanation">"You might be confused by the text field asking for the domain of your 'instance'.
|
||||||
|
|
Loading…
Reference in New Issue