Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notifications redesign #4274

Merged
merged 49 commits into from
Oct 26, 2021
Merged

Notifications redesign #4274

merged 49 commits into from
Oct 26, 2021

Conversation

ouchadam
Copy link
Contributor

@ouchadam ouchadam commented Oct 20, 2021

Notification redesign feature PR

Addresses an assortment of issues

The notifications logic has been redesigned in order to split the creation of the notifications and the displaying/rendering of them.
This aims to eliminate any race conditions between updating the child and group summary notifications which can cause duplicated notifications, sounds, vibration.

Another benefit of the redesign is the simplification of the flow allowing us to diff new events and rendered events which means we're able to stay better in sync with which notifications to display

Included reviewed PRs

JOINING ROOMS EVENT MARKING READ
after-multiple-joins after-mark-read
INCOMING MESSAGES ROOM INVITE ACCEPTING / READING
after-incoming-messages after-room-invite after-accepting-reading

@github-actions
Copy link

github-actions bot commented Oct 20, 2021

Unit Test Results

  60 files  +  12    60 suites  +12   53s ⏱️ -3s
117 tests +  26  117 ✔️ +  26  0 💤 ±0  0 ±0 
348 runs  +104  348 ✔️ +104  0 💤 ±0  0 ±0 

Results for commit 124061e. ± Comparison against base commit 109a5a6.

♻️ This comment has been updated with latest results.

@ouchadam ouchadam force-pushed the feature/adm/notification-redesign branch from d8919e8 to 7eaf0d8 Compare October 20, 2021 14:47
@bmarty
Copy link
Member

bmarty commented Oct 20, 2021

Doing some tests.

  • I have pushed 2 commits to stop using a room member avatar when there is no room avatar.
  • There is a regression with message redaction:
  1. send a message -> a notif is displayed
  2. redact the message -> the notif is still displayed, because I think there is no PUSH when message are redacted
  3. send another message -> PUSH; sync; the second message is displayed, and the first one is removed -> This is where the regression is seen, see the diff between prod (Element) and this branch (Element dbg):

image

@ouchadam
Copy link
Contributor Author

ouchadam commented Oct 20, 2021

ahhh good catch, this is because the redaction logic is only removing the message when all the messages are redacted

here's a failing test for the NotificationFactoryTest

@Test
fun `given a room with redacted and non redacted message events when mapping to notification then redacted events are removed`() = testWith(notificationFactory) {
    val roomWithRedactedMessage = mapOf(A_ROOM_ID to listOf(
            ProcessedEvent(Type.KEEP, A_MESSAGE_EVENT.copy(isRedacted = true)),
            ProcessedEvent(Type.KEEP, A_MESSAGE_EVENT.copy(eventId = "not-redacted"))
    ))
    val withRedactedRemoved = listOf(A_MESSAGE_EVENT.copy(eventId = "not-redacted"))
    val expectedNotification = roomGroupMessageCreator.givenCreatesRoomMessageFor(withRedactedRemoved, A_ROOM_ID, MY_USER_ID, MY_AVATAR_URL)

    val result = roomWithRedactedMessage.toNotifications(MY_USER_ID, MY_AVATAR_URL)

    result shouldBeEqualTo listOf(expectedNotification)
}

the fix is to add a redacted filter to the messages

val messageEvents = events.onlyKeptEvents().filterNot { it.isRedacted }

https://github.com/vector-im/element-android/pull/4274/files#diff-f84cd8e58c4dd28a339a6ad64f469236f48f2aef8a9483bd0eacce49ddbe9018R36

@bmarty
Copy link
Member

bmarty commented Oct 20, 2021

Another remark, I think fun loadEventInfo() will failed after an upgrade of the application, since the model has changed, so the file could not be deserialized (Not tested though). The failure will be caught, so no crash will occur.
This is maybe acceptable.
Also I have noticed that after an upgrade of the application, the notification are removed (by the system I guess), but I have never tested that a new notification would restore all the previously displayed notification.

@bmarty
Copy link
Member

bmarty commented Oct 20, 2021

ahhh good catch, this is because the redaction logic is only removing the message when all the messages are redacted

Thanks 😊

here's a failing test for the NotificationFactoryTest

TDD FTW!

@ouchadam
Copy link
Contributor Author

Another remark, I think fun loadEventInfo() will failed after an upgrade of the application, since the model has changed, so the file could not be deserialized (Not tested though). The failure will be caught, so no crash will occur. This is maybe acceptable. Also I have noticed that after an upgrade of the application, the notification are removed (by the system I guess), but I have never tested that a new notification would restore all the previously displayed notification.

that's a very good point that I completely missed

it's not ideal but at least it will only happen once for this upgrade


for the fix above I'm waiting for some test devices to charge so I can take a screenshot/gif of the redaction in action


private typealias ProcessedMessageEvents = List<ProcessedEvent<NotifiableMessageEvent>>

class NotificationFactory @Inject constructor(
Copy link
Member

Choose a reason for hiding this comment

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

The name is a bit confusing, this factory does not create Notifications (class from the Android SDK) but rather Notifications bound to actions (as far as I understand).
However, I do not know what would be a better name :/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's creating delegates/wrappers of android notification + element metadata, could be a ElementNotification + ElementNotificationFactory but it doesn't add much, totally open to ideas

Copy link
Member

@bmarty bmarty left a comment

Choose a reason for hiding this comment

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

Very nice work, thanks!
Maybe some important classes may required a small documentation, but this is not worth than the rest of the code...
Happy to see NotificationDrawerManager.kt file size reduced from 664 to 134 lines 🎉

when (summaryNotification) {
SummaryNotification.Removed -> {
Timber.d("Removing summary notification")
notificationDisplayer.cancelNotificationMessage(null, SUMMARY_NOTIFICATION_ID)
Copy link
Member

@bmarty bmarty Oct 20, 2021

Choose a reason for hiding this comment

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

At first sight, I was wondering if it was worth continuing with the rest of the fun (so add a return statement), but reading more carefully, I think the answer is yes, we have to remove the other notifications

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep exactly ^^^ we also need to update the summary is a specific order to avoiding flickering

}
}

fun <T> List<ProcessedEvent<T>>.onlyKeptEvents() = filter { it.type == ProcessedEvent.Type.KEEP }.map { it.event }
Copy link
Member

Choose a reason for hiding this comment

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

Nit: to avoid multiple iterations on list, reduce to

fun <T> List<ProcessedEvent<T>>.onlyKeptEvents() = mapNotNull { processedEvent ->
    processedEvent.event.takeIf { processedEvent.type == ProcessedEvent.Type.KEEP }
}

(not tested)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point 0d81fc9

is working as expected

}
}

sealed interface RoomNotification {
Copy link
Member

Choose a reason for hiding this comment

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

kudos for the usage of sealed interface

@bmarty
Copy link
Member

bmarty commented Oct 20, 2021

(I've pushed a small commit about formatting. I think I will not push other commits on this branch)

@bmarty
Copy link
Member

bmarty commented Oct 20, 2021

I have seen that too, not sure where it comes from, and this is maybe not new...

image

@ouchadam ouchadam mentioned this pull request Oct 21, 2021
@ouchadam
Copy link
Contributor Author

redacted events fixed by #4286

@ouchadam ouchadam force-pushed the feature/adm/notification-redesign branch from de62a33 to 5b43e5e Compare October 26, 2021 07:47
Copy link
Member

@bmarty bmarty left a comment

Choose a reason for hiding this comment

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

I think you can merge this PR if you think it is up to date regarding latest develop. I think you have force pushed the branch so you probably did a git rebase?
Anyway feel free to merge it (and close related issues).

Thanks!

@ouchadam
Copy link
Contributor Author

🎉

I did rebase this morning but will do another one and a quick test before merging

- we only want to notify users when they receive an invititation, not when they've accepted it
…an avoid eager notification cancels and rely on the main notification refresh flow
- also makes the notifiable events sealed interfaces so that we can copy the data classes with new redacted values when it changes
…ed or made immutable by the notification redesign
…can be replaced

- makes the property immutable as only the creation of the event knows if it can be replace eg it came from a push or the /sync event stream
ouchadam and others added 25 commits October 26, 2021 20:03
…l notifications

- adds some comments to explain the positioning
- this allows us to only synchronise of the event list modifications rather than the entire notification creation/rendering which should in turn reduce some of our ANRs #4214
…ed event id

- this state will be used to diff the currently rendered events against the new ones
… allow us to dismiss notifications from removed events
…cting the processed type when creating the notifications
…assing around the process notificatiable events

- also includes @JvmName on all conflicting extensions for consistency
@ouchadam ouchadam force-pushed the feature/adm/notification-redesign branch from 5b43e5e to 124061e Compare October 26, 2021 19:07
@ouchadam
Copy link
Contributor Author

CI happy, local testing is also still working as expected, going to merge!

@ouchadam ouchadam merged commit fe9dde5 into develop Oct 26, 2021
@ouchadam ouchadam deleted the feature/adm/notification-redesign branch October 26, 2021 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants