Merge tag 'v1.4.31' into sc
Change-Id: I91353e1ae897942cd95f745d62c9250596c7112e
This commit is contained in:
commit
382e3726d6
|
@ -1,3 +1,12 @@
|
||||||
|
Changes in Element v1.4.31 (2022-08-01)
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
Bugfixes 🐛
|
||||||
|
----------
|
||||||
|
- Fixes crash when returning to the app after backgrounding ([#6709](https://github.com/vector-im/element-android/issues/6709))
|
||||||
|
- Fix message content sometimes appearing in the log ([#6706](https://github.com/vector-im/element-android/issues/6706))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element v1.4.30 (2022-07-29)
|
Changes in Element v1.4.30 (2022-07-29)
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Main changes in this version: Enables the improved sign in and sign up journeys.
|
||||||
|
Full changelog: https://github.com/vector-im/element-android/releases
|
|
@ -60,7 +60,7 @@ android {
|
||||||
// that the app's state is completely cleared between tests.
|
// that the app's state is completely cleared between tests.
|
||||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||||
|
|
||||||
buildConfigField "String", "SDK_VERSION", "\"1.4.30\""
|
buildConfigField "String", "SDK_VERSION", "\"1.4.31\""
|
||||||
|
|
||||||
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
|
buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\""
|
||||||
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
|
buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\""
|
||||||
|
|
|
@ -36,7 +36,7 @@ ext.versionMinor = 4
|
||||||
// Note: even values are reserved for regular release, odd values for hotfix release.
|
// Note: even values are reserved for regular release, odd values for hotfix release.
|
||||||
// When creating a hotfix, you should decrease the value, since the current value
|
// When creating a hotfix, you should decrease the value, since the current value
|
||||||
// is the value for the next regular release.
|
// is the value for the next regular release.
|
||||||
ext.versionPatch = 30
|
ext.versionPatch = 31
|
||||||
|
|
||||||
ext.scVersion = 55
|
ext.scVersion = 55
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,10 @@
|
||||||
|
|
||||||
package im.vector.app.core.di
|
package im.vector.app.core.di
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import arrow.core.Option
|
import arrow.core.Option
|
||||||
import im.vector.app.ActiveSessionDataSource
|
import im.vector.app.ActiveSessionDataSource
|
||||||
|
import im.vector.app.core.extensions.configureAndStart
|
||||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.core.services.GuardServiceStarter
|
import im.vector.app.core.services.GuardServiceStarter
|
||||||
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
||||||
|
@ -25,6 +27,8 @@ import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
|
||||||
import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
|
import im.vector.app.features.crypto.verification.IncomingVerificationRequestHandler
|
||||||
import im.vector.app.features.notifications.PushRuleTriggerListener
|
import im.vector.app.features.notifications.PushRuleTriggerListener
|
||||||
import im.vector.app.features.session.SessionListener
|
import im.vector.app.features.session.SessionListener
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
@ -41,7 +45,10 @@ class ActiveSessionHolder @Inject constructor(
|
||||||
private val sessionListener: SessionListener,
|
private val sessionListener: SessionListener,
|
||||||
private val imageManager: ImageManager,
|
private val imageManager: ImageManager,
|
||||||
private val unifiedPushHelper: UnifiedPushHelper,
|
private val unifiedPushHelper: UnifiedPushHelper,
|
||||||
private val guardServiceStarter: GuardServiceStarter
|
private val guardServiceStarter: GuardServiceStarter,
|
||||||
|
private val sessionInitializer: SessionInitializer,
|
||||||
|
private val applicationContext: Context,
|
||||||
|
private val authenticationService: AuthenticationService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private var activeSessionReference: AtomicReference<Session?> = AtomicReference()
|
private var activeSessionReference: AtomicReference<Session?> = AtomicReference()
|
||||||
|
@ -80,18 +87,27 @@ class ActiveSessionHolder @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasActiveSession(): Boolean {
|
fun hasActiveSession(): Boolean {
|
||||||
return activeSessionReference.get() != null
|
return activeSessionReference.get() != null || authenticationService.hasAuthenticatedSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSafeActiveSession(): Session? {
|
fun getSafeActiveSession(): Session? {
|
||||||
return activeSessionReference.get()
|
return runBlocking { getOrInitializeSession(startSync = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getActiveSession(): Session {
|
fun getActiveSession(): Session {
|
||||||
return activeSessionReference.get()
|
return getSafeActiveSession()
|
||||||
?: throw IllegalStateException("You should authenticate before using this")
|
?: throw IllegalStateException("You should authenticate before using this")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getOrInitializeSession(startSync: Boolean): Session? {
|
||||||
|
return activeSessionReference.get() ?: sessionInitializer.tryInitialize(readCurrentSession = { activeSessionReference.get() }) { session ->
|
||||||
|
setActiveSession(session)
|
||||||
|
session.configureAndStart(applicationContext, startSyncing = startSync)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isWaitingForSessionInitialization() = activeSessionReference.get() == null && authenticationService.hasAuthenticatedSessions()
|
||||||
|
|
||||||
// TODO Stop sync ?
|
// TODO Stop sync ?
|
||||||
// fun switchToSession(sessionParams: SessionParams) {
|
// fun switchToSession(sessionParams: SessionParams) {
|
||||||
// val newActiveSession = authenticationService.getSession(sessionParams)
|
// val newActiveSession = authenticationService.getSession(sessionParams)
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022 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.app.core.di
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import im.vector.app.core.extensions.configureAndStart
|
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class ActiveSessionSetter @Inject constructor(
|
|
||||||
private val activeSessionHolder: ActiveSessionHolder,
|
|
||||||
private val authenticationService: AuthenticationService,
|
|
||||||
private val applicationContext: Context,
|
|
||||||
) {
|
|
||||||
fun shouldSetActionSession(): Boolean {
|
|
||||||
return authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tryToSetActiveSession(startSync: Boolean) {
|
|
||||||
if (shouldSetActionSession()) {
|
|
||||||
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
|
|
||||||
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
|
|
||||||
lastAuthenticatedSession.configureAndStart(applicationContext, startSyncing = startSync)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.app.core.di
|
||||||
|
|
||||||
|
import kotlinx.coroutines.sync.Semaphore
|
||||||
|
import kotlinx.coroutines.sync.withPermit
|
||||||
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
private val initializerSemaphore = Semaphore(permits = 1)
|
||||||
|
|
||||||
|
class SessionInitializer @Inject constructor(
|
||||||
|
private val authenticationService: AuthenticationService,
|
||||||
|
) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A thread safe way to initialize the last authenticated Session instance.
|
||||||
|
*
|
||||||
|
* @param readCurrentSession expects an in-memory Session to be provided or null if not yet set.
|
||||||
|
* @param initializer callback to allow additional initialization on the Session, such as setting the in-memory Session instance.
|
||||||
|
* @return the initialized Session or null when no authenticated sessions are available.
|
||||||
|
*/
|
||||||
|
suspend fun tryInitialize(readCurrentSession: () -> Session?, initializer: (Session) -> Unit): Session? {
|
||||||
|
return initializerSemaphore.withPermit {
|
||||||
|
val currentInMemorySession = readCurrentSession()
|
||||||
|
when {
|
||||||
|
currentInMemorySession != null -> currentInMemorySession
|
||||||
|
authenticationService.hasAuthenticatedSessions() -> {
|
||||||
|
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
|
||||||
|
lastAuthenticatedSession.also { initializer(lastAuthenticatedSession) }
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.BuildConfig
|
import im.vector.app.BuildConfig
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.di.ActiveSessionSetter
|
|
||||||
import im.vector.app.core.network.WifiDetector
|
import im.vector.app.core.network.WifiDetector
|
||||||
import im.vector.app.core.pushers.model.PushData
|
import im.vector.app.core.pushers.model.PushData
|
||||||
import im.vector.app.core.services.GuardServiceStarter
|
import im.vector.app.core.services.GuardServiceStarter
|
||||||
|
@ -38,6 +37,7 @@ import im.vector.app.features.settings.BackgroundSyncMode
|
||||||
import im.vector.app.features.settings.VectorDataStore
|
import im.vector.app.features.settings.VectorDataStore
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
@ -60,7 +60,6 @@ class VectorMessagingReceiver : MessagingReceiver() {
|
||||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
||||||
@Inject lateinit var notifiableEventResolver: NotifiableEventResolver
|
@Inject lateinit var notifiableEventResolver: NotifiableEventResolver
|
||||||
@Inject lateinit var pushersManager: PushersManager
|
@Inject lateinit var pushersManager: PushersManager
|
||||||
@Inject lateinit var activeSessionSetter: ActiveSessionSetter
|
|
||||||
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||||
@Inject lateinit var vectorPreferences: VectorPreferences
|
@Inject lateinit var vectorPreferences: VectorPreferences
|
||||||
@Inject lateinit var vectorDataStore: VectorDataStore
|
@Inject lateinit var vectorDataStore: VectorDataStore
|
||||||
|
@ -116,7 +115,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
|
||||||
// we are in foreground, let the sync do the things?
|
// we are in foreground, let the sync do the things?
|
||||||
Timber.tag(loggerTag.value).d("PUSH received in a foreground state, ignore")
|
Timber.tag(loggerTag.value).d("PUSH received in a foreground state, ignore")
|
||||||
} else {
|
} else {
|
||||||
onMessageReceivedInternal(pushData)
|
coroutineScope.launch(Dispatchers.IO) { onMessageReceivedInternal(pushData) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +169,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
|
||||||
*
|
*
|
||||||
* @param pushData Object containing message data.
|
* @param pushData Object containing message data.
|
||||||
*/
|
*/
|
||||||
private fun onMessageReceivedInternal(pushData: PushData) {
|
private suspend fun onMessageReceivedInternal(pushData: PushData) {
|
||||||
try {
|
try {
|
||||||
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
|
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
|
||||||
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal() : $pushData")
|
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal() : $pushData")
|
||||||
|
@ -178,12 +177,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
|
||||||
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal()")
|
Timber.tag(loggerTag.value).d("## onMessageReceivedInternal()")
|
||||||
}
|
}
|
||||||
|
|
||||||
val session = activeSessionHolder.getSafeActiveSession()
|
val session = activeSessionHolder.getOrInitializeSession(startSync = false)
|
||||||
?: run {
|
|
||||||
// Active session may not exist yet, if MainActivity has not been launched
|
|
||||||
activeSessionSetter.tryToSetActiveSession(startSync = false)
|
|
||||||
activeSessionHolder.getSafeActiveSession()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
Timber.tag(loggerTag.value).w("## Can't sync from push, no current session")
|
Timber.tag(loggerTag.value).w("## Can't sync from push, no current session")
|
||||||
|
@ -204,7 +198,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getEventFastLane(session: Session, pushData: PushData) {
|
private suspend fun getEventFastLane(session: Session, pushData: PushData) {
|
||||||
pushData.roomId ?: return
|
pushData.roomId ?: return
|
||||||
pushData.eventId ?: return
|
pushData.eventId ?: return
|
||||||
|
|
||||||
|
@ -218,18 +212,16 @@ class VectorMessagingReceiver : MessagingReceiver() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
coroutineScope.launch {
|
Timber.tag(loggerTag.value).d("Fast lane: start request")
|
||||||
Timber.tag(loggerTag.value).d("Fast lane: start request")
|
val event = tryOrNull { session.eventService().getEvent(pushData.roomId, pushData.eventId) } ?: return
|
||||||
val event = tryOrNull { session.eventService().getEvent(pushData.roomId, pushData.eventId) } ?: return@launch
|
|
||||||
|
|
||||||
val resolvedEvent = notifiableEventResolver.resolveInMemoryEvent(session, event, canBeReplaced = true)
|
val resolvedEvent = notifiableEventResolver.resolveInMemoryEvent(session, event, canBeReplaced = true)
|
||||||
|
|
||||||
resolvedEvent
|
resolvedEvent
|
||||||
?.also { Timber.tag(loggerTag.value).d("Fast lane: notify drawer") }
|
?.also { Timber.tag(loggerTag.value).d("Fast lane: notify drawer") }
|
||||||
?.let {
|
?.let {
|
||||||
notificationDrawerManager.updateEvents { it.onNotifiableEventReceived(resolvedEvent) }
|
notificationDrawerManager.updateEvents { it.onNotifiableEventReceived(resolvedEvent) }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the event was not yet received
|
// check if the event was not yet received
|
||||||
|
|
|
@ -20,9 +20,10 @@ import com.airbnb.mvrx.MavericksViewModelFactory
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.core.di.ActiveSessionSetter
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
|
import im.vector.app.core.dispatchers.CoroutineDispatchers
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
@ -31,7 +32,8 @@ import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
class StartAppViewModel @AssistedInject constructor(
|
class StartAppViewModel @AssistedInject constructor(
|
||||||
@Assisted val initialState: StartAppViewState,
|
@Assisted val initialState: StartAppViewState,
|
||||||
private val activeSessionSetter: ActiveSessionSetter,
|
private val sessionHolder: ActiveSessionHolder,
|
||||||
|
private val dispatchers: CoroutineDispatchers,
|
||||||
) : VectorViewModel<StartAppViewState, StartAppAction, StartAppViewEvent>(initialState) {
|
) : VectorViewModel<StartAppViewState, StartAppAction, StartAppViewEvent>(initialState) {
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
|
@ -42,7 +44,7 @@ class StartAppViewModel @AssistedInject constructor(
|
||||||
companion object : MavericksViewModelFactory<StartAppViewModel, StartAppViewState> by hiltMavericksViewModelFactory()
|
companion object : MavericksViewModelFactory<StartAppViewModel, StartAppViewState> by hiltMavericksViewModelFactory()
|
||||||
|
|
||||||
fun shouldStartApp(): Boolean {
|
fun shouldStartApp(): Boolean {
|
||||||
return activeSessionSetter.shouldSetActionSession()
|
return sessionHolder.isWaitingForSessionInitialization()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handle(action: StartAppAction) {
|
override fun handle(action: StartAppAction) {
|
||||||
|
@ -53,13 +55,17 @@ class StartAppViewModel @AssistedInject constructor(
|
||||||
|
|
||||||
private fun handleStartApp() {
|
private fun handleStartApp() {
|
||||||
handleLongProcessing()
|
handleLongProcessing()
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(dispatchers.io) {
|
||||||
// This can take time because of DB migration(s), so do it in a background task.
|
// This can take time because of DB migration(s), so do it in a background task.
|
||||||
activeSessionSetter.tryToSetActiveSession(startSync = true)
|
eagerlyInitializeSession()
|
||||||
_viewEvents.post(StartAppViewEvent.AppStarted)
|
_viewEvents.post(StartAppViewEvent.AppStarted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun eagerlyInitializeSession() {
|
||||||
|
sessionHolder.getOrInitializeSession(startSync = true)
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleLongProcessing() {
|
private fun handleLongProcessing() {
|
||||||
viewModelScope.launch(Dispatchers.Default) {
|
viewModelScope.launch(Dispatchers.Default) {
|
||||||
delay(1.seconds.inWholeMilliseconds)
|
delay(1.seconds.inWholeMilliseconds)
|
||||||
|
|
Loading…
Reference in New Issue