Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/res/layout/activity_push_notification.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
android:paddingTop="?attr/actionBarSize"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="10dp"
tools:listitem="@layout/item_push_notification" />

<androidx.appcompat.widget.AppCompatTextView
Expand Down
14 changes: 8 additions & 6 deletions app/src/org/commcare/activities/PushNotificationActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import org.commcare.activities.connect.viewmodel.PushNotificationViewModel
import org.commcare.adapters.PushNotificationAdapter
import org.commcare.android.database.connect.models.PushNotificationRecord
import org.commcare.dalvik.R
import org.commcare.dalvik.databinding.ActivityPushNotificationBinding
import org.commcare.google.services.analytics.AnalyticsParamValue
import org.commcare.google.services.analytics.CCAnalyticsParam
import org.commcare.google.services.analytics.FirebaseAnalyticsUtil
import org.commcare.pn.helper.NotificationBroadcastHelper
import org.commcare.preferences.NotificationPrefs
import org.commcare.utils.FirebaseMessagingUtil.getIntentForPNClick
import org.commcare.views.dialogs.CustomProgressDialog

class PushNotificationActivity : AppCompatActivity() {
class PushNotificationActivity : CommCareActivity<PushNotificationActivity>() {
private val binding: ActivityPushNotificationBinding by lazy {
ActivityPushNotificationBinding.inflate(layoutInflater)
}
Expand All @@ -32,7 +31,7 @@ class PushNotificationActivity : AppCompatActivity() {
initViews()
observeRetrieveNotificationApi()
registerForNewNotification()
pushNotificationViewModel.loadNotifications(isRefreshed = false)
pushNotificationViewModel.loadNotifications(isRefreshed = false, this)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Having an unlabeled input after a labeled one feels odd to me, thinking maybe better to remove the label here? So it looks like line 123

}

private fun observeRetrieveNotificationApi() {
Expand Down Expand Up @@ -109,7 +108,7 @@ class PushNotificationActivity : AppCompatActivity() {
}

R.id.notification_cloud_sync -> {
pushNotificationViewModel.loadNotifications(isRefreshed = true)
pushNotificationViewModel.loadNotifications(isRefreshed = true, this)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: same as above

true
}

Expand All @@ -121,7 +120,10 @@ class PushNotificationActivity : AppCompatActivity() {
// Whenever new notification is received, signalling is calling retrieve_notifications api
// so whenever this broadcast is received, new notification is already stored in local DB
// that's the reason that isRefreshed = false is required
pushNotificationViewModel.loadNotifications(false)
pushNotificationViewModel.loadNotifications(false, this)
}
}

override fun generateProgressDialog(taskId: Int): CustomProgressDialog =
CustomProgressDialog.newInstance(null, getString(R.string.please_wait), taskId)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.commcare.activities.connect.viewmodel

import android.app.Application
import android.content.Context
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
Expand All @@ -13,7 +14,9 @@ import org.commcare.connect.database.NotificationRecordDatabaseHelper
import org.commcare.pn.workermanager.NotificationsSyncWorkerManager
import org.commcare.utils.PushNotificationApiHelper.retrieveLatestPushNotifications

class PushNotificationViewModel(application: Application) : AndroidViewModel(application) {
class PushNotificationViewModel(
application: Application,
) : AndroidViewModel(application) {
private val _fetchApiError =
MutableLiveData<String>()
val fetchApiError: LiveData<String> =
Expand All @@ -23,36 +26,45 @@ class PushNotificationViewModel(application: Application) : AndroidViewModel(app
val allNotifications: LiveData<List<PushNotificationRecord>> = _allNotifications
private val _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> = _isLoading
fun loadNotifications(isRefreshed: Boolean) {

fun loadNotifications(
isRefreshed: Boolean,
context: Context,
) {
viewModelScope.launch(Dispatchers.IO) {
_isLoading.postValue(true)
// Load from DB first
if (!isRefreshed) {
val cachedNotifications =
NotificationRecordDatabaseHelper.getAllNotifications(getApplication()).orEmpty()
NotificationRecordDatabaseHelper
.getAllNotifications(context)
.orEmpty()
.sortedByDescending { it.createdDate }
if (cachedNotifications.isNotEmpty()) {
_isLoading.postValue(false)
}
_allNotifications.postValue(cachedNotifications)
}

val latestPushNotificationsFromApi = retrieveLatestPushNotifications(application)
latestPushNotificationsFromApi.onSuccess {
val currentNotifications = _allNotifications.value.orEmpty()
NotificationsSyncWorkerManager(
application,
it,
false
).startPNApiSync()
val updatedNotifications = (it + currentNotifications).distinctBy { it.notificationId }
.sortedByDescending { it.createdDate }
_isLoading.postValue(false)
_allNotifications.postValue(updatedNotifications)
}.onFailure {
_isLoading.postValue(false)
_fetchApiError.postValue(it.message)
}
val latestPushNotificationsFromApi = retrieveLatestPushNotifications(context)
latestPushNotificationsFromApi
.onSuccess {
val currentNotifications = _allNotifications.value.orEmpty()
NotificationsSyncWorkerManager(
application,
it,
false,
).startPNApiSync()
val updatedNotifications =
(it + currentNotifications)
.distinctBy { it.notificationId }
.sortedByDescending { it.createdDate }
_isLoading.postValue(false)
_allNotifications.postValue(updatedNotifications)
}.onFailure {
_isLoading.postValue(false)
_fetchApiError.postValue(it.message)
}
}
}
}
34 changes: 20 additions & 14 deletions app/src/org/commcare/pn/helper/NotificationBroadcastHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,38 @@ import android.content.IntentFilter
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager

object NotificationBroadcastHelper {
const val ACTION_NEW_NOTIFICATIONS = "org.commcare.dalvik.action.NEW_NOTIFICATION"

fun registerForNotifications(
context: Context,
owner: LifecycleOwner,
onNewNotification: () -> Unit
onNewNotification: () -> Unit,
) {
val receiver = object : BroadcastReceiver() {
override fun onReceive(c: Context?, i: Intent?) {
onNewNotification()
val receiver =
object : BroadcastReceiver() {
override fun onReceive(
c: Context?,
i: Intent?,
) {
onNewNotification()
}
}
}

val manager = LocalBroadcastManager.getInstance(context)

owner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
manager.registerReceiver(receiver, IntentFilter(ACTION_NEW_NOTIFICATIONS))
onNewNotification()
}
owner.lifecycle.addObserver(
object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
manager.registerReceiver(receiver, IntentFilter(ACTION_NEW_NOTIFICATIONS))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see onNewNotification was removed here, just making sure that was intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it was intentional. Whenever any activity register for new notification broadcast, it was calling onNewNotification even though there were no new notifications.

}

override fun onPause(owner: LifecycleOwner) {
manager.unregisterReceiver(receiver)
}
})
override fun onPause(owner: LifecycleOwner) {
manager.unregisterReceiver(receiver)
}
},
)
}

fun sendNewNotificationBroadcast(context: Context) {
Expand Down