Create ShortcutBuilder and use

This commit is contained in:
Emma Vanbrabant 2020-05-09 19:52:27 +01:00
parent 1cafca6de6
commit 54ecc25831
5 changed files with 151 additions and 2 deletions

View File

@ -72,6 +72,27 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
.into(target)
}
@AnyThread
fun shortcutDrawable(context: Context, glideRequest: GlideRequests, matrixItem: MatrixItem): Drawable {
return glideRequest
.asDrawable()
.apply {
val resolvedUrl = resolvedUrl(matrixItem.avatarUrl)
if (resolvedUrl != null) {
load(resolvedUrl)
} else {
val avatarColor = avatarColor(matrixItem, context)
load(TextDrawable.builder()
.beginConfig()
.bold()
.endConfig()
.buildRect(matrixItem.firstLetterOfDisplayName(), avatarColor))
}
}
.submit()
.get()
}
@AnyThread
fun getCachedDrawable(glideRequest: GlideRequests, matrixItem: MatrixItem): Drawable {
return buildGlideRequest(glideRequest, matrixItem.avatarUrl)
@ -103,4 +124,16 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active
.load(resolvedUrl)
.apply(RequestOptions.circleCropTransform())
}
private fun resolvedUrl(avatarUrl: String?): String? {
return activeSessionHolder.getSafeActiveSession()?.contentUrlResolver()
?.resolveThumbnail(avatarUrl, THUMBNAIL_SIZE, THUMBNAIL_SIZE, ContentUrlResolver.ThumbnailMethod.SCALE)
}
private fun avatarColor(matrixItem: MatrixItem, context: Context): Int {
return when (matrixItem) {
is MatrixItem.UserItem -> ContextCompat.getColor(context, getColorFromUserId(matrixItem.id))
else -> ContextCompat.getColor(context, getColorFromRoomId(matrixItem.id))
}
}
}

View File

@ -65,6 +65,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
@Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var popupAlertManager: PopupAlertManager
@Inject lateinit var shortcutsHandler: ShortcutsHandler
private val drawerListener = object : DrawerLayout.SimpleDrawerListener() {
override fun onDrawerStateChanged(newState: Int) {
@ -144,6 +145,8 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
&& activeSessionHolder.getSafeActiveSession()?.hasAlreadySynced() == true) {
promptCompleteSecurityIfNeeded()
}
shortcutsHandler.observeRoomsAndBuildShortcuts(context = this)
}
private fun promptCompleteSecurityIfNeeded() {

View File

@ -16,6 +16,7 @@
package im.vector.riotx.features.home
import androidx.core.content.pm.ShortcutInfoCompat
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2020 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.riotx.features.home
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.os.Build
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.tag.RoomTag
import im.vector.matrix.android.api.util.toMatrixItem
import im.vector.riotx.core.glide.GlideApp
import im.vector.riotx.core.utils.DimensionConverter
import im.vector.riotx.features.home.room.detail.RoomDetailActivity
import io.reactivex.schedulers.Schedulers
import javax.inject.Inject
private val useAdaptiveIcon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
private const val adaptiveIconSizeDp = 108
private const val adaptiveIconOuterSidesDp = 18
class ShortcutsHandler @Inject constructor(
private val homeRoomListStore: HomeRoomListDataSource,
private val avatarRenderer: AvatarRenderer,
private val dimensionConverter: DimensionConverter
) {
@SuppressLint("CheckResult")
fun observeRoomsAndBuildShortcuts(context: Context) {
homeRoomListStore
.observe()
.observeOn(Schedulers.computation())
.subscribe { rooms ->
val shortcuts = rooms
.favoriteRooms()
.map { room ->
val intent = RoomDetailActivity.shortcutIntent(context, room.roomId)
val drawable = avatarRenderer.shortcutDrawable(context, GlideApp.with(context), room.toMatrixItem())
ShortcutInfoCompat.Builder(context, room.roomId)
.setShortLabel(room.displayName)
.setIcon(drawable.toProfileImageIcon())
.setIntent(intent)
.build()
}
ShortcutManagerCompat.removeAllDynamicShortcuts(context)
ShortcutManagerCompat.addDynamicShortcuts(context, shortcuts)
}
}
// PRIVATE API *********************************************************************************
private fun List<RoomSummary>.favoriteRooms(): List<RoomSummary> {
return filter { room -> room.tags.any { it.name == RoomTag.ROOM_TAG_FAVOURITE } }
.take(n = 4) // Android only allows us to create 4 shortcuts
}
private fun Drawable.toProfileImageIcon(): IconCompat {
val adaptiveIconSize = dimensionConverter.dpToPx(adaptiveIconSizeDp)
val adaptiveIconOuterSides = dimensionConverter.dpToPx(adaptiveIconOuterSidesDp)
val bitmap = Bitmap.createBitmap(adaptiveIconSize, adaptiveIconSize, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
return if (useAdaptiveIcon) {
setBounds(adaptiveIconOuterSides, adaptiveIconOuterSides, adaptiveIconSize - adaptiveIconOuterSides, adaptiveIconSize - adaptiveIconOuterSides)
draw(canvas)
IconCompat.createWithAdaptiveBitmap(bitmap)
} else {
setBounds(0, 0, bitmap.width, bitmap.height)
draw(canvas)
IconCompat.createWithBitmap(bitmap)
}
}
}

View File

@ -44,8 +44,14 @@ class RoomDetailActivity : VectorBaseActivity(), ToolbarConfigurable {
super.onCreate(savedInstanceState)
waitingView = waiting_view
if (isFirstCreation()) {
val roomDetailArgs: RoomDetailArgs = intent?.extras?.getParcelable(EXTRA_ROOM_DETAIL_ARGS)
?: return
val roomDetailArgs: RoomDetailArgs? = if (intent?.action == ACTION_ROOM_DETAILS_FROM_SHORTCUT) {
RoomDetailArgs(roomId = intent?.extras?.getString(EXTRA_ROOM_ID)!!)
} else {
intent?.extras?.getParcelable(EXTRA_ROOM_DETAIL_ARGS)
}
if (roomDetailArgs == null) return
currentRoomId = roomDetailArgs.roomId
replaceFragment(R.id.roomDetailContainer, RoomDetailFragment::class.java, roomDetailArgs)
replaceFragment(R.id.roomDetailDrawerContainer, BreadcrumbsFragment::class.java)
@ -110,11 +116,20 @@ class RoomDetailActivity : VectorBaseActivity(), ToolbarConfigurable {
companion object {
const val EXTRA_ROOM_DETAIL_ARGS = "EXTRA_ROOM_DETAIL_ARGS"
const val EXTRA_ROOM_ID = "EXTRA_ROOM_ID"
const val ACTION_ROOM_DETAILS_FROM_SHORTCUT = "ROOM_DETAILS_FROM_SHORTCUT"
fun newIntent(context: Context, roomDetailArgs: RoomDetailArgs): Intent {
return Intent(context, RoomDetailActivity::class.java).apply {
putExtra(EXTRA_ROOM_DETAIL_ARGS, roomDetailArgs)
}
}
fun shortcutIntent(context: Context, roomId: String): Intent {
return Intent(context, RoomDetailActivity::class.java).apply {
action = ACTION_ROOM_DETAILS_FROM_SHORTCUT
putExtra(EXTRA_ROOM_ID, roomId)
}
}
}
}