diff --git a/changelog.d/1809.feature b/changelog.d/1809.feature new file mode 100644 index 0000000000..b037ffa6d3 --- /dev/null +++ b/changelog.d/1809.feature @@ -0,0 +1 @@ +Support Android 11 Conversation features \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt index 36da242527..e721abd6a0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomSortOrder.kt @@ -19,5 +19,6 @@ package org.matrix.android.sdk.api.session.room enum class RoomSortOrder { NAME, ACTIVITY, + PRIORITY_AND_ACTIVITY, NONE } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt index 7a06c2129c..7294ce4abf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryRoomOrderProcessor.kt @@ -24,13 +24,21 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields internal fun RealmQuery.process(sortOrder: RoomSortOrder): RealmQuery { when (sortOrder) { - RoomSortOrder.NAME -> { + RoomSortOrder.NAME -> { sort(RoomSummaryEntityFields.DISPLAY_NAME, Sort.ASCENDING) } - RoomSortOrder.ACTIVITY -> { + RoomSortOrder.ACTIVITY -> { sort(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, Sort.DESCENDING) } - RoomSortOrder.NONE -> { + RoomSortOrder.PRIORITY_AND_ACTIVITY -> { + sort( + arrayOf( + RoomSummaryEntityFields.IS_FAVOURITE, + RoomSummaryEntityFields.IS_LOW_PRIORITY, + RoomSummaryEntityFields.LAST_ACTIVITY_TIME), + arrayOf(Sort.DESCENDING, Sort.ASCENDING, Sort.DESCENDING)) + } + RoomSortOrder.NONE -> { } } return this diff --git a/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt b/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt index 787027e0e2..d22707bda0 100644 --- a/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/home/AvatarRenderer.kt @@ -171,6 +171,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active .toBitmap(width = iconSize, height = iconSize)) } } + .apply(RequestOptions.centerCropTransform()) .submit(iconSize, iconSize) .get() } diff --git a/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt b/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt index db396cf990..fc204a0c56 100644 --- a/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt +++ b/vector/src/main/java/im/vector/app/features/home/ShortcutCreator.kt @@ -17,7 +17,9 @@ package im.vector.app.features.home import android.content.Context +import android.content.pm.ShortcutInfo import android.graphics.Bitmap +import android.graphics.Canvas import android.os.Build import androidx.annotation.WorkerThread import androidx.core.content.pm.ShortcutInfoCompat @@ -45,7 +47,7 @@ class ShortcutCreator @Inject constructor( private val adaptiveIconOuterSides = dimensionConverter.dpToPx(adaptiveIconOuterSidesDp) private val iconSize by lazy { if (useAdaptiveIcon) { - adaptiveIconSize - adaptiveIconOuterSides + adaptiveIconSize - (adaptiveIconOuterSides * 2) } else { dimensionConverter.dpToPx(72) } @@ -56,27 +58,37 @@ class ShortcutCreator @Inject constructor( } @WorkerThread - fun create(roomSummary: RoomSummary): ShortcutInfoCompat { + fun create(roomSummary: RoomSummary, rank: Int = 1): ShortcutInfoCompat { val intent = RoomDetailActivity.shortcutIntent(context, roomSummary.roomId) val bitmap = try { avatarRenderer.shortcutDrawable(GlideApp.with(context), roomSummary.toMatrixItem(), iconSize) } catch (failure: Throwable) { null } + val categories = if (Build.VERSION.SDK_INT >= 25) { + setOf(directShareCategory, ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION) + } else { + setOf(directShareCategory) + } + return ShortcutInfoCompat.Builder(context, roomSummary.roomId) .setShortLabel(roomSummary.displayName) .setIcon(bitmap?.toProfileImageIcon()) .setIntent(intent) - - // Make it show up in the direct share menu - .setCategories(setOf(directShareCategory)) + .setLongLived(true) + .setRank(rank) + .setCategories(categories) .build() } private fun Bitmap.toProfileImageIcon(): IconCompat { return if (useAdaptiveIcon) { - IconCompat.createWithAdaptiveBitmap(this) + val insetBmp = Bitmap.createBitmap(adaptiveIconSize, adaptiveIconSize, Bitmap.Config.ARGB_8888) + val canvas = Canvas(insetBmp) + canvas.drawBitmap(this, adaptiveIconOuterSides.toFloat(), adaptiveIconOuterSides.toFloat(), null) + + IconCompat.createWithAdaptiveBitmap(insetBmp) } else { IconCompat.createWithBitmap(this) } diff --git a/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt index 4a2d001e1d..c3249f5b26 100644 --- a/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt +++ b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt @@ -24,7 +24,7 @@ import androidx.core.content.pm.ShortcutManagerCompat import im.vector.app.core.di.ActiveSessionHolder import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposables -import org.matrix.android.sdk.api.query.RoomTagQueryFilter +import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.rx.asObservable @@ -46,17 +46,25 @@ class ShortcutsHandler @Inject constructor( ?.getPagedRoomSummariesLive( roomSummaryQueryParams { memberships = listOf(Membership.JOIN) - roomTagQueryFilter = RoomTagQueryFilter(isFavorite = true, null, null) - } + }, + sortOrder = RoomSortOrder.PRIORITY_AND_ACTIVITY ) ?.asObservable() ?.subscribe { rooms -> - val shortcuts = rooms - .take(n = 4) // Android only allows us to create 4 shortcuts - .map { shortcutCreator.create(it) } + // Remove dead shortcuts (i.e. deleted rooms) + val roomIds = rooms.map { it.roomId } + val deadShortcutIds = ShortcutManagerCompat.getShortcuts(context, ShortcutManagerCompat.FLAG_MATCH_DYNAMIC) + .map { it.id } + .filter { !roomIds.contains(it) } + ShortcutManagerCompat.removeLongLivedShortcuts(context, deadShortcutIds) - ShortcutManagerCompat.removeAllDynamicShortcuts(context) - ShortcutManagerCompat.addDynamicShortcuts(context, shortcuts) + val shortcuts = rooms.mapIndexed { index, room -> + shortcutCreator.create(room, index) + } + + shortcuts.forEach { shortcut -> + ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) + } } ?: Disposables.empty() } diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt index 665cddd031..a74c13a496 100755 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt @@ -550,6 +550,9 @@ class NotificationUtils @Inject constructor(private val context: Context, // that can be displayed in not disturb mode if white listed (the later will need compat28.x) .setCategory(NotificationCompat.CATEGORY_MESSAGE) + // ID of the corresponding shortcut, for conversation features under API 30+ + .setShortcutId(roomInfo.roomId) + // Title for API < 16 devices. .setContentTitle(roomInfo.roomDisplayName) // Content for API < 16 devices.