mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 21:48:50 +03:00
Refresh notification drawer in a background thread. It also fixes the person and room avatar display
This commit is contained in:
parent
568e8c8bc0
commit
62a81a556e
3 changed files with 42 additions and 136 deletions
|
@ -18,73 +18,38 @@ package im.vector.riotx.features.notifications
|
|||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.DecodeFormat
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* FIXME It works, but it does not refresh the notification, when it's already displayed
|
||||
*/
|
||||
class BitmapLoader(val context: Context,
|
||||
val listener: BitmapLoaderListener) {
|
||||
class BitmapLoader(val context: Context) {
|
||||
|
||||
/**
|
||||
* Avatar Url -> Icon
|
||||
*/
|
||||
private val cache = HashMap<String, Bitmap>()
|
||||
|
||||
// URLs to load
|
||||
private val toLoad = HashSet<String>()
|
||||
private val cache = HashMap<String, Bitmap?>()
|
||||
|
||||
// Black list of URLs (broken URL, etc.)
|
||||
private val blacklist = HashSet<String>()
|
||||
|
||||
private var uiHandler = Handler()
|
||||
|
||||
private val handlerThread: HandlerThread = HandlerThread("BitmapLoader", Thread.MIN_PRIORITY)
|
||||
private var backgroundHandler: Handler
|
||||
|
||||
init {
|
||||
handlerThread.start()
|
||||
backgroundHandler = Handler(handlerThread.looper)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get icon of a room.
|
||||
* If already in cache, use it, else load it and call BitmapLoaderListener.onBitmapsLoaded() when ready
|
||||
*/
|
||||
@WorkerThread
|
||||
fun getRoomBitmap(path: String?): Bitmap? {
|
||||
if (path == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
synchronized(cache) {
|
||||
if (cache[path] != null) {
|
||||
return cache[path]
|
||||
}
|
||||
|
||||
// Add to the queue, if not blacklisted
|
||||
if (!blacklist.contains(path)) {
|
||||
if (toLoad.contains(path)) {
|
||||
// Wait
|
||||
} else {
|
||||
toLoad.add(path)
|
||||
|
||||
backgroundHandler.post {
|
||||
loadRoomBitmap(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return cache.getOrPut(path) {
|
||||
loadRoomBitmap(path)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun loadRoomBitmap(path: String) {
|
||||
private fun loadRoomBitmap(path: String): Bitmap? {
|
||||
val bitmap = path.let {
|
||||
try {
|
||||
Glide.with(context)
|
||||
|
@ -99,26 +64,11 @@ class BitmapLoader(val context: Context,
|
|||
}
|
||||
}
|
||||
|
||||
synchronized(cache) {
|
||||
if (bitmap == null) {
|
||||
// Add to the blacklist
|
||||
blacklist.add(path)
|
||||
} else {
|
||||
cache[path] = bitmap
|
||||
}
|
||||
|
||||
toLoad.remove(path)
|
||||
|
||||
if (toLoad.isEmpty()) {
|
||||
uiHandler.post {
|
||||
listener.onBitmapsLoaded()
|
||||
}
|
||||
}
|
||||
if (bitmap == null) {
|
||||
// Add to the blacklist
|
||||
blacklist.add(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface BitmapLoaderListener {
|
||||
fun onBitmapsLoaded()
|
||||
return bitmap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@ package im.vector.riotx.features.notifications
|
|||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import com.bumptech.glide.Glide
|
||||
|
@ -27,67 +25,34 @@ import com.bumptech.glide.load.DecodeFormat
|
|||
import com.bumptech.glide.request.RequestOptions
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* FIXME It works, but it does not refresh the notification, when it's already displayed
|
||||
*/
|
||||
class IconLoader(val context: Context,
|
||||
val listener: IconLoaderListener) {
|
||||
class IconLoader(val context: Context) {
|
||||
|
||||
/**
|
||||
* Avatar Url -> Icon
|
||||
*/
|
||||
private val cache = HashMap<String, IconCompat>()
|
||||
|
||||
// URLs to load
|
||||
private val toLoad = HashSet<String>()
|
||||
private val cache = HashMap<String, IconCompat?>()
|
||||
|
||||
// Black list of URLs (broken URL, etc.)
|
||||
private val blacklist = HashSet<String>()
|
||||
|
||||
private var uiHandler = Handler()
|
||||
|
||||
private val handlerThread: HandlerThread = HandlerThread("IconLoader", Thread.MIN_PRIORITY)
|
||||
private var backgroundHandler: Handler
|
||||
|
||||
init {
|
||||
handlerThread.start()
|
||||
backgroundHandler = Handler(handlerThread.looper)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get icon of a user.
|
||||
* If already in cache, use it, else load it and call IconLoaderListener.onIconsLoaded() when ready
|
||||
* Before Android P, this does nothing because the icon won't be used
|
||||
*/
|
||||
@WorkerThread
|
||||
fun getUserIcon(path: String?): IconCompat? {
|
||||
if (path == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
return null
|
||||
}
|
||||
|
||||
synchronized(cache) {
|
||||
if (cache[path] != null) {
|
||||
return cache[path]
|
||||
}
|
||||
|
||||
// Add to the queue, if not blacklisted
|
||||
if (!blacklist.contains(path)) {
|
||||
if (toLoad.contains(path)) {
|
||||
// Wait
|
||||
} else {
|
||||
toLoad.add(path)
|
||||
|
||||
backgroundHandler.post {
|
||||
loadUserIcon(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
return cache.getOrPut(path) {
|
||||
loadUserIcon(path)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun loadUserIcon(path: String) {
|
||||
fun loadUserIcon(path: String): IconCompat? {
|
||||
val iconCompat = path.let {
|
||||
try {
|
||||
Glide.with(context)
|
||||
|
@ -105,26 +70,11 @@ class IconLoader(val context: Context,
|
|||
}
|
||||
}
|
||||
|
||||
synchronized(cache) {
|
||||
if (iconCompat == null) {
|
||||
// Add to the blacklist
|
||||
blacklist.add(path)
|
||||
} else {
|
||||
cache[path] = iconCompat
|
||||
}
|
||||
|
||||
toLoad.remove(path)
|
||||
|
||||
if (toLoad.isEmpty()) {
|
||||
uiHandler.post {
|
||||
listener.onIconsLoaded()
|
||||
}
|
||||
}
|
||||
if (iconCompat == null) {
|
||||
// Add to the blacklist
|
||||
blacklist.add(path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface IconLoaderListener {
|
||||
fun onIconsLoaded()
|
||||
return iconCompat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@ package im.vector.riotx.features.notifications
|
|||
import android.app.Notification
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.Person
|
||||
import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
||||
|
@ -44,6 +47,14 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
|
|||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
private val outdatedDetector: OutdatedEventDetector?) {
|
||||
|
||||
private val handlerThread: HandlerThread = HandlerThread("NotificationDrawerManager", Thread.MIN_PRIORITY)
|
||||
private var backgroundHandler: Handler
|
||||
|
||||
init {
|
||||
handlerThread.start()
|
||||
backgroundHandler = Handler(handlerThread.looper)
|
||||
}
|
||||
|
||||
//The first time the notification drawer is refreshed, we force re-render of all notifications
|
||||
private var firstTime = true
|
||||
|
||||
|
@ -53,21 +64,9 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
|
|||
|
||||
private var currentRoomId: String? = null
|
||||
|
||||
private var iconLoader = IconLoader(context,
|
||||
object : IconLoader.IconLoaderListener {
|
||||
override fun onIconsLoaded() {
|
||||
// Force refresh
|
||||
refreshNotificationDrawer()
|
||||
}
|
||||
})
|
||||
private var iconLoader = IconLoader(context)
|
||||
|
||||
private var bitmapLoader = BitmapLoader(context,
|
||||
object : BitmapLoader.BitmapLoaderListener {
|
||||
override fun onBitmapsLoaded() {
|
||||
// Force refresh
|
||||
refreshNotificationDrawer()
|
||||
}
|
||||
})
|
||||
private var bitmapLoader = BitmapLoader(context)
|
||||
|
||||
/**
|
||||
Should be called as soon as a new event is ready to be displayed.
|
||||
|
@ -171,6 +170,13 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
|
|||
|
||||
|
||||
fun refreshNotificationDrawer() {
|
||||
backgroundHandler.post {
|
||||
refreshNotificationDrawerBg()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun refreshNotificationDrawerBg() {
|
||||
val session = activeSessionHolder.getActiveSession()
|
||||
val user = session.getUser(session.sessionParams.credentials.userId)
|
||||
val myUserDisplayName = user?.displayName ?: ""
|
||||
|
|
Loading…
Reference in a new issue