Merge pull request #3128 from vector-im/feature/bma/various_fixes

Various fixes before release 1.1.4
This commit is contained in:
Benoit Marty 2021-04-07 15:32:13 +02:00 committed by GitHub
commit 0693ce13e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 73 additions and 50 deletions

View File

@ -16,6 +16,7 @@ Improvements 🙌:
- Improve timeline filtering (dissociate membership and profile events, display hidden events when highlighted, fix hidden item/read receipts behavior) - Improve timeline filtering (dissociate membership and profile events, display hidden events when highlighted, fix hidden item/read receipts behavior)
- Add better support for empty room name fallback (#3106) - Add better support for empty room name fallback (#3106)
- Room list improvements (paging) - Room list improvements (paging)
- Fix quick click action (#3127)
Bugfix 🐛: Bugfix 🐛:
- Fix bad theme change for the MainActivity - Fix bad theme change for the MainActivity
@ -23,6 +24,7 @@ Bugfix 🐛:
- Disable URL preview for some domains (#2995) - Disable URL preview for some domains (#2995)
- Fix avatar rendering for DMs, after initial sync (#2693) - Fix avatar rendering for DMs, after initial sync (#2693)
- Fix mandatory parameter in API (#3065) - Fix mandatory parameter in API (#3065)
- If signout request fails, do not start LoginActivity, but restart the app (#3099)
Translations 🗣: Translations 🗣:
- -

View File

@ -35,5 +35,5 @@ object MessageType {
const val MSGTYPE_STICKER_LOCAL = "org.matrix.android.sdk.sticker" const val MSGTYPE_STICKER_LOCAL = "org.matrix.android.sdk.sticker"
const val MSGTYPE_CONFETTI = "nic.custom.confetti" const val MSGTYPE_CONFETTI = "nic.custom.confetti"
const val MSGTYPE_SNOW = "nic.custom.snow" const val MSGTYPE_SNOW = "io.element.effect.snowfall"
} }

View File

@ -55,9 +55,13 @@ internal suspend inline fun <DATA> executeRequest(globalErrorReceiver: GlobalErr
else -> throwable else -> throwable
} }
// Log some details about the request which has failed. This is less useful than before... // Log some details about the request which has failed.
// Timber.e("Exception when executing request ${apiCall.request().method} ${apiCall.request().url.toString().substringBefore("?")}") val request = (throwable as? HttpException)?.response()?.raw()?.request
Timber.e("Exception when executing request") if (request == null) {
Timber.e("Exception when executing request")
} else {
Timber.e("Exception when executing request ${request.method} ${request.url.toString().substringBefore("?")}")
}
// Check if this is a certificateException // Check if this is a certificateException
CertUtil.getCertificateException(exception) CertUtil.getCertificateException(exception)

View File

@ -386,14 +386,14 @@ internal class DefaultTimeline(
private fun getState(direction: Timeline.Direction): TimelineState { private fun getState(direction: Timeline.Direction): TimelineState {
return when (direction) { return when (direction) {
Timeline.Direction.FORWARDS -> forwardsState.get() Timeline.Direction.FORWARDS -> forwardsState.get()
Timeline.Direction.BACKWARDS -> backwardsState.get() Timeline.Direction.BACKWARDS -> backwardsState.get()
} }
} }
private fun updateState(direction: Timeline.Direction, update: (TimelineState) -> TimelineState) { private fun updateState(direction: Timeline.Direction, update: (TimelineState) -> TimelineState) {
val stateReference = when (direction) { val stateReference = when (direction) {
Timeline.Direction.FORWARDS -> forwardsState Timeline.Direction.FORWARDS -> forwardsState
Timeline.Direction.BACKWARDS -> backwardsState Timeline.Direction.BACKWARDS -> backwardsState
} }
val currentValue = stateReference.get() val currentValue = stateReference.get()
@ -604,12 +604,14 @@ internal class DefaultTimeline(
return offsetResults.size return offsetResults.size
} }
private fun buildTimelineEvent(eventEntity: TimelineEventEntity) = timelineEventMapper.map( private fun buildTimelineEvent(eventEntity: TimelineEventEntity): TimelineEvent {
timelineEventEntity = eventEntity, return timelineEventMapper.map(
buildReadReceipts = settings.buildReadReceipts timelineEventEntity = eventEntity,
).let { buildReadReceipts = settings.buildReadReceipts
// eventually enhance with ui echo? ).let { timelineEvent ->
(uiEchoManager.decorateEventWithReactionUiEcho(it) ?: it) // eventually enhance with ui echo?
uiEchoManager.decorateEventWithReactionUiEcho(timelineEvent) ?: timelineEvent
}
} }
/** /**
@ -702,10 +704,10 @@ internal class DefaultTimeline(
return object : MatrixCallback<TokenChunkEventPersistor.Result> { return object : MatrixCallback<TokenChunkEventPersistor.Result> {
override fun onSuccess(data: TokenChunkEventPersistor.Result) { override fun onSuccess(data: TokenChunkEventPersistor.Result) {
when (data) { when (data) {
TokenChunkEventPersistor.Result.SUCCESS -> { TokenChunkEventPersistor.Result.SUCCESS -> {
Timber.v("Success fetching $limit items $direction from pagination request") Timber.v("Success fetching $limit items $direction from pagination request")
} }
TokenChunkEventPersistor.Result.REACHED_END -> { TokenChunkEventPersistor.Result.REACHED_END -> {
postSnapshot() postSnapshot()
} }
TokenChunkEventPersistor.Result.SHOULD_FETCH_MORE -> TokenChunkEventPersistor.Result.SHOULD_FETCH_MORE ->

View File

@ -15,6 +15,8 @@
*/ */
package im.vector.app.core.utils package im.vector.app.core.utils
import android.os.SystemClock
/** /**
* Simple ThrottleFirst * Simple ThrottleFirst
* See https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/throttleFirst.png * See https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/throttleFirst.png
@ -23,7 +25,7 @@ class FirstThrottler(private val minimumInterval: Long = 800) {
private var lastDate = 0L private var lastDate = 0L
fun canHandle(): Boolean { fun canHandle(): Boolean {
val now = System.currentTimeMillis() val now = SystemClock.elapsedRealtime()
if (now > lastDate + minimumInterval) { if (now > lastDate + minimumInterval) {
lastDate = now lastDate = now
return true return true

View File

@ -161,25 +161,22 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
lifecycleScope.launch { lifecycleScope.launch {
try { try {
session.signOut(!args.isUserLoggedOut) session.signOut(!args.isUserLoggedOut)
Timber.w("SIGN_OUT: success, start app")
sessionHolder.clearActiveSession()
doLocalCleanup(clearPreferences = true)
startNextActivityAndFinish()
} catch (failure: Throwable) { } catch (failure: Throwable) {
displayError(failure) displayError(failure)
return@launch
} }
Timber.w("SIGN_OUT: success, start app")
sessionHolder.clearActiveSession()
doLocalCleanup(clearPreferences = true)
startNextActivityAndFinish()
} }
} }
args.clearCache -> { args.clearCache -> {
lifecycleScope.launch { lifecycleScope.launch {
try { session.clearCache()
session.clearCache() doLocalCleanup(clearPreferences = false)
doLocalCleanup(clearPreferences = false) session.startSyncing(applicationContext)
session.startSyncing(applicationContext) startNextActivityAndFinish()
startNextActivityAndFinish()
} catch (failure: Throwable) {
displayError(failure)
}
} }
} }
} }
@ -215,15 +212,16 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
.setTitle(R.string.dialog_title_error) .setTitle(R.string.dialog_title_error)
.setMessage(errorFormatter.toHumanReadable(failure)) .setMessage(errorFormatter.toHumanReadable(failure))
.setPositiveButton(R.string.global_retry) { _, _ -> doCleanUp() } .setPositiveButton(R.string.global_retry) { _, _ -> doCleanUp() }
.setNegativeButton(R.string.cancel) { _, _ -> startNextActivityAndFinish() } .setNegativeButton(R.string.cancel) { _, _ -> startNextActivityAndFinish(ignoreClearCredentials = true) }
.setCancelable(false) .setCancelable(false)
.show() .show()
} }
} }
private fun startNextActivityAndFinish() { private fun startNextActivityAndFinish(ignoreClearCredentials: Boolean = false) {
val intent = when { val intent = when {
args.clearCredentials args.clearCredentials
&& !ignoreClearCredentials
&& (!args.isUserLoggedOut || args.isAccountDeactivated) -> && (!args.isUserLoggedOut || args.isAccountDeactivated) ->
// User has explicitly asked to log out or deactivated his account // User has explicitly asked to log out or deactivated his account
LoginActivity.newIntent(this, null) LoginActivity.newIntent(this, null)

View File

@ -1675,10 +1675,12 @@ class RoomDetailFragment @Inject constructor(
shareText(requireContext(), action.messageContent.body) shareText(requireContext(), action.messageContent.body)
} else if (action.messageContent is MessageWithAttachmentContent) { } else if (action.messageContent is MessageWithAttachmentContent) {
lifecycleScope.launch { lifecycleScope.launch {
val data = session.fileService().downloadFile(messageContent = action.messageContent) val result = runCatching { session.fileService().downloadFile(messageContent = action.messageContent) }
if (isAdded) { if (!isAdded) return@launch
shareMedia(requireContext(), data, getMimeTypeFromUri(requireContext(), data.toUri())) result.fold(
} { shareMedia(requireContext(), it, getMimeTypeFromUri(requireContext(), it.toUri())) },
{ showErrorInSnackbar(it) }
)
} }
} }
} }
@ -1701,16 +1703,22 @@ class RoomDetailFragment @Inject constructor(
return return
} }
lifecycleScope.launch { lifecycleScope.launch {
val data = session.fileService().downloadFile(messageContent = action.messageContent) val result = runCatching { session.fileService().downloadFile(messageContent = action.messageContent) }
if (isAdded) { if (!isAdded) return@launch
saveMedia( result.fold(
context = requireContext(), {
file = data, saveMedia(
title = action.messageContent.body, context = requireContext(),
mediaMimeType = action.messageContent.mimeType ?: getMimeTypeFromUri(requireContext(), data.toUri()), file = it,
notificationUtils = notificationUtils title = action.messageContent.body,
) mediaMimeType = action.messageContent.mimeType ?: getMimeTypeFromUri(requireContext(), it.toUri()),
} notificationUtils = notificationUtils
)
},
{
showErrorInSnackbar(it)
}
)
} }
} }

View File

@ -127,25 +127,27 @@ class RoomUploadsViewModel @AssistedInject constructor(
private fun handleShare(action: RoomUploadsAction.Share) { private fun handleShare(action: RoomUploadsAction.Share) {
viewModelScope.launch { viewModelScope.launch {
try { val event = try {
val file = session.fileService().downloadFile( val file = session.fileService().downloadFile(
messageContent = action.uploadEvent.contentWithAttachmentContent) messageContent = action.uploadEvent.contentWithAttachmentContent)
_viewEvents.post(RoomUploadsViewEvents.FileReadyForSharing(file)) RoomUploadsViewEvents.FileReadyForSharing(file)
} catch (failure: Throwable) { } catch (failure: Throwable) {
_viewEvents.post(RoomUploadsViewEvents.Failure(failure)) RoomUploadsViewEvents.Failure(failure)
} }
_viewEvents.post(event)
} }
} }
private fun handleDownload(action: RoomUploadsAction.Download) { private fun handleDownload(action: RoomUploadsAction.Download) {
viewModelScope.launch { viewModelScope.launch {
try { val event = try {
val file = session.fileService().downloadFile( val file = session.fileService().downloadFile(
messageContent = action.uploadEvent.contentWithAttachmentContent) messageContent = action.uploadEvent.contentWithAttachmentContent)
_viewEvents.post(RoomUploadsViewEvents.FileReadyForSaving(file, action.uploadEvent.contentWithAttachmentContent.body)) RoomUploadsViewEvents.FileReadyForSaving(file, action.uploadEvent.contentWithAttachmentContent.body)
} catch (failure: Throwable) { } catch (failure: Throwable) {
_viewEvents.post(RoomUploadsViewEvents.Failure(failure)) RoomUploadsViewEvents.Failure(failure)
} }
_viewEvents.post(event)
} }
} }
} }

View File

@ -20,6 +20,7 @@ import androidx.preference.Preference
import im.vector.app.BuildConfig import im.vector.app.BuildConfig
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.preference.VectorPreference import im.vector.app.core.preference.VectorPreference
import im.vector.app.core.utils.FirstThrottler
import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.copyToClipboard
import im.vector.app.core.utils.displayInWebView import im.vector.app.core.utils.displayInWebView
import im.vector.app.core.utils.openAppSettingsPage import im.vector.app.core.utils.openAppSettingsPage
@ -36,6 +37,8 @@ class VectorSettingsHelpAboutFragment @Inject constructor(
override var titleRes = R.string.preference_root_help_about override var titleRes = R.string.preference_root_help_about
override val preferenceXmlRes = R.xml.vector_settings_help_about override val preferenceXmlRes = R.xml.vector_settings_help_about
private val firstThrottler = FirstThrottler(1000)
override fun bindPref() { override fun bindPref() {
// preference to start the App info screen, to facilitate App permissions access // preference to start the App info screen, to facilitate App permissions access
findPreference<VectorPreference>(APP_INFO_LINK_PREFERENCE_KEY)!! findPreference<VectorPreference>(APP_INFO_LINK_PREFERENCE_KEY)!!
@ -98,7 +101,9 @@ class VectorSettingsHelpAboutFragment @Inject constructor(
// third party notice // third party notice
findPreference<VectorPreference>(VectorPreferences.SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!! findPreference<VectorPreference>(VectorPreferences.SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!!
.onPreferenceClickListener = Preference.OnPreferenceClickListener { .onPreferenceClickListener = Preference.OnPreferenceClickListener {
activity?.displayInWebView(VectorSettingsUrls.THIRD_PARTY_LICENSES) if (firstThrottler.canHandle()) {
activity?.displayInWebView(VectorSettingsUrls.THIRD_PARTY_LICENSES)
}
false false
} }