Skip to content

Commit

Permalink
notif [nfc]: Remove unused functions and Class.
Browse files Browse the repository at this point in the history
These were involved in constructing old notification UI and are
no longer needed.
  • Loading branch information
AkashDhiman committed Aug 5, 2021
1 parent 291ad40 commit 6575678
Show file tree
Hide file tree
Showing 5 changed files with 8 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,13 @@
import org.unimodules.core.interfaces.SingletonModule;

import com.zulipmobile.generated.BasePackageList;
import com.zulipmobile.notifications.ConversationMap;
import com.zulipmobile.notifications.FCMPushNotifications;
import com.zulipmobile.notifications.NotificationsPackage;
import com.zulipmobile.sharing.SharingPackage;

public class MainApplication extends Application implements ReactApplication {
private final ReactModuleRegistryProvider mModuleRegistryProvider = new ReactModuleRegistryProvider(new BasePackageList().getPackageList(), null);

private ConversationMap conversations;

public ConversationMap getConversations() {
return conversations;
}

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
Expand Down Expand Up @@ -79,7 +72,6 @@ public void onCreate() {
FCMPushNotifications.createNotificationChannel(this);
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
conversations = new ConversationMap();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.text.TextUtils
import android.util.Log
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.NotificationCompat
Expand Down Expand Up @@ -56,7 +54,7 @@ private fun logNotificationData(msg: String, data: Bundle) {
Log.v(TAG, "$msg: $data")
}

internal fun onReceived(context: Context, conversations: ConversationMap, mapData: Map<String, String>) {
internal fun onReceived(context: Context, mapData: Map<String, String>) {
// TODO refactor to not need this; reflects a juxtaposition of FCM with old GCM interfaces.
val data = Bundle()
for ((key, value) in mapData) {
Expand All @@ -73,14 +71,8 @@ internal fun onReceived(context: Context, conversations: ConversationMap, mapDat
}

if (fcmMessage is MessageFcmMessage) {
addConversationToMap(fcmMessage, conversations)
updateNotification(context, conversations, fcmMessage)
} else if (fcmMessage is RemoveFcmMessage) {
removeMessagesFromMap(conversations, fcmMessage)
if (conversations.isEmpty()) {
NotificationManagerCompat.from(context).cancelAll()
}
}
updateNotification(context, fcmMessage)
} // TODO handle case for RemoveFcmMessage
}

private fun createViewPendingIntent(fcmMessage: MessageFcmMessage, context: Context): PendingIntent {
Expand Down Expand Up @@ -157,7 +149,7 @@ private fun createSummaryNotification(
}

private fun updateNotification(
context: Context, conversations: ConversationMap, fcmMessage: MessageFcmMessage) {
context: Context, fcmMessage: MessageFcmMessage) {
val user = Person.Builder().setName("You").build()
val sender = Person.Builder()
.setName(fcmMessage.sender.fullName)
Expand Down Expand Up @@ -222,95 +214,13 @@ private fun updateNotification(
}
}

private fun getNotificationSoundUri(context: Context): Uri {
// Note: Provide default notification sound until we found a good sound
// return Uri.parse("${ContentResolver.SCHEME_ANDROID_RESOURCE}://${context.packageName}/${R.raw.zulip}")
return Settings.System.DEFAULT_NOTIFICATION_URI
}

private fun getNotificationBuilder(
context: Context, conversations: ConversationMap, fcmMessage: MessageFcmMessage): NotificationCompat.Builder {
val builder = NotificationCompat.Builder(context, CHANNEL_ID)

val viewPendingIntent = createViewPendingIntent(fcmMessage, context)
builder.setContentIntent(viewPendingIntent)
builder.setAutoCancel(true)

val totalMessagesCount = extractTotalMessagesCount(conversations)

if (BuildConfig.DEBUG) {
builder.setSmallIcon(R.mipmap.ic_launcher)
} else {
builder.setSmallIcon(R.drawable.zulip_notification)
}

// This should agree with `BRAND_COLOR` in the JS code.
builder.setColor(Color.rgb(100, 146, 254))

val nameList = extractNames(conversations)

if (conversations.size == 1 && nameList.size == 1) {
//Only one 1 notification therefore no using of big view styles
if (totalMessagesCount > 1) {
builder.setContentTitle("${fcmMessage.sender.fullName} ($totalMessagesCount)")
} else {
builder.setContentTitle(fcmMessage.sender.fullName)
}
builder.setContentText(fcmMessage.content)
if (fcmMessage.recipient is Recipient.Stream) {
val (stream, topic) = fcmMessage.recipient
val displayTopic = "$stream > $topic"
builder.setSubText("Message on $displayTopic")
}
fetchBitmap(sizedURL(context, fcmMessage.sender.avatarURL, 64f))
?.let { builder.setLargeIcon(it) }
builder.setStyle(NotificationCompat.BigTextStyle().bigText(fcmMessage.content))
} else {
val numConversations = context.resources.getQuantityString(
R.plurals.numConversations, conversations.size, conversations.size)
builder.setContentTitle("$totalMessagesCount messages in $numConversations")
builder.setContentText("Messages from ${TextUtils.join(",", nameList)}")
val inboxStyle = NotificationCompat.InboxStyle(builder)
inboxStyle.setSummaryText(numConversations)
buildNotificationContent(conversations, inboxStyle)
builder.setStyle(inboxStyle)
}

try {
ShortcutBadger.applyCount(context, totalMessagesCount)
} catch (e: Exception) {
Log.e(TAG, "BADGE ERROR: $e")
}

builder.setWhen(fcmMessage.timeMs)
builder.setShowWhen(true)

val vPattern = longArrayOf(0, 100, 200, 100)
// NB the DEFAULT_VIBRATE flag below causes this to have no effect.
// TODO: choose a vibration pattern we like, and unset DEFAULT_VIBRATE.
builder.setVibrate(vPattern)

builder.setDefaults(NotificationCompat.DEFAULT_VIBRATE or NotificationCompat.DEFAULT_LIGHTS)

builder.addAction(createDismissAction(context))

val soundUri = getNotificationSoundUri(context)
builder.setSound(soundUri)
return builder
}

internal fun onOpened(application: ReactApplication, conversations: ConversationMap, data: Bundle) {
internal fun onOpened(application: ReactApplication, data: Bundle) {
logNotificationData("notif opened", data)
notifyReact(application, data)
clearConversations(conversations)
try {
ShortcutBadger.removeCount(application as Context)
} catch (e: Exception) {
Log.e(TAG, "BADGE ERROR: $e")
}

}

internal fun onClear(context: Context, conversations: ConversationMap) {
clearConversations(conversations)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ public void onMessageReceived(RemoteMessage message) {
if (!(applicationContext instanceof MainApplication)) {
return;
}
final ConversationMap conversations =
((MainApplication) applicationContext).getConversations();
FCMPushNotifications.onReceived(this, conversations, message.getData());
FCMPushNotifications.onReceived(this, message.getData());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,16 @@

package com.zulipmobile.notifications

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.TextUtils
import android.text.style.StyleSpan
import android.util.Log
import android.util.TypedValue
import androidx.core.app.NotificationCompat
import java.io.IOException
import java.io.InputStream
import java.net.URL
import java.util.*

@JvmField
val TAG = "ZulipNotif"

/**
* All Zulip messages we're showing in notifications.
*
* Each key identifies a conversation; see [buildKeyString].
*
* Each value is the messages in the conversation, in the order we
* received them.
*/
class ConversationMap : LinkedHashMap<String, MutableList<MessageFcmMessage>>()

fun fetchBitmap(url: URL): Bitmap? {
return try {
val connection = url.openConnection()
Expand All @@ -41,101 +23,3 @@ fun fetchBitmap(url: URL): Bitmap? {
null
}
}

fun sizedURL(context: Context, url: URL, dpSize: Float): URL {
// From http://stackoverflow.com/questions/4605527/
val r = context.resources
val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpSize, r.displayMetrics)
val query = if (url.query != null) "${url.query}&s=$px" else "s=$px"
return URL(url, "?$query")
}

fun buildNotificationContent(conversations: ConversationMap, inboxStyle: NotificationCompat.InboxStyle) {
for (conversation in conversations.values) {
// TODO ensure latest sender is shown last? E.g. Gmail-style A, B, ..., A.
val seenSenders = HashSet<String>()
val names = ArrayList<String>()
for (message in conversation) {
if (seenSenders.contains(message.sender.email))
continue;
seenSenders.add(message.sender.email)
names.add(message.sender.fullName)
}

val builder = SpannableStringBuilder()
builder.append(TextUtils.join(", ", names))
builder.setSpan(StyleSpan(android.graphics.Typeface.BOLD),
0, builder.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
builder.append(": ")
builder.append(conversation.last().content)
inboxStyle.addLine(builder)
}
}

fun extractTotalMessagesCount(conversations: ConversationMap): Int {
var totalNumber = 0
for ((_, value) in conversations) {
totalNumber += value.size
}
return totalNumber
}

/**
* Formats -
* stream message - fullName:streamName:'stream'
* group message - fullName:Recipients:'group'
* private message - fullName:Email:'private'
*/
private fun buildKeyString(fcmMessage: MessageFcmMessage): String {
val recipient = fcmMessage.recipient
return when (recipient) {
is Recipient.Stream -> String.format("%s:stream", recipient.stream)
is Recipient.GroupPm -> String.format("%s:group", recipient.getPmUsersString())
is Recipient.Pm -> String.format("%s:private", fcmMessage.sender.email)
}
}

fun extractNames(conversations: ConversationMap): ArrayList<String> {
val namesSet = LinkedHashSet<String>()
for (fcmMessages in conversations.values) {
for (fcmMessage in fcmMessages) {
namesSet.add(fcmMessage.sender.fullName)
}
}
return ArrayList(namesSet)
}

fun addConversationToMap(fcmMessage: MessageFcmMessage, conversations: ConversationMap) {
val key = buildKeyString(fcmMessage)
var messages: MutableList<MessageFcmMessage>? = conversations[key]
if (messages == null) {
messages = ArrayList()
}
messages.add(fcmMessage)
conversations[key] = messages
}

fun removeMessagesFromMap(conversations: ConversationMap, removeFcmMessage: RemoveFcmMessage) {
// We don't have the information to compute what key we ought to find each message under,
// so just walk the whole thing. If the user has >100 notifications, this linear scan
// won't be their worst problem anyway...
//
// TODO redesign this whole data structure, for many reasons.
val it = conversations.values.iterator()
while (it.hasNext()) {
val messages: MutableList<MessageFcmMessage> = it.next()
for (i in messages.indices.reversed()) {
if (removeFcmMessage.messageIds.contains(messages[i].zulipMessageId)) {
messages.removeAt(i)
}
}
if (messages.isEmpty()) {
it.remove()
}
}
}

fun clearConversations(conversations: ConversationMap) {
conversations.clear()
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ protected void onHandleIntent(Intent intent) {
if (!(applicationContext instanceof MainApplication)) {
return;
}
final ConversationMap conversations =
((MainApplication) applicationContext).getConversations();
if (ACTION_VIEW.equals(intent.getAction())) {
final Bundle data = intent.getBundleExtra(EXTRA_NOTIFICATION_DATA);
FCMPushNotifications.onOpened((ReactApplication) getApplication(), conversations, data);
FCMPushNotifications.onOpened((ReactApplication) getApplication(), data);
} else if (ACTION_CLEAR.equals(intent.getAction())) {
FCMPushNotifications.onClear(this, conversations);
// TODO implement dismiss
}
}
}

0 comments on commit 6575678

Please sign in to comment.