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 d7e1122246..f27cd30494 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 @@ -23,6 +23,7 @@ import androidx.core.content.getSystemService import androidx.core.content.pm.ShortcutManagerCompat import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.features.pin.PinCodeStore +import im.vector.app.features.pin.PinCodeStoreListener import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposables import org.matrix.android.sdk.api.session.room.RoomSortOrder @@ -38,16 +39,22 @@ class ShortcutsHandler @Inject constructor( private val shortcutCreator: ShortcutCreator, private val activeSessionHolder: ActiveSessionHolder, private val pinCodeStore: PinCodeStore -) { +) : PinCodeStoreListener { private val isRequestPinShortcutSupported = ShortcutManagerCompat.isRequestPinShortcutSupported(context) + // Value will be set correctly if necessary + private var hasPinCode = true + fun observeRoomsAndBuildShortcuts(): Disposable { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) { // No op return Disposables.empty() } + hasPinCode = pinCodeStore.getEncodedPin() != null + val session = activeSessionHolder.getSafeActiveSession() ?: return Disposables.empty() + pinCodeStore.addListener(this) return session.getRoomSummariesLive( roomSummaryQueryParams { memberships = listOf(Membership.JOIN) @@ -55,6 +62,9 @@ class ShortcutsHandler @Inject constructor( sortOrder = RoomSortOrder.PRIORITY_AND_ACTIVITY ) .asObservable() + .doOnDispose { + pinCodeStore.removeListener(this) + } .subscribe { rooms -> // Remove dead shortcuts (i.e. deleted rooms) removeDeadShortcut(rooms.map { it.roomId }) @@ -81,7 +91,7 @@ class ShortcutsHandler @Inject constructor( } private fun createShortcuts(rooms: List) { - if (pinCodeStore.getEncodedPin() != null) { + if (hasPinCode) { // No shortcut in this case (privacy) ShortcutManagerCompat.removeAllDynamicShortcuts(context) } else { @@ -117,4 +127,14 @@ class ShortcutsHandler @Inject constructor( } } } + + override fun onPinSetUpChange(isConfigured: Boolean) { + hasPinCode = isConfigured + if (isConfigured) { + // Remove shortcuts immediately + ShortcutManagerCompat.removeAllDynamicShortcuts(context) + } + // Else shortcut will be created next time any room summary is updated, or + // next time the app is started which is acceptable + } } diff --git a/vector/src/main/java/im/vector/app/features/pin/PinCodeStore.kt b/vector/src/main/java/im/vector/app/features/pin/PinCodeStore.kt index fb7c6897e2..d3632edbca 100644 --- a/vector/src/main/java/im/vector/app/features/pin/PinCodeStore.kt +++ b/vector/src/main/java/im/vector/app/features/pin/PinCodeStore.kt @@ -25,6 +25,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.extensions.orFalse import javax.inject.Inject +import javax.inject.Singleton import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine @@ -56,26 +57,40 @@ interface PinCodeStore { * Will reset the counters */ fun resetCounters() + + fun addListener(listener: PinCodeStoreListener) + fun removeListener(listener: PinCodeStoreListener) } -class SharedPrefPinCodeStore @Inject constructor(private val sharedPreferences: SharedPreferences) : PinCodeStore { +interface PinCodeStoreListener { + fun onPinSetUpChange(isConfigured: Boolean) +} - override suspend fun storeEncodedPin(encodePin: String) = withContext(Dispatchers.IO) { - sharedPreferences.edit { - putString(ENCODED_PIN_CODE_KEY, encodePin) +@Singleton +class SharedPrefPinCodeStore @Inject constructor(private val sharedPreferences: SharedPreferences) : PinCodeStore { + private val listeners = mutableSetOf() + + override suspend fun storeEncodedPin(encodePin: String) { + withContext(Dispatchers.IO) { + sharedPreferences.edit { + putString(ENCODED_PIN_CODE_KEY, encodePin) + } } + listeners.forEach { it.onPinSetUpChange(isConfigured = true) } } - override suspend fun deleteEncodedPin() = withContext(Dispatchers.IO) { - // Also reset the counters - resetCounters() - sharedPreferences.edit { - remove(ENCODED_PIN_CODE_KEY) + override suspend fun deleteEncodedPin() { + withContext(Dispatchers.IO) { + // Also reset the counters + resetCounters() + sharedPreferences.edit { + remove(ENCODED_PIN_CODE_KEY) + } + awaitPinCodeCallback { + PFSecurityManager.getInstance().pinCodeHelper.delete(it) + } } - awaitPinCodeCallback { - PFSecurityManager.getInstance().pinCodeHelper.delete(it) - } - return@withContext + listeners.forEach { it.onPinSetUpChange(isConfigured = false) } } override fun getEncodedPin(): String? { @@ -124,6 +139,14 @@ class SharedPrefPinCodeStore @Inject constructor(private val sharedPreferences: } } + override fun addListener(listener: PinCodeStoreListener) { + listeners.add(listener) + } + + override fun removeListener(listener: PinCodeStoreListener) { + listeners.remove(listener) + } + private suspend inline fun awaitPinCodeCallback(crossinline callback: (PFPinCodeHelperCallback) -> Unit) = suspendCoroutine> { cont -> callback(PFPinCodeHelperCallback { result -> cont.resume(result) }) }