lifting the persistence out of the notification state
This commit is contained in:
parent
55fd362b3d
commit
7693f3bc6c
@ -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.
|
* Events can be grouped into the same notification, old (already read) events can be removed to do some cleaning.
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
class NotificationDrawerManager @Inject constructor(private val context: Context,
|
class NotificationDrawerManager @Inject constructor(
|
||||||
private val notificationDisplayer: NotificationDisplayer,
|
private val context: Context,
|
||||||
private val vectorPreferences: VectorPreferences,
|
private val notificationDisplayer: NotificationDisplayer,
|
||||||
private val activeSessionDataSource: ActiveSessionDataSource,
|
private val vectorPreferences: VectorPreferences,
|
||||||
private val notifiableEventProcessor: NotifiableEventProcessor,
|
private val activeSessionDataSource: ActiveSessionDataSource,
|
||||||
private val notificationRenderer: NotificationRenderer) {
|
private val notifiableEventProcessor: NotifiableEventProcessor,
|
||||||
|
private val notificationRenderer: NotificationRenderer,
|
||||||
|
private val notificationEventPersistence: NotificationEventPersistence
|
||||||
|
) {
|
||||||
|
|
||||||
private val handlerThread: HandlerThread = HandlerThread("NotificationDrawerManager", Thread.MIN_PRIORITY)
|
private val handlerThread: HandlerThread = HandlerThread("NotificationDrawerManager", Thread.MIN_PRIORITY)
|
||||||
private var backgroundHandler: Handler
|
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
|
* 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 val avatarSize = context.resources.getDimensionPixelSize(R.dimen.profile_avatar_size)
|
||||||
private var currentRoomId: String? = null
|
private var currentRoomId: String? = null
|
||||||
private val firstThrottler = FirstThrottler(200)
|
private val firstThrottler = FirstThrottler(200)
|
||||||
@ -67,6 +70,14 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
|
|||||||
backgroundHandler = Handler(handlerThread.looper)
|
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.
|
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
|
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)
|
notificationState.clearAndAddRenderedEvents(eventsToRender)
|
||||||
val session = currentSession ?: return
|
val session = currentSession ?: return
|
||||||
renderEvents(session, eventsToRender)
|
renderEvents(session, eventsToRender)
|
||||||
notificationState.persist(context, session)
|
persistEvents(session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun persistEvents(session: Session) {
|
||||||
|
notificationState.queuedEvents { queuedEvents ->
|
||||||
|
notificationEventPersistence.persistEvents(queuedEvents, session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,14 +21,15 @@ import org.matrix.android.sdk.api.session.Session
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
// TODO Multi-account
|
// TODO Multi-account
|
||||||
private const val ROOMS_NOTIFICATIONS_FILE_NAME = "im.vector.notifications.cache"
|
private const val ROOMS_NOTIFICATIONS_FILE_NAME = "im.vector.notifications.cache"
|
||||||
private const val KEY_ALIAS_SECRET_STORAGE = "notificationMgr"
|
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<NotifiableEvent>) -> NotificationEventQueue): NotificationEventQueue {
|
fun loadEvents(currentSession: Session?, factory: (List<NotifiableEvent>) -> NotificationEventQueue): NotificationEventQueue {
|
||||||
try {
|
try {
|
||||||
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
|
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
@ -45,21 +46,19 @@ object NotificationEventPersistence {
|
|||||||
return factory(emptyList())
|
return factory(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun persistEvents(queuedEvents: NotificationEventQueue, context: Context, currentSession: Session) {
|
fun persistEvents(queuedEvents: NotificationEventQueue, currentSession: Session) {
|
||||||
synchronized(queuedEvents) {
|
if (queuedEvents.isEmpty()) {
|
||||||
if (queuedEvents.isEmpty()) {
|
deleteCachedRoomNotifications(context)
|
||||||
deleteCachedRoomNotifications(context)
|
return
|
||||||
return
|
}
|
||||||
}
|
try {
|
||||||
try {
|
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
|
||||||
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
|
if (!file.exists()) file.createNewFile()
|
||||||
if (!file.exists()) file.createNewFile()
|
FileOutputStream(file).use {
|
||||||
FileOutputStream(file).use {
|
currentSession.securelyStoreObject(queuedEvents.rawEvents(), KEY_ALIAS_SECRET_STORAGE, it)
|
||||||
currentSession.securelyStoreObject(queuedEvents.rawEvents(), KEY_ALIAS_SECRET_STORAGE, it)
|
|
||||||
}
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
Timber.e(e, "## Failed to save cached notification info")
|
|
||||||
}
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
Timber.e(e, "## Failed to save cached notification info")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.app.features.notifications
|
package im.vector.app.features.notifications
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import org.matrix.android.sdk.api.session.Session
|
|
||||||
|
|
||||||
class NotificationState(
|
class NotificationState(
|
||||||
/**
|
/**
|
||||||
* The notifiable events queued for rendering or currently rendered
|
* The notifiable events queued for rendering or currently rendered
|
||||||
@ -53,18 +50,9 @@ class NotificationState(
|
|||||||
|
|
||||||
fun hasAlreadyRendered(eventsToRender: List<ProcessedEvent<NotifiableEvent>>) = renderedEvents == eventsToRender
|
fun hasAlreadyRendered(eventsToRender: List<ProcessedEvent<NotifiableEvent>>) = renderedEvents == eventsToRender
|
||||||
|
|
||||||
fun persist(context: Context, session: Session) {
|
fun queuedEvents(block: (NotificationEventQueue) -> Unit) {
|
||||||
NotificationEventPersistence.persistEvents(queuedEvents, context, session)
|
synchronized(queuedEvents) {
|
||||||
}
|
block(queuedEvents)
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user