From 69d0ed3fb80dd3ae811792f293fd3c2e90c00d26 Mon Sep 17 00:00:00 2001 From: David Teresi Date: Mon, 5 Jul 2021 14:12:49 -0400 Subject: [PATCH 1/7] Support Android 11 Conversation features Instead of only favorite rooms having shortcuts, all rooms now have shortcuts and they are ranked according to favorite/normal/low-priority status. --- .../vector/app/features/home/ShortcutCreator.kt | 6 +++++- .../vector/app/features/home/ShortcutsHandler.kt | 15 ++++++++++----- .../features/notifications/NotificationUtils.kt | 3 +++ 3 files changed, 18 insertions(+), 6 deletions(-) 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 db396cf9902..879efcaf196 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,6 +17,7 @@ package im.vector.app.features.home import android.content.Context +import android.content.pm.ShortcutInfo import android.graphics.Bitmap import android.os.Build import androidx.annotation.WorkerThread @@ -67,9 +68,12 @@ class ShortcutCreator @Inject constructor( .setShortLabel(roomSummary.displayName) .setIcon(bitmap?.toProfileImageIcon()) .setIntent(intent) + .setLongLived(true) // Make it show up in the direct share menu - .setCategories(setOf(directShareCategory)) + .setCategories(setOf( + directShareCategory, + ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION)) .build() } 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 4a2d001e1d2..62595389ebc 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,6 @@ 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.model.Membership import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.rx.asObservable @@ -46,17 +45,23 @@ class ShortcutsHandler @Inject constructor( ?.getPagedRoomSummariesLive( roomSummaryQueryParams { memberships = listOf(Membership.JOIN) - roomTagQueryFilter = RoomTagQueryFilter(isFavorite = true, null, null) } ) ?.asObservable() ?.subscribe { rooms -> val shortcuts = rooms - .take(n = 4) // Android only allows us to create 4 shortcuts + .sortedBy { room -> + // pushDynamicShortcut adds each shortcut to the top of the shortcut ranking, + // so higher priority rooms should be at the end of this list to get pushed on last. + if (room.isFavorite) 2 + else if (room.isLowPriority) 0 + else 1 + } .map { shortcutCreator.create(it) } - ShortcutManagerCompat.removeAllDynamicShortcuts(context) - ShortcutManagerCompat.addDynamicShortcuts(context, shortcuts) + 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 33f419857b9..d5eb80261ed 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. From 996b4e7a4573e36a5a8580e25cc599020eb00907 Mon Sep 17 00:00:00 2001 From: David Teresi Date: Mon, 5 Jul 2021 14:13:32 -0400 Subject: [PATCH 2/7] Remove dead shortcuts --- .../java/im/vector/app/features/home/ShortcutsHandler.kt | 7 +++++++ 1 file changed, 7 insertions(+) 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 62595389ebc..aa10c7d45c9 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 @@ -49,6 +49,13 @@ class ShortcutsHandler @Inject constructor( ) ?.asObservable() ?.subscribe { rooms -> + // 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) + val shortcuts = rooms .sortedBy { room -> // pushDynamicShortcut adds each shortcut to the top of the shortcut ranking, From 5df0bd69c7e7331474c4876fc8d20a963b57f1ca Mon Sep 17 00:00:00 2001 From: David Teresi Date: Sat, 3 Jul 2021 20:43:24 -0400 Subject: [PATCH 3/7] Fix icon crop Rectangular icons were causing issues with the conversation icon display (probably an Android bug) and shortcut icons were being cropped in unnecessarily. --- .../java/im/vector/app/features/home/AvatarRenderer.kt | 1 + .../java/im/vector/app/features/home/ShortcutCreator.kt | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) 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 787027e0e29..d22707bda03 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 879efcaf196..b40666d1cf8 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 @@ -19,6 +19,7 @@ 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 @@ -46,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) } @@ -80,7 +81,11 @@ class ShortcutCreator @Inject constructor( 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) } From 4af58dde7483eef8f212eef47b873201581e8d43 Mon Sep 17 00:00:00 2001 From: David Teresi Date: Mon, 5 Jul 2021 14:21:55 -0400 Subject: [PATCH 4/7] Add changelog.d item --- changelog.d/1809.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1809.feature diff --git a/changelog.d/1809.feature b/changelog.d/1809.feature new file mode 100644 index 00000000000..b037ffa6d31 --- /dev/null +++ b/changelog.d/1809.feature @@ -0,0 +1 @@ +Support Android 11 Conversation features \ No newline at end of file From 842ccb12b251c2c3717b8c00a4f956b754fe5eb9 Mon Sep 17 00:00:00 2001 From: David Teresi Date: Mon, 12 Jul 2021 21:21:31 -0400 Subject: [PATCH 5/7] Improve shortcut sorting --- .../android/sdk/api/session/room/RoomSortOrder.kt | 1 + .../sdk/internal/query/QueryRoomOrderProcessor.kt | 14 +++++++++++--- .../vector/app/features/home/ShortcutsHandler.kt | 12 ++++-------- 3 files changed, 16 insertions(+), 11 deletions(-) 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 36da2425273..e721abd6a05 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 7a06c2129c0..7294ce4abf0 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/ShortcutsHandler.kt b/vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt index aa10c7d45c9..702a15b606f 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,6 +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.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 @@ -45,7 +46,8 @@ class ShortcutsHandler @Inject constructor( ?.getPagedRoomSummariesLive( roomSummaryQueryParams { memberships = listOf(Membership.JOIN) - } + }, + sortOrder = RoomSortOrder.PRIORITY_AND_ACTIVITY ) ?.asObservable() ?.subscribe { rooms -> @@ -57,13 +59,7 @@ class ShortcutsHandler @Inject constructor( ShortcutManagerCompat.removeLongLivedShortcuts(context, deadShortcutIds) val shortcuts = rooms - .sortedBy { room -> - // pushDynamicShortcut adds each shortcut to the top of the shortcut ranking, - // so higher priority rooms should be at the end of this list to get pushed on last. - if (room.isFavorite) 2 - else if (room.isLowPriority) 0 - else 1 - } + .asReversed() .map { shortcutCreator.create(it) } shortcuts.forEach { shortcut -> From 2004d357d549f968fe16aac78ea5e32abdd1fb1b Mon Sep 17 00:00:00 2001 From: David Teresi Date: Wed, 25 Aug 2021 14:58:14 -0400 Subject: [PATCH 6/7] Insert room shortcuts in order This prevents shortcuts from momentarily being shown out of order while the shortcut list is in the process of being updated. --- .../java/im/vector/app/features/home/ShortcutCreator.kt | 3 ++- .../java/im/vector/app/features/home/ShortcutsHandler.kt | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) 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 b40666d1cf8..9b0ba644917 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 @@ -58,7 +58,7 @@ 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) @@ -70,6 +70,7 @@ class ShortcutCreator @Inject constructor( .setIcon(bitmap?.toProfileImageIcon()) .setIntent(intent) .setLongLived(true) + .setRank(rank) // Make it show up in the direct share menu .setCategories(setOf( 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 702a15b606f..c3249f5b267 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 @@ -58,9 +58,9 @@ class ShortcutsHandler @Inject constructor( .filter { !roomIds.contains(it) } ShortcutManagerCompat.removeLongLivedShortcuts(context, deadShortcutIds) - val shortcuts = rooms - .asReversed() - .map { shortcutCreator.create(it) } + val shortcuts = rooms.mapIndexed { index, room -> + shortcutCreator.create(room, index) + } shortcuts.forEach { shortcut -> ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) From 15217d98ac7bf9a333aa7a26e0dd9d95870e33d2 Mon Sep 17 00:00:00 2001 From: David Teresi Date: Fri, 27 Aug 2021 16:19:25 -0400 Subject: [PATCH 7/7] Only set SHORTCUT_CATEGORY_CONVERSATION above API 25 --- .../im/vector/app/features/home/ShortcutCreator.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 9b0ba644917..fc204a0c562 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 @@ -65,17 +65,19 @@ class ShortcutCreator @Inject constructor( } 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) .setLongLived(true) .setRank(rank) - - // Make it show up in the direct share menu - .setCategories(setOf( - directShareCategory, - ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION)) + .setCategories(categories) .build() }