From 7693f3bc6c7607ade8015838e0cbfaf3bdc1160f Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Fri, 19 Nov 2021 09:33:28 +0000 Subject: [PATCH] lifting the persistence out of the notification state --- .../NotificationDrawerManager.kt | 33 ++++++++++++++----- .../NotificationEventPersistence.kt | 31 +++++++++-------- .../notifications/NotificationState.kt | 18 ++-------- 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt index 81db029d8b..fa56e3b8ed 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt @@ -38,12 +38,15 @@ import javax.inject.Singleton * Events can be grouped into the same notification, old (already read) events can be removed to do some cleaning. */ @Singleton -class NotificationDrawerManager @Inject constructor(private val context: Context, - private val notificationDisplayer: NotificationDisplayer, - private val vectorPreferences: VectorPreferences, - private val activeSessionDataSource: ActiveSessionDataSource, - private val notifiableEventProcessor: NotifiableEventProcessor, - private val notificationRenderer: NotificationRenderer) { +class NotificationDrawerManager @Inject constructor( + private val context: Context, + private val notificationDisplayer: NotificationDisplayer, + private val vectorPreferences: VectorPreferences, + private val activeSessionDataSource: ActiveSessionDataSource, + private val notifiableEventProcessor: NotifiableEventProcessor, + private val notificationRenderer: NotificationRenderer, + private val notificationEventPersistence: NotificationEventPersistence +) { private val handlerThread: HandlerThread = HandlerThread("NotificationDrawerManager", Thread.MIN_PRIORITY) private var backgroundHandler: Handler @@ -55,7 +58,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context /** * Lazily initializes the NotificationState as we rely on having a current session in order to fetch the persisted queue of events */ - private val notificationState by lazy { NotificationState.createInitialNotificationState(context, currentSession) } + private val notificationState by lazy { createInitialNotificationState() } private val avatarSize = context.resources.getDimensionPixelSize(R.dimen.profile_avatar_size) private var currentRoomId: String? = null private val firstThrottler = FirstThrottler(200) @@ -67,6 +70,14 @@ class NotificationDrawerManager @Inject constructor(private val context: Context backgroundHandler = Handler(handlerThread.looper) } + private fun createInitialNotificationState(): NotificationState { + val queuedEvents = notificationEventPersistence.loadEvents(currentSession, factory = { rawEvents -> + NotificationEventQueue(rawEvents.toMutableList(), seenEventIds = CircularCache.create(cacheSize = 25)) + }) + val renderedEvents = queuedEvents.rawEvents().map { ProcessedEvent(ProcessedEvent.Type.KEEP, it) }.toMutableList() + return NotificationState(queuedEvents, renderedEvents) + } + /** Should be called as soon as a new event is ready to be displayed. The notification corresponding to this event will not be displayed until @@ -161,7 +172,13 @@ class NotificationDrawerManager @Inject constructor(private val context: Context notificationState.clearAndAddRenderedEvents(eventsToRender) val session = currentSession ?: return renderEvents(session, eventsToRender) - notificationState.persist(context, session) + persistEvents(session) + } + } + + private fun persistEvents(session: Session) { + notificationState.queuedEvents { queuedEvents -> + notificationEventPersistence.persistEvents(queuedEvents, session) } } diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationEventPersistence.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationEventPersistence.kt index 11cc247b48..a4a7570fec 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationEventPersistence.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationEventPersistence.kt @@ -21,14 +21,15 @@ import org.matrix.android.sdk.api.session.Session import timber.log.Timber import java.io.File import java.io.FileOutputStream +import javax.inject.Inject // TODO Multi-account private const val ROOMS_NOTIFICATIONS_FILE_NAME = "im.vector.notifications.cache" private const val KEY_ALIAS_SECRET_STORAGE = "notificationMgr" -object NotificationEventPersistence { +class NotificationEventPersistence @Inject constructor(private val context: Context) { - fun loadEvents(context: Context, currentSession: Session?, factory: (List) -> NotificationEventQueue): NotificationEventQueue { + fun loadEvents(currentSession: Session?, factory: (List) -> NotificationEventQueue): NotificationEventQueue { try { val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME) if (file.exists()) { @@ -45,21 +46,19 @@ object NotificationEventPersistence { return factory(emptyList()) } - fun persistEvents(queuedEvents: NotificationEventQueue, context: Context, currentSession: Session) { - synchronized(queuedEvents) { - if (queuedEvents.isEmpty()) { - deleteCachedRoomNotifications(context) - return - } - try { - val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME) - if (!file.exists()) file.createNewFile() - FileOutputStream(file).use { - currentSession.securelyStoreObject(queuedEvents.rawEvents(), KEY_ALIAS_SECRET_STORAGE, it) - } - } catch (e: Throwable) { - Timber.e(e, "## Failed to save cached notification info") + fun persistEvents(queuedEvents: NotificationEventQueue, currentSession: Session) { + if (queuedEvents.isEmpty()) { + deleteCachedRoomNotifications(context) + return + } + try { + val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME) + if (!file.exists()) file.createNewFile() + FileOutputStream(file).use { + currentSession.securelyStoreObject(queuedEvents.rawEvents(), KEY_ALIAS_SECRET_STORAGE, it) } + } catch (e: Throwable) { + Timber.e(e, "## Failed to save cached notification info") } } diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationState.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationState.kt index c880b99db5..193116a6bc 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationState.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationState.kt @@ -16,9 +16,6 @@ package im.vector.app.features.notifications -import android.content.Context -import org.matrix.android.sdk.api.session.Session - class NotificationState( /** * The notifiable events queued for rendering or currently rendered @@ -53,18 +50,9 @@ class NotificationState( fun hasAlreadyRendered(eventsToRender: List>) = renderedEvents == eventsToRender - fun persist(context: Context, session: Session) { - NotificationEventPersistence.persistEvents(queuedEvents, context, session) - } - - companion object { - - fun createInitialNotificationState(context: Context, currentSession: Session?): NotificationState { - val queuedEvents = NotificationEventPersistence.loadEvents(context, currentSession, factory = { rawEvents -> - NotificationEventQueue(rawEvents.toMutableList(), seenEventIds = CircularCache.create(cacheSize = 25)) - }) - val renderedEvents = queuedEvents.rawEvents().map { ProcessedEvent(ProcessedEvent.Type.KEEP, it) }.toMutableList() - return NotificationState(queuedEvents, renderedEvents) + fun queuedEvents(block: (NotificationEventQueue) -> Unit) { + synchronized(queuedEvents) { + block(queuedEvents) } } }