Skip to content

Commit 2ce4d8d

Browse files
authored
Merge pull request #4354 from vector-im/feature/bma/shortcut_fixes
Shortcut fixes
2 parents 54daee2 + 34e8cf8 commit 2ce4d8d

File tree

8 files changed

+140
-60
lines changed

8 files changed

+140
-60
lines changed

changelog.d/4170.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Do not show shortcuts if a PIN code is set

matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,15 @@ interface RoomService {
9494
* Get a snapshot list of room summaries.
9595
* @return the immutable list of [RoomSummary]
9696
*/
97-
fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary>
97+
fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
98+
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary>
9899

99100
/**
100101
* Get a live list of room summaries. This list is refreshed as soon as the data changes.
101102
* @return the [LiveData] of List[RoomSummary]
102103
*/
103-
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>>
104+
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
105+
sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): LiveData<List<RoomSummary>>
104106

105107
/**
106108
* Get a snapshot list of Breadcrumbs

matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.session.space
1919
import android.net.Uri
2020
import androidx.lifecycle.LiveData
2121
import org.matrix.android.sdk.api.session.events.model.Event
22+
import org.matrix.android.sdk.api.session.room.RoomSortOrder
2223
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
2324
import org.matrix.android.sdk.api.session.room.model.RoomSummary
2425
import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult
@@ -74,9 +75,11 @@ interface SpaceService {
7475
* Get a live list of space summaries. This list is refreshed as soon as the data changes.
7576
* @return the [LiveData] of List[SpaceSummary]
7677
*/
77-
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>>
78+
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
79+
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>>
7880

79-
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary>
81+
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
82+
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary>
8083

8184
suspend fun joinSpace(spaceIdOrAlias: String,
8285
reason: String? = null,

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt

+6-4
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,14 @@ internal class DefaultRoomService @Inject constructor(
8585
return roomSummaryDataSource.getRoomSummary(roomIdOrAlias)
8686
}
8787

88-
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
89-
return roomSummaryDataSource.getRoomSummaries(queryParams)
88+
override fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
89+
sortOrder: RoomSortOrder): List<RoomSummary> {
90+
return roomSummaryDataSource.getRoomSummaries(queryParams, sortOrder)
9091
}
9192

92-
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
93-
return roomSummaryDataSource.getRoomSummariesLive(queryParams)
93+
override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
94+
sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> {
95+
return roomSummaryDataSource.getRoomSummariesLive(queryParams, sortOrder)
9496
}
9597

9698
override fun getPagedRoomSummariesLive(queryParams: RoomSummaryQueryParams,

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryDataSource.kt

+12-10
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import androidx.paging.PagedList
2525
import com.zhuinden.monarchy.Monarchy
2626
import io.realm.Realm
2727
import io.realm.RealmQuery
28-
import io.realm.Sort
2928
import io.realm.kotlin.where
3029
import org.matrix.android.sdk.api.query.ActiveSpaceFilter
3130
import org.matrix.android.sdk.api.query.RoomCategoryFilter
@@ -80,25 +79,27 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
8079
}
8180
}
8281

83-
fun getRoomSummaries(queryParams: RoomSummaryQueryParams): List<RoomSummary> {
82+
fun getRoomSummaries(queryParams: RoomSummaryQueryParams,
83+
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary> {
8484
return monarchy.fetchAllMappedSync(
85-
{ roomSummariesQuery(it, queryParams) },
85+
{ roomSummariesQuery(it, queryParams).process(sortOrder) },
8686
{ roomSummaryMapper.map(it) }
8787
)
8888
}
8989

90-
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>> {
90+
fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams,
91+
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>> {
9192
return monarchy.findAllMappedWithChanges(
9293
{
93-
roomSummariesQuery(it, queryParams)
94-
.sort(RoomSummaryEntityFields.LAST_ACTIVITY_TIME, Sort.DESCENDING)
94+
roomSummariesQuery(it, queryParams).process(sortOrder)
9595
},
9696
{ roomSummaryMapper.map(it) }
9797
)
9898
}
9999

100-
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> {
101-
return getRoomSummariesLive(queryParams)
100+
fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
101+
sortOrder: RoomSortOrder = RoomSortOrder.NONE): LiveData<List<RoomSummary>> {
102+
return getRoomSummariesLive(queryParams, sortOrder)
102103
}
103104

104105
fun getSpaceSummary(roomIdOrAlias: String): RoomSummary? {
@@ -122,8 +123,9 @@ internal class RoomSummaryDataSource @Inject constructor(@SessionDatabase privat
122123
}
123124
}
124125

125-
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> {
126-
return getRoomSummaries(spaceSummaryQueryParams)
126+
fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
127+
sortOrder: RoomSortOrder = RoomSortOrder.NONE): List<RoomSummary> {
128+
return getRoomSummaries(spaceSummaryQueryParams, sortOrder)
127129
}
128130

129131
fun getRootSpaceSummaries(): List<RoomSummary> {

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt

+7-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
2323
import org.matrix.android.sdk.api.session.events.model.EventType
2424
import org.matrix.android.sdk.api.session.events.model.toContent
2525
import org.matrix.android.sdk.api.session.events.model.toModel
26+
import org.matrix.android.sdk.api.session.room.RoomSortOrder
2627
import org.matrix.android.sdk.api.session.room.model.GuestAccess
2728
import org.matrix.android.sdk.api.session.room.model.Membership
2829
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
@@ -94,12 +95,14 @@ internal class DefaultSpaceService @Inject constructor(
9495
return spaceGetter.get(spaceId)
9596
}
9697

97-
override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams): LiveData<List<RoomSummary>> {
98-
return roomSummaryDataSource.getSpaceSummariesLive(queryParams)
98+
override fun getSpaceSummariesLive(queryParams: SpaceSummaryQueryParams,
99+
sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> {
100+
return roomSummaryDataSource.getSpaceSummariesLive(queryParams, sortOrder)
99101
}
100102

101-
override fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams): List<RoomSummary> {
102-
return roomSummaryDataSource.getSpaceSummaries(spaceSummaryQueryParams)
103+
override fun getSpaceSummaries(spaceSummaryQueryParams: SpaceSummaryQueryParams,
104+
sortOrder: RoomSortOrder): List<RoomSummary> {
105+
return roomSummaryDataSource.getSpaceSummaries(spaceSummaryQueryParams, sortOrder)
103106
}
104107

105108
override fun getRootSpaceSummaries(): List<RoomSummary> {

vector/src/main/java/im/vector/app/features/home/ShortcutsHandler.kt

+70-26
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,85 @@ import android.os.Build
2222
import androidx.core.content.getSystemService
2323
import androidx.core.content.pm.ShortcutManagerCompat
2424
import im.vector.app.core.di.ActiveSessionHolder
25+
import im.vector.app.features.pin.PinCodeStore
26+
import im.vector.app.features.pin.PinCodeStoreListener
2527
import io.reactivex.disposables.Disposable
2628
import io.reactivex.disposables.Disposables
2729
import org.matrix.android.sdk.api.session.room.RoomSortOrder
2830
import org.matrix.android.sdk.api.session.room.model.Membership
31+
import org.matrix.android.sdk.api.session.room.model.RoomSummary
2932
import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
3033
import org.matrix.android.sdk.rx.asObservable
34+
import timber.log.Timber
3135
import javax.inject.Inject
3236

3337
class ShortcutsHandler @Inject constructor(
3438
private val context: Context,
3539
private val shortcutCreator: ShortcutCreator,
36-
private val activeSessionHolder: ActiveSessionHolder
37-
) {
40+
private val activeSessionHolder: ActiveSessionHolder,
41+
private val pinCodeStore: PinCodeStore
42+
) : PinCodeStoreListener {
43+
private val isRequestPinShortcutSupported = ShortcutManagerCompat.isRequestPinShortcutSupported(context)
44+
45+
// Value will be set correctly if necessary
46+
private var hasPinCode = true
3847

3948
fun observeRoomsAndBuildShortcuts(): Disposable {
4049
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) {
4150
// No op
4251
return Disposables.empty()
4352
}
4453

45-
return activeSessionHolder.getSafeActiveSession()
46-
?.getPagedRoomSummariesLive(
47-
roomSummaryQueryParams {
48-
memberships = listOf(Membership.JOIN)
49-
},
50-
sortOrder = RoomSortOrder.PRIORITY_AND_ACTIVITY
51-
)
52-
?.asObservable()
53-
?.subscribe { rooms ->
54+
hasPinCode = pinCodeStore.getEncodedPin() != null
55+
56+
val session = activeSessionHolder.getSafeActiveSession() ?: return Disposables.empty()
57+
return session.getRoomSummariesLive(
58+
roomSummaryQueryParams {
59+
memberships = listOf(Membership.JOIN)
60+
},
61+
sortOrder = RoomSortOrder.PRIORITY_AND_ACTIVITY
62+
)
63+
.asObservable()
64+
.doOnSubscribe { pinCodeStore.addListener(this) }
65+
.doFinally { pinCodeStore.removeListener(this) }
66+
.subscribe { rooms ->
5467
// Remove dead shortcuts (i.e. deleted rooms)
55-
val roomIds = rooms.map { it.roomId }
56-
val deadShortcutIds = ShortcutManagerCompat.getShortcuts(context, ShortcutManagerCompat.FLAG_MATCH_DYNAMIC)
57-
.map { it.id }
58-
.filter { !roomIds.contains(it) }
59-
ShortcutManagerCompat.removeLongLivedShortcuts(context, deadShortcutIds)
60-
61-
val shortcuts = rooms.mapIndexed { index, room ->
62-
shortcutCreator.create(room, index)
63-
}
64-
65-
shortcuts.forEach { shortcut ->
66-
ShortcutManagerCompat.pushDynamicShortcut(context, shortcut)
67-
}
68+
removeDeadShortcut(rooms.map { it.roomId })
69+
70+
// Create shortcuts
71+
createShortcuts(rooms)
6872
}
69-
?: Disposables.empty()
73+
}
74+
75+
private fun removeDeadShortcut(roomIds: List<String>) {
76+
val deadShortcutIds = ShortcutManagerCompat.getShortcuts(context, ShortcutManagerCompat.FLAG_MATCH_DYNAMIC)
77+
.map { it.id }
78+
.filter { !roomIds.contains(it) }
79+
80+
if (deadShortcutIds.isNotEmpty()) {
81+
Timber.d("Removing shortcut(s) $deadShortcutIds")
82+
ShortcutManagerCompat.removeLongLivedShortcuts(context, deadShortcutIds)
83+
if (isRequestPinShortcutSupported) {
84+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
85+
context.getSystemService<ShortcutManager>()?.disableShortcuts(deadShortcutIds)
86+
}
87+
}
88+
}
89+
}
90+
91+
private fun createShortcuts(rooms: List<RoomSummary>) {
92+
if (hasPinCode) {
93+
// No shortcut in this case (privacy)
94+
ShortcutManagerCompat.removeAllDynamicShortcuts(context)
95+
} else {
96+
val shortcuts = rooms.mapIndexed { index, room ->
97+
shortcutCreator.create(room, index)
98+
}
99+
100+
shortcuts.forEach { shortcut ->
101+
ShortcutManagerCompat.pushDynamicShortcut(context, shortcut)
102+
}
103+
}
70104
}
71105

72106
fun clearShortcuts() {
@@ -82,7 +116,7 @@ class ShortcutsHandler @Inject constructor(
82116
ShortcutManagerCompat.removeLongLivedShortcuts(context, shortcuts)
83117

84118
// We can only disabled pinned shortcuts with the API, but at least it will prevent the crash
85-
if (ShortcutManagerCompat.isRequestPinShortcutSupported(context)) {
119+
if (isRequestPinShortcutSupported) {
86120
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
87121
context.getSystemService<ShortcutManager>()
88122
?.let {
@@ -91,4 +125,14 @@ class ShortcutsHandler @Inject constructor(
91125
}
92126
}
93127
}
128+
129+
override fun onPinSetUpChange(isConfigured: Boolean) {
130+
hasPinCode = isConfigured
131+
if (isConfigured) {
132+
// Remove shortcuts immediately
133+
ShortcutManagerCompat.removeAllDynamicShortcuts(context)
134+
}
135+
// Else shortcut will be created next time any room summary is updated, or
136+
// next time the app is started which is acceptable
137+
}
94138
}

vector/src/main/java/im/vector/app/features/pin/PinCodeStore.kt

+35-12
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import kotlinx.coroutines.Dispatchers
2525
import kotlinx.coroutines.withContext
2626
import org.matrix.android.sdk.api.extensions.orFalse
2727
import javax.inject.Inject
28+
import javax.inject.Singleton
2829
import kotlin.coroutines.resume
2930
import kotlin.coroutines.suspendCoroutine
3031

@@ -56,26 +57,40 @@ interface PinCodeStore {
5657
* Will reset the counters
5758
*/
5859
fun resetCounters()
60+
61+
fun addListener(listener: PinCodeStoreListener)
62+
fun removeListener(listener: PinCodeStoreListener)
63+
}
64+
65+
interface PinCodeStoreListener {
66+
fun onPinSetUpChange(isConfigured: Boolean)
5967
}
6068

69+
@Singleton
6170
class SharedPrefPinCodeStore @Inject constructor(private val sharedPreferences: SharedPreferences) : PinCodeStore {
71+
private val listeners = mutableSetOf<PinCodeStoreListener>()
6272

63-
override suspend fun storeEncodedPin(encodePin: String) = withContext(Dispatchers.IO) {
64-
sharedPreferences.edit {
65-
putString(ENCODED_PIN_CODE_KEY, encodePin)
73+
override suspend fun storeEncodedPin(encodePin: String) {
74+
withContext(Dispatchers.IO) {
75+
sharedPreferences.edit {
76+
putString(ENCODED_PIN_CODE_KEY, encodePin)
77+
}
6678
}
79+
listeners.forEach { it.onPinSetUpChange(isConfigured = true) }
6780
}
6881

69-
override suspend fun deleteEncodedPin() = withContext(Dispatchers.IO) {
70-
// Also reset the counters
71-
resetCounters()
72-
sharedPreferences.edit {
73-
remove(ENCODED_PIN_CODE_KEY)
82+
override suspend fun deleteEncodedPin() {
83+
withContext(Dispatchers.IO) {
84+
// Also reset the counters
85+
resetCounters()
86+
sharedPreferences.edit {
87+
remove(ENCODED_PIN_CODE_KEY)
88+
}
89+
awaitPinCodeCallback<Boolean> {
90+
PFSecurityManager.getInstance().pinCodeHelper.delete(it)
91+
}
7492
}
75-
awaitPinCodeCallback<Boolean> {
76-
PFSecurityManager.getInstance().pinCodeHelper.delete(it)
77-
}
78-
return@withContext
93+
listeners.forEach { it.onPinSetUpChange(isConfigured = false) }
7994
}
8095

8196
override fun getEncodedPin(): String? {
@@ -124,6 +139,14 @@ class SharedPrefPinCodeStore @Inject constructor(private val sharedPreferences:
124139
}
125140
}
126141

142+
override fun addListener(listener: PinCodeStoreListener) {
143+
listeners.add(listener)
144+
}
145+
146+
override fun removeListener(listener: PinCodeStoreListener) {
147+
listeners.remove(listener)
148+
}
149+
127150
private suspend inline fun <T> awaitPinCodeCallback(crossinline callback: (PFPinCodeHelperCallback<T>) -> Unit) = suspendCoroutine<PFResult<T>> { cont ->
128151
callback(PFPinCodeHelperCallback<T> { result -> cont.resume(result) })
129152
}

0 commit comments

Comments
 (0)