extracting the queued notification events persistence to its own file

This commit is contained in:
Adam Brown 2021-11-18 13:17:41 +00:00
parent 940fe634c4
commit fb5e3cdfcd
3 changed files with 77 additions and 49 deletions

View file

@ -161,7 +161,7 @@ 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.persistState(context, session) notificationState.persist(context, session)
} }
} }

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2021 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.notifications
import android.content.Context
import org.matrix.android.sdk.api.session.Session
import timber.log.Timber
import java.io.File
import java.io.FileOutputStream
// TODO Multi-account
private const val ROOMS_NOTIFICATIONS_FILE_NAME = "im.vector.notifications.cache"
private const val KEY_ALIAS_SECRET_STORAGE = "notificationMgr"
object NotificationEventPersistence {
fun loadEvents(context: Context, currentSession: Session?): NotificationEventQueue {
try {
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
if (file.exists()) {
file.inputStream().use {
val events: ArrayList<NotifiableEvent>? = currentSession?.loadSecureSecret(it, KEY_ALIAS_SECRET_STORAGE)
if (events != null) {
return NotificationEventQueue(events.toMutableList())
}
}
}
} catch (e: Throwable) {
Timber.e(e, "## Failed to load cached notification info")
}
return NotificationEventQueue()
}
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")
}
}
}
private fun deleteCachedRoomNotifications(context: Context) {
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
if (file.exists()) {
file.delete()
}
}
}

View file

@ -18,13 +18,6 @@ package im.vector.app.features.notifications
import android.content.Context import android.content.Context
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import timber.log.Timber
import java.io.File
import java.io.FileOutputStream
// TODO Mutliaccount
private const val ROOMS_NOTIFICATIONS_FILE_NAME = "im.vector.notifications.cache"
private const val KEY_ALIAS_SECRET_STORAGE = "notificationMgr"
class NotificationState( class NotificationState(
/** /**
@ -65,57 +58,20 @@ class NotificationState(
fun hasAlreadyRendered(eventsToRender: List<ProcessedEvent<NotifiableEvent>>) = renderedEvents == eventsToRender fun hasAlreadyRendered(eventsToRender: List<ProcessedEvent<NotifiableEvent>>) = renderedEvents == eventsToRender
fun persistState(context: Context, currentSession: Session) { fun persist(context: Context, session: Session) {
synchronized(queuedEvents) { NotificationEventPersistence.persistEvents(queuedEvents, context, 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")
}
}
}
private fun deleteCachedRoomNotifications(context: Context) {
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
if (file.exists()) {
file.delete()
}
} }
companion object { companion object {
fun createInitialNotificationState(context: Context, currentSession: Session?): NotificationState { fun createInitialNotificationState(context: Context, currentSession: Session?): NotificationState {
val queuedEvents = loadEventInfo(context, currentSession) val queuedEvents = NotificationEventPersistence.loadEvents(context, currentSession)
return NotificationState( return NotificationState(
queuedEvents = queuedEvents, queuedEvents = queuedEvents,
renderedEvents = queuedEvents.rawEvents().map { ProcessedEvent(ProcessedEvent.Type.KEEP, it) }.toMutableList(), renderedEvents = queuedEvents.rawEvents().map { ProcessedEvent(ProcessedEvent.Type.KEEP, it) }.toMutableList(),
seenEventIds = CircularCache.create(cacheSize = 25) seenEventIds = CircularCache.create(cacheSize = 25)
) )
} }
private fun loadEventInfo(context: Context, currentSession: Session?): NotificationEventQueue {
try {
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
if (file.exists()) {
file.inputStream().use {
val events: ArrayList<NotifiableEvent>? = currentSession?.loadSecureSecret(it, KEY_ALIAS_SECRET_STORAGE)
if (events != null) {
return NotificationEventQueue(events.toMutableList())
}
}
}
} catch (e: Throwable) {
Timber.e(e, "## Failed to load cached notification info")
}
return NotificationEventQueue()
}
} }
} }