Send mutltiple notifications instead of summary notification (#1365)
Before Width: | Height: | Size: 478 B |
Before Width: | Height: | Size: 652 B |
Before Width: | Height: | Size: 384 B |
Before Width: | Height: | Size: 460 B |
Before Width: | Height: | Size: 426 B |
Before Width: | Height: | Size: 355 B |
Before Width: | Height: | Size: 451 B |
Before Width: | Height: | Size: 297 B |
Before Width: | Height: | Size: 339 B |
Before Width: | Height: | Size: 335 B |
Before Width: | Height: | Size: 588 B |
Before Width: | Height: | Size: 897 B |
Before Width: | Height: | Size: 508 B |
Before Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 519 B |
Before Width: | Height: | Size: 781 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 692 B |
Before Width: | Height: | Size: 805 B |
Before Width: | Height: | Size: 700 B |
@ -7,6 +7,7 @@ import io.github.wulkanowy.ui.modules.main.MainView
|
||||
|
||||
sealed interface Notification {
|
||||
val channelId: String
|
||||
val group: String
|
||||
val startMenu: MainView.Section
|
||||
val icon: Int
|
||||
val titleStringRes: Int
|
||||
@ -15,6 +16,7 @@ sealed interface Notification {
|
||||
|
||||
data class MultipleNotifications(
|
||||
override val channelId: String,
|
||||
override val group: String,
|
||||
override val startMenu: MainView.Section,
|
||||
@DrawableRes override val icon: Int,
|
||||
@PluralsRes override val titleStringRes: Int,
|
||||
@ -26,6 +28,7 @@ data class MultipleNotifications(
|
||||
|
||||
data class OneNotification(
|
||||
override val channelId: String,
|
||||
override val group: String,
|
||||
override val startMenu: MainView.Section,
|
||||
@DrawableRes override val icon: Int,
|
||||
@StringRes override val titleStringRes: Int,
|
||||
|
@ -18,6 +18,7 @@ class LuckyNumberChannel @Inject constructor(
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "lucky_number_channel"
|
||||
const val GROUP_ID = "lucky_number_group"
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
|
@ -18,6 +18,7 @@ class NewConferencesChannel @Inject constructor(
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "new_conferences_channel"
|
||||
const val GROUP_ID = "new_conferences_group"
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
|
@ -18,6 +18,7 @@ class NewExamChannel @Inject constructor(
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "new_exam_channel"
|
||||
const val GROUP_ID = "new_exam_group"
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
|
@ -18,6 +18,9 @@ class NewGradesChannel @Inject constructor(
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "new_grade_channel"
|
||||
const val GROUP_DETAILS_ID = "new_grade_details_group"
|
||||
const val GROUP_PREDICTED_ID = "new_grade_predicted_group"
|
||||
const val GROUP_FINAL_ID = "new_grade_final_group"
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
|
@ -18,6 +18,7 @@ class NewHomeworkChannel @Inject constructor(
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "new_homework_channel"
|
||||
const val GROUP_ID = "new_homework_group"
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
|
@ -18,6 +18,7 @@ class NewMessagesChannel @Inject constructor(
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "new_message_channel"
|
||||
const val GROUP_ID = "new_message_group"
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
|
@ -18,6 +18,7 @@ class NewNotesChannel @Inject constructor(
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "new_notes_channel"
|
||||
const val GROUP_ID = "new_notes_group"
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
|
@ -17,7 +17,8 @@ class NewSchoolAnnouncementsChannel @Inject constructor(
|
||||
) : Channel {
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "new_schoolAnnouncements_channel"
|
||||
const val CHANNEL_ID = "new_school_announcements_channel"
|
||||
const val GROUP_ID = "new_school_announcements_group"
|
||||
}
|
||||
|
||||
override fun create() {
|
||||
|
@ -2,6 +2,8 @@ package io.github.wulkanowy.services.sync.notifications
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import io.github.wulkanowy.R
|
||||
@ -18,53 +20,68 @@ abstract class BaseNotification(
|
||||
private val notificationManager: NotificationManagerCompat,
|
||||
) {
|
||||
|
||||
protected fun sendNotification(notification: Notification) {
|
||||
protected fun sendNotification(notification: Notification) = when (notification) {
|
||||
is OneNotification -> sendOneNotification(notification)
|
||||
is MultipleNotifications -> sendMultipleNotifications(notification)
|
||||
}
|
||||
|
||||
private fun sendOneNotification(notification: OneNotification) {
|
||||
notificationManager.notify(
|
||||
Random.nextInt(Int.MAX_VALUE),
|
||||
NotificationCompat.Builder(context, notification.channelId)
|
||||
.setLargeIcon(context.getCompatBitmap(notification.icon, R.color.colorPrimary))
|
||||
.setSmallIcon(R.drawable.ic_stat_all)
|
||||
.setAutoCancel(true)
|
||||
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setColor(context.getCompatColor(R.color.colorPrimary))
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(
|
||||
context, notification.startMenu.id,
|
||||
MainActivity.getStartIntent(context, notification.startMenu, true),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
getNotificationBuilder(notification).apply {
|
||||
val content = context.getString(
|
||||
notification.contentStringRes,
|
||||
*notification.contentValues.toTypedArray()
|
||||
)
|
||||
.apply {
|
||||
when (notification) {
|
||||
is OneNotification -> buildForOneNotification(notification)
|
||||
is MultipleNotifications -> buildForMultipleNotification(notification)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
setContentTitle(context.getString(notification.titleStringRes))
|
||||
setContentText(content)
|
||||
setStyle(NotificationCompat.BigTextStyle().bigText(content))
|
||||
}.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun NotificationCompat.Builder.buildForOneNotification(n: OneNotification) {
|
||||
val content = context.getString(n.contentStringRes, *n.contentValues.toTypedArray())
|
||||
setContentTitle(context.getString(n.titleStringRes))
|
||||
setContentText(content)
|
||||
setStyle(NotificationCompat.BigTextStyle().run {
|
||||
bigText(content)
|
||||
this
|
||||
})
|
||||
private fun sendMultipleNotifications(notification: MultipleNotifications) {
|
||||
notification.lines.forEach { item ->
|
||||
notificationManager.notify(
|
||||
Random.nextInt(Int.MAX_VALUE),
|
||||
getNotificationBuilder(notification).apply {
|
||||
setContentTitle(getQuantityString(notification.titleStringRes, 1))
|
||||
setContentText(item)
|
||||
setStyle(NotificationCompat.BigTextStyle().bigText(item))
|
||||
setGroup(notification.group)
|
||||
}.build()
|
||||
)
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return
|
||||
|
||||
notificationManager.notify(
|
||||
notification.group.hashCode(),
|
||||
getNotificationBuilder(notification).apply {
|
||||
setSmallIcon(notification.icon)
|
||||
setGroup(notification.group)
|
||||
setGroupSummary(true)
|
||||
}.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun NotificationCompat.Builder.buildForMultipleNotification(n: MultipleNotifications) {
|
||||
val lines = n.lines.size
|
||||
setContentTitle(context.resources.getQuantityString(n.titleStringRes, lines, lines))
|
||||
setContentText(context.resources.getQuantityString(n.contentStringRes, lines, lines))
|
||||
setStyle(NotificationCompat.InboxStyle().run {
|
||||
setSummaryText(
|
||||
context.resources.getQuantityString(n.summaryStringRes, n.lines.size, n.lines.size)
|
||||
private fun getNotificationBuilder(notification: Notification) = NotificationCompat
|
||||
.Builder(context, notification.channelId)
|
||||
.setLargeIcon(context.getCompatBitmap(notification.icon, R.color.colorPrimary))
|
||||
.setSmallIcon(R.drawable.ic_stat_all)
|
||||
.setAutoCancel(true)
|
||||
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setColor(context.getCompatColor(R.color.colorPrimary))
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(
|
||||
context, notification.startMenu.id,
|
||||
MainActivity.getStartIntent(context, notification.startMenu, true),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
n.lines.forEach(::addLine)
|
||||
this
|
||||
})
|
||||
)
|
||||
|
||||
private fun getQuantityString(@PluralsRes id: Int, value: Int): String {
|
||||
return context.resources.getQuantityString(id, value, value)
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ class NewConferenceNotification @Inject constructor(
|
||||
fun notify(items: List<Conference>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewConferencesChannel.CHANNEL_ID,
|
||||
group = NewConferencesChannel.GROUP_ID,
|
||||
icon = R.drawable.ic_more_conferences,
|
||||
titleStringRes = R.plurals.conference_notify_new_item_title,
|
||||
contentStringRes = R.plurals.conference_notify_new_items,
|
||||
|
@ -18,9 +18,10 @@ class NewExamNotification @Inject constructor(
|
||||
fun notify(items: List<Exam>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewExamChannel.CHANNEL_ID,
|
||||
group = NewExamChannel.GROUP_ID,
|
||||
icon = R.drawable.ic_main_exam,
|
||||
titleStringRes = R.plurals.exam_notify_new_item_title,
|
||||
contentStringRes = R.plurals.grade_notify_new_items, // TODO add missing string
|
||||
contentStringRes = R.plurals.exam_notify_new_item_title, // TODO add missing string
|
||||
summaryStringRes = R.plurals.exam_number_item,
|
||||
startMenu = MainView.Section.EXAM,
|
||||
lines = items.map {
|
||||
|
@ -16,9 +16,10 @@ class NewGradeNotification @Inject constructor(
|
||||
notificationManager: NotificationManagerCompat,
|
||||
) : BaseNotification(context, notificationManager) {
|
||||
|
||||
fun notifyDetails(items: List<Grade>) {
|
||||
fun notifyDetails(items: List<Grade>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewGradesChannel.CHANNEL_ID,
|
||||
group = NewGradesChannel.GROUP_DETAILS_ID,
|
||||
icon = R.drawable.ic_stat_grade,
|
||||
titleStringRes = R.plurals.grade_new_items,
|
||||
contentStringRes = R.plurals.grade_notify_new_items,
|
||||
@ -32,9 +33,10 @@ class NewGradeNotification @Inject constructor(
|
||||
sendNotification(notification)
|
||||
}
|
||||
|
||||
fun notifyPredicted(items: List<GradeSummary>) {
|
||||
fun notifyPredicted(items: List<GradeSummary>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewGradesChannel.CHANNEL_ID,
|
||||
group = NewGradesChannel.GROUP_PREDICTED_ID,
|
||||
icon = R.drawable.ic_stat_grade,
|
||||
titleStringRes = R.plurals.grade_new_items_predicted,
|
||||
contentStringRes = R.plurals.grade_notify_new_items_predicted,
|
||||
@ -48,9 +50,10 @@ class NewGradeNotification @Inject constructor(
|
||||
sendNotification(notification)
|
||||
}
|
||||
|
||||
fun notifyFinal(items: List<GradeSummary>) {
|
||||
fun notifyFinal(items: List<GradeSummary>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewGradesChannel.CHANNEL_ID,
|
||||
group = NewGradesChannel.GROUP_FINAL_ID,
|
||||
icon = R.drawable.ic_stat_grade,
|
||||
titleStringRes = R.plurals.grade_new_items_final,
|
||||
contentStringRes = R.plurals.grade_notify_new_items_final,
|
||||
|
@ -18,6 +18,7 @@ class NewHomeworkNotification @Inject constructor(
|
||||
fun notify(items: List<Homework>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewHomeworkChannel.CHANNEL_ID,
|
||||
group = NewHomeworkChannel.GROUP_ID,
|
||||
icon = R.drawable.ic_more_homework,
|
||||
titleStringRes = R.plurals.homework_notify_new_item_title,
|
||||
contentStringRes = R.plurals.homework_notify_new_item_title, // todo: you received %d new homework
|
||||
|
@ -18,6 +18,7 @@ class NewLuckyNumberNotification @Inject constructor(
|
||||
fun notify(item: LuckyNumber) {
|
||||
val notification = OneNotification(
|
||||
channelId = LuckyNumberChannel.CHANNEL_ID,
|
||||
group = LuckyNumberChannel.GROUP_ID,
|
||||
icon = R.drawable.ic_stat_luckynumber,
|
||||
titleStringRes = R.string.lucky_number_notify_new_item_title,
|
||||
contentStringRes = R.string.lucky_number_notify_new_item,
|
||||
|
@ -18,6 +18,7 @@ class NewMessageNotification @Inject constructor(
|
||||
fun notify(items: List<Message>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewMessagesChannel.CHANNEL_ID,
|
||||
group = NewMessagesChannel.GROUP_ID,
|
||||
icon = R.drawable.ic_stat_message,
|
||||
titleStringRes = R.plurals.message_new_items,
|
||||
contentStringRes = R.plurals.message_notify_new_items,
|
||||
|
@ -7,7 +7,7 @@ import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Note
|
||||
import io.github.wulkanowy.data.pojos.MultipleNotifications
|
||||
import io.github.wulkanowy.sdk.scrapper.notes.NoteCategory
|
||||
import io.github.wulkanowy.services.sync.channels.NewMessagesChannel
|
||||
import io.github.wulkanowy.services.sync.channels.NewNotesChannel
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -18,7 +18,8 @@ class NewNoteNotification @Inject constructor(
|
||||
|
||||
fun notify(items: List<Note>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewMessagesChannel.CHANNEL_ID,
|
||||
channelId = NewNotesChannel.CHANNEL_ID,
|
||||
group = NewNotesChannel.GROUP_ID,
|
||||
icon = R.drawable.ic_stat_note,
|
||||
titleStringRes = when (NoteCategory.getByValue(items.first().categoryType)) {
|
||||
NoteCategory.POSITIVE -> R.plurals.praise_new_items
|
||||
|
@ -18,6 +18,7 @@ class NewSchoolAnnouncementNotification @Inject constructor(
|
||||
fun notify(items: List<SchoolAnnouncement>) {
|
||||
val notification = MultipleNotifications(
|
||||
channelId = NewSchoolAnnouncementsChannel.CHANNEL_ID,
|
||||
group = NewSchoolAnnouncementsChannel.GROUP_ID,
|
||||
icon = R.drawable.ic_all_about,
|
||||
titleStringRes = R.plurals.school_announcement_notify_new_item_title,
|
||||
contentStringRes = R.plurals.school_announcement_notify_new_items,
|
||||
|
Before Width: | Height: | Size: 364 B |
Before Width: | Height: | Size: 473 B |
Before Width: | Height: | Size: 252 B |
Before Width: | Height: | Size: 347 B |
Before Width: | Height: | Size: 386 B |
Before Width: | Height: | Size: 301 B |
Before Width: | Height: | Size: 343 B |
Before Width: | Height: | Size: 220 B |
Before Width: | Height: | Size: 280 B |
Before Width: | Height: | Size: 315 B |
Before Width: | Height: | Size: 427 B |
Before Width: | Height: | Size: 713 B |
Before Width: | Height: | Size: 289 B |
Before Width: | Height: | Size: 449 B |
Before Width: | Height: | Size: 499 B |
Before Width: | Height: | Size: 602 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 590 B |
Before Width: | Height: | Size: 671 B |
Before Width: | Height: | Size: 659 B |