notification: classify email messages and add mail check prompt

This commit adds logic to classify notifications as "email" type when the notification text contains "sent you an email". This change ensures that email notifications are properly categorized, which was previously missing, leading to all email notifications being marked as UNKNOWN type.

### Problem:
Previously, email-related notifications from the backend were missing a URL. As a result, when users clicked on these notifications, there was no link to open, and the notifications were categorized as UNKNOWN. This led to a poor user experience since there was no feedback provided when the user clicked on an email notification.

### Changes:
- **NotificationClient**:
  - Modified `WikimediaNotification.toCommonsNotification()` to check if the notification text contains "sent you an email". If it does, the notification is classified as `EMAIL_MESSAGE` instead of the default `UNKNOWN`.

- **NotificationActivity**:
  - In the `NotificatinAdapter` click handler, added a check for `EMAIL_MESSAGE` type. When an email-type notification is clicked, a "Check your mail box" prompt is shown using `Snackbar`, instead of attempting to open a URL (which is typically missing for such notifications).

- **NotificationType**:
  - Added a new `EMAIL` type to categorize email-related notifications.

This change improves the user experience by ensuring email notifications are properly categorized and provides useful feedback when they are clicked.
This commit is contained in:
Qiutong Zeng 2024-10-17 10:00:50 +11:00
parent 95e0a0d143
commit 6243bf142b
3 changed files with 58 additions and 38 deletions

View file

@ -19,6 +19,7 @@ import fr.free.nrw.commons.databinding.ActivityNotificationBinding;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
import fr.free.nrw.commons.notification.models.Notification;
import fr.free.nrw.commons.notification.models.NotificationType;
import fr.free.nrw.commons.theme.BaseActivity;
import fr.free.nrw.commons.utils.NetworkUtils;
import fr.free.nrw.commons.utils.ViewUtil;
@ -147,8 +148,11 @@ public class NotificationActivity extends BaseActivity {
refresh(false);
}
adapter = new NotificatinAdapter(item -> {
Timber.d("Notification clicked %s", item.getLink());
handleUrl(item.getLink());
if (item.getNotificationType() == NotificationType.EMAIL){
ViewUtil.showLongSnackbar(binding.container, "Check your mail box");
} else {
handleUrl(item.getLink());
}
removeNotification(item);
return Unit.INSTANCE;
});

View file

@ -9,6 +9,7 @@ import fr.free.nrw.commons.utils.DateUtil
import fr.free.nrw.commons.wikidata.mwapi.MwQueryResponse
import io.reactivex.Observable
import io.reactivex.Single
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Named
import javax.inject.Singleton
@ -21,43 +22,55 @@ class NotificationClient
@param:Named(NetworkingModule.NAMED_COMMONS_CSRF) private val csrfTokenClient: CsrfTokenClient,
private val service: NotificationInterface,
) {
fun getNotifications(archived: Boolean): Single<List<Notification>> =
fun getNotifications(archived: Boolean): Single<List<Notification>> =
service
.getAllNotifications(
wikiList = "wikidatawiki|commonswiki|enwiki",
filter = if (archived) "read" else "!read",
continueStr = null,
).map {
it.query()?.notifications()?.list() ?: emptyList()
}.flatMap {
Observable.fromIterable(it)
}.map {
it.toCommonsNotification()
}.toList()
fun markNotificationAsRead(notificationId: String?): Observable<Boolean> =
try {
service
.getAllNotifications(
wikiList = "wikidatawiki|commonswiki|enwiki",
filter = if (archived) "read" else "!read",
continueStr = null,
).map {
it.query()?.notifications()?.list() ?: emptyList()
}.flatMap {
Observable.fromIterable(it)
}.map {
it.toCommonsNotification()
}.toList()
fun markNotificationAsRead(notificationId: String?): Observable<Boolean> =
try {
service
.markRead(
token = csrfTokenClient.getTokenBlocking(),
readList = notificationId,
unreadList = "",
).map(MwQueryResponse::success)
} catch (throwable: Throwable) {
if (throwable is InvalidLoginTokenException) {
Observable.error(throwable)
} else {
Observable.just(false)
}
.markRead(
token = csrfTokenClient.getTokenBlocking(),
readList = notificationId,
unreadList = "",
).map(MwQueryResponse::success)
} catch (throwable: Throwable) {
if (throwable is InvalidLoginTokenException) {
Observable.error(throwable)
} else {
Observable.just(false)
}
}
private fun WikimediaNotification.toCommonsNotification(): Notification {
val notificationText = contents?.compactHeader ?: ""
val notificationType = if (notificationText.contains("sent you an email", ignoreCase = true)){
NotificationType.EMAIL
} else {
NotificationType.UNKNOWN
}
return Notification(
notificationType = notificationType,
notificationText = notificationText,
date = DateUtil.getMonthOnlyDateString(timestamp),
link = contents?.links?.primary?.url ?: "",
iconUrl = "",
notificationId = id().toString(),
)
private fun WikimediaNotification.toCommonsNotification() =
Notification(
notificationType = NotificationType.UNKNOWN,
notificationText = contents?.compactHeader ?: "",
date = DateUtil.getMonthOnlyDateString(timestamp),
link = contents?.links?.primary?.url ?: "",
iconUrl = "",
notificationId = id().toString(),
)
}
}

View file

@ -1,9 +1,12 @@
package fr.free.nrw.commons.notification.models;
import timber.log.Timber;
public enum NotificationType {
THANK_YOU_EDIT("thank-you-edit"),
EDIT_USER_TALK("edit-user-talk"),
MENTION("mention"),
EMAIL("email"),
WELCOME("welcome"),
UNKNOWN("unknown");
private String type;