Skip to content

Commit

Permalink
Merge pull request #2094 from OneSignal/feature/preventDefault_discar…
Browse files Browse the repository at this point in the history
…d_parameter

Add discard parameter to preventDefault()
  • Loading branch information
emawby committed May 28, 2024
2 parents 4727d9b + 64b309c commit d9c8110
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,11 @@ interface INotificationReceivedEvent {
* can still be manually displayed using `notification.display()`.
*/
fun preventDefault()

/**
* Call this to prevent OneSignal from displaying the notification automatically.
* @param discard an [preventDefault] set to true to dismiss the notification with no
* possibility of displaying it in the future.
*/
fun preventDefault(discard: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,11 @@ interface INotificationWillDisplayEvent {
* caller still has the option to display the notification by calling `notification.display()`.
*/
fun preventDefault()

/**
* Call this to prevent OneSignal from displaying the notification automatically.
* @param discard an [preventDefault] set to true to dismiss the notification with no
* possibility of displaying it in the future.
*/
fun preventDefault(discard: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ internal class NotificationReceivedEvent(
override val notification: Notification,
) : INotificationReceivedEvent {
var isPreventDefault: Boolean = false
var discard: Boolean = false

override fun preventDefault() {
preventDefault(false)
}

override fun preventDefault(discard: Boolean) {
Logging.debug("NotificationReceivedEvent.preventDefault()")
isPreventDefault = true
this.discard = discard
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ internal class NotificationWillDisplayEvent(
override val notification: Notification,
) : INotificationWillDisplayEvent {
var isPreventDefault: Boolean = false
var discard: Boolean = false

override fun preventDefault() {
preventDefault(false)
}

override fun preventDefault(discard: Boolean) {
Logging.debug("NotificationWillDisplayEvent.preventDefault()")
isPreventDefault = true
this.discard = discard
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ internal class NotificationGenerationProcessor(
GlobalScope.launch(Dispatchers.IO) {
_lifecycleService.externalRemoteNotificationReceived(notificationReceivedEvent)

if (notificationReceivedEvent.isPreventDefault) {
if (notificationReceivedEvent.discard) {
wantsToDisplay = false
} else if (notificationReceivedEvent.isPreventDefault) {
// wait on display waiter. If the caller calls `display` on the notification,
// we will exit `waitForWake` and set `wantsToDisplay` to true. If the callback
// never calls `display` we will timeout and never set `wantsToDisplay` to true.
Expand Down Expand Up @@ -105,7 +107,9 @@ internal class NotificationGenerationProcessor(
GlobalScope.launch(Dispatchers.IO) {
_lifecycleService.externalNotificationWillShowInForeground(notificationWillDisplayEvent)

if (notificationWillDisplayEvent.isPreventDefault) {
if (notificationWillDisplayEvent.discard) {
wantsToDisplay = false
} else if (notificationWillDisplayEvent.isPreventDefault) {
// wait on display waiter. If the caller calls `display` on the notification,
// we will exit `waitForWake` and set `wantsToDisplay` to true. If the callback
// never calls `display` we will timeout and never set `wantsToDisplay` to true.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeout
import org.json.JSONObject
import org.robolectric.annotation.Config

Expand Down Expand Up @@ -373,4 +374,99 @@ class NotificationGenerationProcessorTests : FunSpec({
)
}
}

test("processNotificationData should immediately drop the notification when will display callback indicates to") {
// Given
val context = ApplicationProvider.getApplicationContext<Context>()
val mockTime = MockHelper.time(1111)
val mockApplicationService = AndroidMockHelper.applicationService()
every { mockApplicationService.isInForeground } returns true
val mockNotificationDisplayer = mockk<INotificationDisplayer>()
val mockNotificationRepository = mockk<INotificationRepository>()
coEvery { mockNotificationRepository.doesNotificationExist(any()) } returns false
coEvery { mockNotificationRepository.createNotification(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()) } just runs
val mockNotificationSummaryManager = mockk<INotificationSummaryManager>()
val mockNotificationLifecycleService = mockk<INotificationLifecycleService>()
coEvery { mockNotificationLifecycleService.canReceiveNotification(any()) } returns true
coEvery { mockNotificationLifecycleService.notificationReceived(any()) } just runs
coEvery { mockNotificationLifecycleService.externalRemoteNotificationReceived(any()) } just runs
coEvery { mockNotificationLifecycleService.externalNotificationWillShowInForeground(any()) } answers {
val willDisplayEvent = firstArg<INotificationWillDisplayEvent>()
// Setting discard parameter to true indicating we should immediately discard
willDisplayEvent.preventDefault(true)
}

val notificationGenerationProcessor =
NotificationGenerationProcessor(
mockApplicationService,
mockNotificationDisplayer,
MockHelper.configModelStore(),
mockNotificationRepository,
mockNotificationSummaryManager,
mockNotificationLifecycleService,
mockTime,
)

val payload =
JSONObject()
.put("alert", "test message")
.put("title", "test title")
.put(
"custom",
JSONObject()
.put("i", "UUID1"),
)

// If discard is set to false this should timeout waiting for display()
withTimeout(1_000) {
notificationGenerationProcessor.processNotificationData(context, 1, payload, false, 1111)
}
}

test("processNotificationData should immediately drop the notification when received event callback indicates to") {
// Given
val context = ApplicationProvider.getApplicationContext<Context>()
val mockTime = MockHelper.time(1111)
val mockApplicationService = AndroidMockHelper.applicationService()
every { mockApplicationService.isInForeground } returns true
val mockNotificationDisplayer = mockk<INotificationDisplayer>()
val mockNotificationRepository = mockk<INotificationRepository>()
coEvery { mockNotificationRepository.doesNotificationExist(any()) } returns false
coEvery { mockNotificationRepository.createNotification(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()) } just runs
val mockNotificationSummaryManager = mockk<INotificationSummaryManager>()
val mockNotificationLifecycleService = mockk<INotificationLifecycleService>()
coEvery { mockNotificationLifecycleService.canReceiveNotification(any()) } returns true
coEvery { mockNotificationLifecycleService.notificationReceived(any()) } just runs
coEvery { mockNotificationLifecycleService.externalRemoteNotificationReceived(any()) } answers {
val receivedEvent = firstArg<INotificationReceivedEvent>()
receivedEvent.preventDefault(true)
}
coEvery { mockNotificationLifecycleService.externalNotificationWillShowInForeground(any()) } just runs

val notificationGenerationProcessor =
NotificationGenerationProcessor(
mockApplicationService,
mockNotificationDisplayer,
MockHelper.configModelStore(),
mockNotificationRepository,
mockNotificationSummaryManager,
mockNotificationLifecycleService,
mockTime,
)

val payload =
JSONObject()
.put("alert", "test message")
.put("title", "test title")
.put(
"custom",
JSONObject()
.put("i", "UUID1"),
)

// If discard is set to false this should timeout waiting for display()
withTimeout(1_000) {
notificationGenerationProcessor.processNotificationData(context, 1, payload, false, 1111)
}
}
})

0 comments on commit d9c8110

Please sign in to comment.