Notification: display room avatar

This commit is contained in:
Benoit Marty 2019-06-25 17:31:53 +02:00
parent b388be93c8
commit 9fa3a75fb6
3 changed files with 135 additions and 15 deletions

View File

@ -0,0 +1,124 @@
/*
* Copyright 2019 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.riotredesign.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) {

/**
* Avatar Url -> Icon
*/
private val cache = HashMap<String, Bitmap>()

// URLs to load
private val toLoad = HashSet<String>()

// 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
*/
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 null
}

@WorkerThread
private fun loadRoomBitmap(path: String) {
val bitmap = path.let {
try {
Glide.with(context)
.asBitmap()
.load(path)
.format(DecodeFormat.PREFER_ARGB_8888)
.submit()
.get()
} catch (e: Exception) {
Timber.e(e, "decodeFile failed")
null
}
}

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()
}
}
}
}


interface BitmapLoaderListener {
fun onBitmapsLoaded()
}
}

View File

@ -18,8 +18,6 @@ package im.vector.riotredesign.features.notifications
import android.app.Notification import android.app.Notification
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.text.TextUtils
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.Person import androidx.core.app.Person
import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.Matrix
@ -59,6 +57,14 @@ class NotificationDrawerManager(val context: Context,
} }
}) })


private var bitmapLoader = BitmapLoader(context,
object : BitmapLoader.BitmapLoaderListener {
override fun onBitmapsLoaded() {
// Force refresh
refreshNotificationDrawer()
}
})

/** /**
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
@ -372,19 +378,10 @@ class NotificationDrawerManager(val context: Context,
if (events.isEmpty()) return null if (events.isEmpty()) return null


//Use the last event (most recent?) //Use the last event (most recent?)
val roomAvatarPath = events[events.size - 1].roomAvatarPath val roomAvatarPath = events.last().roomAvatarPath
?: events[events.size - 1].senderAvatarPath ?: events.last().senderAvatarPath
if (!TextUtils.isEmpty(roomAvatarPath)) {
val options = BitmapFactory.Options()
options.inPreferredConfig = Bitmap.Config.ARGB_8888
try {
return BitmapFactory.decodeFile(roomAvatarPath, options)
} catch (oom: OutOfMemoryError) {
Timber.e(oom, "decodeFile failed with an oom")
}


} return bitmapLoader.getRoomBitmap(roomAvatarPath)
return null
} }


private fun shouldIgnoreMessageEventInRoom(roomId: String?): Boolean { private fun shouldIgnoreMessageEventInRoom(roomId: String?): Boolean {

View File

@ -22,7 +22,6 @@ package im.vector.riotredesign.features.notifications
data class RoomEventGroupInfo( data class RoomEventGroupInfo(
val roomId: String, val roomId: String,
val roomDisplayName: String = "", val roomDisplayName: String = "",
val roomAvatarPath: String? = null,
val isDirect: Boolean = false val isDirect: Boolean = false
) { ) {
// An event in the list has not yet been display // An event in the list has not yet been display