diff --git a/CHANGES.md b/CHANGES.md
index 9dd6b3a894..90c2e05c65 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -11,15 +11,17 @@ Bugfix 🐛:
- Fix clear cache issue: sometimes, after a clear cache, there is still a token, so the init sync service is not started.
- Sidebar too large in horizontal orientation or tablets (#475)
- UrlPreview should be updated when the url is edited and changed (#2678)
+ - When receiving a new pepper from identity server, use it on the next hash lookup (#2708)
+ - Crashes reported by PlayStore (new in 1.0.14) (#2707)
Translations 🗣:
-
SDK API changes ⚠️:
- -
+ - Increase targetSdkVersion to 30 (#2600)
Build 🧱:
- -
+ - Compile with Android SDK 30 (Android 11)
Test:
-
diff --git a/attachment-viewer/build.gradle b/attachment-viewer/build.gradle
index d8cd7d0c98..5ce9f1eff6 100644
--- a/attachment-viewer/build.gradle
+++ b/attachment-viewer/build.gradle
@@ -32,11 +32,11 @@ buildscript {
}
android {
- compileSdkVersion 29
+ compileSdkVersion 30
defaultConfig {
minSdkVersion 21
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
}
diff --git a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
index 9b1345cd39..418b5b5cbb 100644
--- a/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
+++ b/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt
@@ -18,15 +18,19 @@
package im.vector.lib.attachmentviewer
import android.graphics.Color
+import android.os.Build
import android.os.Bundle
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import android.view.ViewGroup
+import android.view.WindowInsets
+import android.view.WindowInsetsController
import android.view.WindowManager
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
import androidx.core.view.GestureDetectorCompat
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
@@ -94,14 +98,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- // This is important for the dispatchTouchEvent, if not we must correct
- // the touch coordinates
- window.decorView.systemUiVisibility = (
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- or View.SYSTEM_UI_FLAG_IMMERSIVE)
- window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
- window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
+ setDecorViewFullScreen()
views = ActivityAttachmentViewerBinding.inflate(layoutInflater)
setContentView(views.root)
@@ -134,6 +131,29 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
}
}
+ @Suppress("DEPRECATION")
+ private fun setDecorViewFullScreen() {
+ // This is important for the dispatchTouchEvent, if not we must correct
+ // the touch coordinates
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ // New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ window.setDecorFitsSystemWindows(false)
+ // New API instead of SYSTEM_UI_FLAG_IMMERSIVE
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ // New API instead of FLAG_TRANSLUCENT_STATUS
+ window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
+ // new API instead of FLAG_TRANSLUCENT_NAVIGATION
+ window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
+ } else {
+ window.decorView.systemUiVisibility = (
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ or View.SYSTEM_UI_FLAG_IMMERSIVE)
+ window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
+ window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
+ }
+ }
+
fun onSelectedPositionChanged(position: Int) {
attachmentsAdapter.recyclerView?.findViewHolderForAdapterPosition(currentPosition)?.let {
(it as? BaseViewHolder)?.onSelected(false)
@@ -313,28 +333,48 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
?.handleCommand(commands)
}
+ @Suppress("DEPRECATION")
private fun hideSystemUI() {
systemUiVisibility = false
// Enables regular immersive mode.
// For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
// Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
- // Set the content to appear under the system bars so that the
- // content doesn't resize when the system bars hide and show.
- or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- // Hide the nav bar and status bar
- or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- or View.SYSTEM_UI_FLAG_FULLSCREEN)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ // New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ window.setDecorFitsSystemWindows(false)
+ // new API instead of SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ window.decorView.windowInsetsController?.hide(WindowInsets.Type.navigationBars())
+ // New API instead of SYSTEM_UI_FLAG_IMMERSIVE
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ // New API instead of FLAG_TRANSLUCENT_STATUS
+ window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
+ // New API instead of FLAG_TRANSLUCENT_NAVIGATION
+ window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
+ } else {
+ window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
+ // Set the content to appear under the system bars so that the
+ // content doesn't resize when the system bars hide and show.
+ or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ // Hide the nav bar and status bar
+ or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ or View.SYSTEM_UI_FLAG_FULLSCREEN)
+ }
}
// Shows the system bars by removing all the flags
// except for the ones that make the content appear under the system bars.
+ @Suppress("DEPRECATION")
private fun showSystemUI() {
systemUiVisibility = true
- window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ // New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ window.setDecorFitsSystemWindows(false)
+ } else {
+ window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
+ }
}
}
diff --git a/attachment-viewer/src/main/res/values/colors.xml b/attachment-viewer/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..7ceef40881
--- /dev/null
+++ b/attachment-viewer/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+
+ #80000000
+
+
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 247e2b90ad..517ae0d4ce 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,6 @@
-#Fri Jan 15 11:30:47 CET 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionSha256Sum=a7ca23b3ccf265680f2bfd35f1f00b1424f4466292c7337c85d46c9641b3f053
+distributionSha256Sum=3db89524a3981819ff28c3f979236c1274a726e146ced0c8a2020417f9bc0782
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip
diff --git a/matrix-sdk-android-rx/build.gradle b/matrix-sdk-android-rx/build.gradle
index a99b5856ba..0e899e21ff 100644
--- a/matrix-sdk-android-rx/build.gradle
+++ b/matrix-sdk-android-rx/build.gradle
@@ -3,11 +3,11 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
- compileSdkVersion 29
+ compileSdkVersion 30
defaultConfig {
minSdkVersion 21
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle
index 7d5432ebb8..836b49b3f2 100644
--- a/matrix-sdk-android/build.gradle
+++ b/matrix-sdk-android/build.gradle
@@ -14,12 +14,12 @@ buildscript {
}
android {
- compileSdkVersion 29
+ compileSdkVersion 30
testOptions.unitTests.includeAndroidResources = true
defaultConfig {
minSdkVersion 21
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 1
versionName "0.0.1"
// Multidex is useful for tests
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ThumbnailExtractor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ThumbnailExtractor.kt
index 4b31db59b1..c28668a53e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ThumbnailExtractor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/ThumbnailExtractor.kt
@@ -47,22 +47,24 @@ internal object ThumbnailExtractor {
val mediaMetadataRetriever = MediaMetadataRetriever()
try {
mediaMetadataRetriever.setDataSource(context, attachment.queryUri)
- val thumbnail = mediaMetadataRetriever.frameAtTime
-
- val outputStream = ByteArrayOutputStream()
- thumbnail.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
- val thumbnailWidth = thumbnail.width
- val thumbnailHeight = thumbnail.height
- val thumbnailSize = outputStream.size()
- thumbnailData = ThumbnailData(
- width = thumbnailWidth,
- height = thumbnailHeight,
- size = thumbnailSize.toLong(),
- bytes = outputStream.toByteArray(),
- mimeType = MimeTypes.Jpeg
- )
- thumbnail.recycle()
- outputStream.reset()
+ mediaMetadataRetriever.frameAtTime?.let { thumbnail ->
+ val outputStream = ByteArrayOutputStream()
+ thumbnail.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
+ val thumbnailWidth = thumbnail.width
+ val thumbnailHeight = thumbnail.height
+ val thumbnailSize = outputStream.size()
+ thumbnailData = ThumbnailData(
+ width = thumbnailWidth,
+ height = thumbnailHeight,
+ size = thumbnailSize.toLong(),
+ bytes = outputStream.toByteArray(),
+ mimeType = MimeTypes.Jpeg
+ )
+ thumbnail.recycle()
+ outputStream.reset()
+ } ?: run {
+ Timber.e("Cannot extract video thumbnail at %s", attachment.queryUri.toString())
+ }
} catch (e: Exception) {
Timber.e(e, "Cannot extract video thumbnail")
} finally {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
index a03bef9501..67f3b2aa56 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityBulkLookupTask.kt
@@ -52,65 +52,60 @@ internal class DefaultIdentityBulkLookupTask @Inject constructor(
val pepper = identityData.hashLookupPepper
val hashDetailResponse = if (pepper == null) {
// We need to fetch the hash details first
- fetchAndStoreHashDetails(identityAPI)
+ fetchHashDetails(identityAPI)
+ .also { identityStore.setHashDetails(it) }
} else {
IdentityHashDetailResponse(pepper, identityData.hashLookupAlgorithm)
}
- if (hashDetailResponse.algorithms.contains("sha256").not()) {
+ if (hashDetailResponse.algorithms.contains(IdentityHashDetailResponse.ALGORITHM_SHA256).not()) {
// TODO We should ask the user if he is ok to send their 3Pid in clear, but for the moment we do not do it
// Also, what we have in cache could be outdated, the identity server maybe now supports sha256
throw IdentityServiceError.BulkLookupSha256NotSupported
}
- val hashedAddresses = withOlmUtility { olmUtility ->
- params.threePids.map { threePid ->
- base64ToBase64Url(
- olmUtility.sha256(threePid.value.toLowerCase(Locale.ROOT)
- + " " + threePid.toMedium() + " " + hashDetailResponse.pepper)
- )
- }
- }
-
- val identityLookUpV2Response = lookUpInternal(identityAPI, hashedAddresses, hashDetailResponse, true)
+ val lookUpData = lookUpInternal(identityAPI, params.threePids, hashDetailResponse, true)
// Convert back to List
- return handleSuccess(params.threePids, hashedAddresses, identityLookUpV2Response)
+ return handleSuccess(params.threePids, lookUpData)
}
+ data class LookUpData(
+ val hashedAddresses: List,
+ val identityLookUpResponse: IdentityLookUpResponse
+ )
+
private suspend fun lookUpInternal(identityAPI: IdentityAPI,
- hashedAddresses: List,
+ threePids: List,
hashDetailResponse: IdentityHashDetailResponse,
- canRetry: Boolean): IdentityLookUpResponse {
+ canRetry: Boolean): LookUpData {
+ val hashedAddresses = getHashedAddresses(threePids, hashDetailResponse.pepper)
return try {
- executeRequest(null) {
- apiCall = identityAPI.lookup(IdentityLookUpParams(
- hashedAddresses,
- IdentityHashDetailResponse.ALGORITHM_SHA256,
- hashDetailResponse.pepper
- ))
- }
+ LookUpData(hashedAddresses,
+ executeRequest(null) {
+ apiCall = identityAPI.lookup(IdentityLookUpParams(
+ hashedAddresses,
+ IdentityHashDetailResponse.ALGORITHM_SHA256,
+ hashDetailResponse.pepper
+ ))
+ })
} catch (failure: Throwable) {
// Catch invalid hash pepper and retry
if (canRetry && failure is Failure.ServerError && failure.error.code == MatrixError.M_INVALID_PEPPER) {
// This is not documented, but the error can contain the new pepper!
- if (!failure.error.newLookupPepper.isNullOrEmpty()) {
+ val newHashDetailResponse = if (!failure.error.newLookupPepper.isNullOrEmpty()) {
// Store it and use it right now
hashDetailResponse.copy(pepper = failure.error.newLookupPepper)
- .also { identityStore.setHashDetails(it) }
- .let { lookUpInternal(identityAPI, hashedAddresses, it, false /* Avoid infinite loop */) }
} else {
// Retrieve the new hash details
- val newHashDetailResponse = fetchAndStoreHashDetails(identityAPI)
-
- if (hashDetailResponse.algorithms.contains(IdentityHashDetailResponse.ALGORITHM_SHA256).not()) {
- // TODO We should ask the user if he is ok to send their 3Pid in clear, but for the moment we do not do it
- // Also, what we have in cache is maybe outdated, the identity server maybe now support sha256
- throw IdentityServiceError.BulkLookupSha256NotSupported
- }
-
- lookUpInternal(identityAPI, hashedAddresses, newHashDetailResponse, false /* Avoid infinite loop */)
+ fetchHashDetails(identityAPI)
}
+ .also { identityStore.setHashDetails(it) }
+ if (newHashDetailResponse.algorithms.contains(IdentityHashDetailResponse.ALGORITHM_SHA256).not()) {
+ // TODO We should ask the user if he is ok to send their 3Pid in clear, but for the moment we do not do it
+ throw IdentityServiceError.BulkLookupSha256NotSupported
+ }
+ lookUpInternal(identityAPI, threePids, newHashDetailResponse, false /* Avoid infinite loop */)
} else {
// Other error
throw failure
@@ -118,16 +113,29 @@ internal class DefaultIdentityBulkLookupTask @Inject constructor(
}
}
- private suspend fun fetchAndStoreHashDetails(identityAPI: IdentityAPI): IdentityHashDetailResponse {
- return executeRequest(null) {
- apiCall = identityAPI.hashDetails()
+ private fun getHashedAddresses(threePids: List, pepper: String): List {
+ return withOlmUtility { olmUtility ->
+ threePids.map { threePid ->
+ base64ToBase64Url(
+ olmUtility.sha256(threePid.value.toLowerCase(Locale.ROOT)
+ + " " + threePid.toMedium() + " " + pepper)
+ )
+ }
}
- .also { identityStore.setHashDetails(it) }
}
- private fun handleSuccess(threePids: List, hashedAddresses: List, identityLookUpResponse: IdentityLookUpResponse): List {
- return identityLookUpResponse.mappings.keys.map { hashedAddress ->
- FoundThreePid(threePids[hashedAddresses.indexOf(hashedAddress)], identityLookUpResponse.mappings[hashedAddress] ?: error(""))
+ private suspend fun fetchHashDetails(identityAPI: IdentityAPI): IdentityHashDetailResponse {
+ return executeRequest(null) {
+ apiCall = identityAPI.hashDetails()
+ }
+ }
+
+ private fun handleSuccess(threePids: List, lookupData: LookUpData): List {
+ return lookupData.identityLookUpResponse.mappings.keys.map { hashedAddress ->
+ FoundThreePid(
+ threePids[lookupData.hashedAddresses.indexOf(hashedAddress)],
+ lookupData.identityLookUpResponse.mappings[hashedAddress] ?: error("")
+ )
}
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt
index bce03354d7..654cf0fb74 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/EventContextResponse.kt
@@ -21,16 +21,34 @@ import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.Event
@JsonClass(generateAdapter = true)
-data class EventContextResponse(
+internal data class EventContextResponse(
+ /**
+ * Details of the requested event.
+ */
@Json(name = "event") val event: Event,
+ /**
+ * A token that can be used to paginate backwards with.
+ */
@Json(name = "start") override val start: String? = null,
- @Json(name = "events_before") val eventsBefore: List = emptyList(),
- @Json(name = "events_after") val eventsAfter: List = emptyList(),
+ /**
+ * A list of room events that happened just before the requested event, in reverse-chronological order.
+ */
+ @Json(name = "events_before") val eventsBefore: List? = null,
+ /**
+ * A list of room events that happened just after the requested event, in chronological order.
+ */
+ @Json(name = "events_after") val eventsAfter: List? = null,
+ /**
+ * A token that can be used to paginate forwards with.
+ */
@Json(name = "end") override val end: String? = null,
- @Json(name = "state") override val stateEvents: List = emptyList()
+ /**
+ * The state of the room at the last event returned.
+ */
+ @Json(name = "state") override val stateEvents: List? = null
) : TokenChunkEvent {
override val events: List by lazy {
- eventsAfter.reversed() + listOf(event) + eventsBefore
+ eventsAfter.orEmpty().reversed() + event + eventsBefore.orEmpty()
}
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt
index ed384d3b3c..2f61b1cce8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/PaginationResponse.kt
@@ -22,8 +22,28 @@ import org.matrix.android.sdk.api.session.events.model.Event
@JsonClass(generateAdapter = true)
internal data class PaginationResponse(
+ /**
+ * The token the pagination starts from. If dir=b this will be the token supplied in from.
+ */
@Json(name = "start") override val start: String? = null,
+ /**
+ * The token the pagination ends at. If dir=b this token should be used again to request even earlier events.
+ */
@Json(name = "end") override val end: String? = null,
- @Json(name = "chunk") override val events: List = emptyList(),
- @Json(name = "state") override val stateEvents: List = emptyList()
-) : TokenChunkEvent
+ /**
+ * A list of room events. The order depends on the dir parameter. For dir=b events will be in
+ * reverse-chronological order, for dir=f in chronological order, so that events start at the from point.
+ */
+ @Json(name = "chunk") val chunk: List? = null,
+ /**
+ * A list of state events relevant to showing the chunk. For example, if lazy_load_members is enabled
+ * in the filter then this may contain the membership events for the senders of events in the chunk.
+ *
+ * Unless include_redundant_members is true, the server may remove membership events which would have
+ * already been sent to the client in prior calls to this endpoint, assuming the membership of those members has not changed.
+ */
+ @Json(name = "state") override val stateEvents: List? = null
+) : TokenChunkEvent {
+ override val events: List
+ get() = chunk.orEmpty()
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt
index 08b20f1701..465b0faac8 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEvent.kt
@@ -22,7 +22,7 @@ internal interface TokenChunkEvent {
val start: String?
val end: String?
val events: List
- val stateEvents: List
+ val stateEvents: List?
fun hasMore() = start != end
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt
index 2a532c6bf5..1a497b8835 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt
@@ -156,7 +156,7 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri
}
}
return if (receivedChunk.events.isEmpty()) {
- if (receivedChunk.start != receivedChunk.end) {
+ if (receivedChunk.hasMore()) {
Result.SHOULD_FETCH_MORE
} else {
Result.REACHED_END
@@ -196,7 +196,7 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri
val now = System.currentTimeMillis()
- for (stateEvent in stateEvents) {
+ stateEvents?.forEach { stateEvent ->
val ageLocalTs = stateEvent.unsignedData?.age?.let { now - it }
val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED, ageLocalTs).copyToRealmOrIgnore(realm, EventInsertType.PAGINATION)
currentChunk.addStateEvent(roomId, stateEventEntity, direction)
@@ -205,9 +205,9 @@ internal class TokenChunkEventPersistor @Inject constructor(@SessionDatabase pri
}
}
val eventIds = ArrayList(eventList.size)
- for (event in eventList) {
+ eventList.forEach { event ->
if (event.eventId == null || event.senderId == null) {
- continue
+ return@forEach
}
val ageLocalTs = event.unsignedData?.age?.let { now - it }
eventIds.add(event.eventId)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt
index 0c0e6a8ed0..b3e4a5aa05 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt
@@ -56,8 +56,8 @@ internal class DefaultGetUploadsTask @Inject constructor(
private val roomAPI: RoomAPI,
private val tokenStore: SyncTokenStore,
@SessionDatabase private val monarchy: Monarchy,
- private val globalErrorReceiver: GlobalErrorReceiver)
- : GetUploadsTask {
+ private val globalErrorReceiver: GlobalErrorReceiver
+) : GetUploadsTask {
override suspend fun execute(params: GetUploadsTask.Params): GetUploadsResult {
val result: GetUploadsResult
diff --git a/multipicker/build.gradle b/multipicker/build.gradle
index c58c4586b2..10dc18e488 100644
--- a/multipicker/build.gradle
+++ b/multipicker/build.gradle
@@ -19,11 +19,11 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize'
android {
- compileSdkVersion 29
+ compileSdkVersion 30
defaultConfig {
minSdkVersion 19
- targetSdkVersion 29
+ targetSdkVersion 30
versionCode 1
versionName "1.0"
diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/AudioPicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/AudioPicker.kt
index 516022100d..e8970d72ef 100644
--- a/multipicker/src/main/java/im/vector/lib/multipicker/AudioPicker.kt
+++ b/multipicker/src/main/java/im/vector/lib/multipicker/AudioPicker.kt
@@ -58,7 +58,7 @@ class AudioPicker : Picker() {
context.contentResolver.openFileDescriptor(selectedUri, "r")?.use { pfd ->
val mediaMetadataRetriever = MediaMetadataRetriever()
mediaMetadataRetriever.setDataSource(pfd.fileDescriptor)
- duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toLong()
+ duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L
}
audioList.add(
diff --git a/multipicker/src/main/java/im/vector/lib/multipicker/VideoPicker.kt b/multipicker/src/main/java/im/vector/lib/multipicker/VideoPicker.kt
index c7c06f795f..dada9ac5bd 100644
--- a/multipicker/src/main/java/im/vector/lib/multipicker/VideoPicker.kt
+++ b/multipicker/src/main/java/im/vector/lib/multipicker/VideoPicker.kt
@@ -61,10 +61,10 @@ class VideoPicker : Picker() {
context.contentResolver.openFileDescriptor(selectedUri, "r")?.use { pfd ->
val mediaMetadataRetriever = MediaMetadataRetriever()
mediaMetadataRetriever.setDataSource(pfd.fileDescriptor)
- duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION).toLong()
- width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH).toInt()
- height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT).toInt()
- orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION).toInt()
+ duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong() ?: 0L
+ width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 0
+ height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 0
+ orientation = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)?.toInt() ?: 0
}
videoList.add(
diff --git a/vector/build.gradle b/vector/build.gradle
index 71cbe532c3..ced0899cf9 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -101,7 +101,7 @@ ext.abiVersionCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86": 3, "x86_64": 4].
def buildNumber = System.env.BUILDKITE_BUILD_NUMBER as Integer ?: 0
android {
- compileSdkVersion 29
+ compileSdkVersion 30
// Due to a bug introduced in Android gradle plugin 3.6.0, we have to specify the ndk version to use
// Ref: https://issuetracker.google.com/issues/144111441
@@ -111,7 +111,7 @@ android {
applicationId "im.vector.app"
// Set to API 21: see #405
minSdkVersion 21
- targetSdkVersion 29
+ targetSdkVersion 30
multiDexEnabled true
// `develop` branch will have version code from timestamp, to ensure each build from CI has a incremented versionCode.
diff --git a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
index 58b596b05f..2d0077fc55 100644
--- a/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
+++ b/vector/src/androidTest/java/im/vector/app/ui/UiAllScreensSanityTest.kt
@@ -196,6 +196,8 @@ class UiAllScreensSanityTest {
pressBack()
clickMenu(R.id.video_call)
pressBack()
+ clickMenu(R.id.search)
+ pressBack()
pressBack()
}
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
index a585e8ea77..d8b61f3cba 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
@@ -19,10 +19,12 @@ package im.vector.app.core.platform
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
+import android.os.Build
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
+import android.view.WindowInsetsController
import android.view.WindowManager
import android.widget.TextView
import androidx.annotation.AttrRes
@@ -33,6 +35,7 @@ import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory
@@ -410,13 +413,25 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScr
/**
* Force to render the activity in fullscreen
*/
+ @Suppress("DEPRECATION")
private fun setFullScreen() {
- window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- or View.SYSTEM_UI_FLAG_FULLSCREEN
- or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ // New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ window.setDecorFitsSystemWindows(false)
+ // New API instead of SYSTEM_UI_FLAG_IMMERSIVE
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ // New API instead of FLAG_TRANSLUCENT_STATUS
+ window.statusBarColor = ContextCompat.getColor(this, im.vector.lib.attachmentviewer.R.color.half_transparent_status_bar)
+ // New API instead of FLAG_TRANSLUCENT_NAVIGATION
+ window.navigationBarColor = ContextCompat.getColor(this, im.vector.lib.attachmentviewer.R.color.half_transparent_status_bar)
+ } else {
+ window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ or View.SYSTEM_UI_FLAG_FULLSCREEN
+ or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+ }
}
/* ==========================================================================================
diff --git a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt
index 407b51666b..cdb015e4da 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt
@@ -19,6 +19,7 @@ package im.vector.app.features.attachments.preview
import android.app.Activity.RESULT_CANCELED
import android.app.Activity.RESULT_OK
+import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
@@ -153,8 +154,13 @@ class AttachmentsPreviewFragment @Inject constructor(
)
}
+ @Suppress("DEPRECATION")
private fun applyInsets() {
- view?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ activity?.window?.setDecorFitsSystemWindows(false)
+ } else {
+ view?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ }
ViewCompat.setOnApplyWindowInsetsListener(views.attachmentPreviewerBottomContainer) { v, insets ->
v.updatePadding(bottom = insets.systemWindowInsetBottom)
insets
diff --git a/vector/src/main/java/im/vector/app/features/call/CallAudioManager.kt b/vector/src/main/java/im/vector/app/features/call/CallAudioManager.kt
index 3a24cf6d48..82bbaf1d54 100644
--- a/vector/src/main/java/im/vector/app/features/call/CallAudioManager.kt
+++ b/vector/src/main/java/im/vector/app/features/call/CallAudioManager.kt
@@ -48,7 +48,7 @@ class CallAudioManager(
private var savedIsSpeakerPhoneOn = false
private var savedIsMicrophoneMute = false
- private var savedAudioMode = AudioManager.MODE_INVALID
+ private var savedAudioMode = AudioManager.MODE_NORMAL
private var connectedBlueToothHeadset: BluetoothProfile? = null
private var wantsBluetoothConnection = false
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
index 41bf7bbeaf..6c49d4d3e2 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt
@@ -25,8 +25,11 @@ import android.os.Bundle
import android.os.Parcelable
import android.view.View
import android.view.Window
+import android.view.WindowInsets
+import android.view.WindowInsetsController
import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
+import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.core.view.ViewCompat
import androidx.core.view.isInvisible
@@ -102,29 +105,49 @@ class VectorCallActivity : VectorBaseActivity(), CallContro
setContentView(R.layout.activity_call)
}
+ @Suppress("DEPRECATION")
private fun hideSystemUI() {
systemUiVisibility = false
// Enables regular immersive mode.
// For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
// Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
- // Set the content to appear under the system bars so that the
- // content doesn't resize when the system bars hide and show.
- or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- // Hide the nav bar and status bar
- or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- or View.SYSTEM_UI_FLAG_FULLSCREEN)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ // New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ window.setDecorFitsSystemWindows(false)
+ // New API instead of SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ window.decorView.windowInsetsController?.hide(WindowInsets.Type.navigationBars())
+ // New API instead of SYSTEM_UI_FLAG_IMMERSIVE
+ window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
+ // New API instead of FLAG_TRANSLUCENT_STATUS
+ window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
+ // New API instead of FLAG_TRANSLUCENT_NAVIGATION
+ window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
+ } else {
+ window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
+ // Set the content to appear under the system bars so that the
+ // content doesn't resize when the system bars hide and show.
+ or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ // Hide the nav bar and status bar
+ or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ or View.SYSTEM_UI_FLAG_FULLSCREEN)
+ }
}
// Shows the system bars by removing all the flags
// except for the ones that make the content appear under the system bars.
+ @Suppress("DEPRECATION")
private fun showSystemUI() {
systemUiVisibility = true
- window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ // New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ window.setDecorFitsSystemWindows(false)
+ } else {
+ window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
+ }
}
private fun toggleUiSystemVisibility() {
diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
index f1ea50c9bf..149bd629e1 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapBottomSheet.kt
@@ -17,6 +17,7 @@
package im.vector.app.features.crypto.recover
import android.app.Dialog
+import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.view.KeyEvent
@@ -102,7 +103,12 @@ class BootstrapBottomSheet : VectorBaseBottomSheetDialogFragment= Build.VERSION_CODES.R) {
+ dialog?.window?.setDecorFitsSystemWindows(false)
+ } else {
+ @Suppress("DEPRECATION")
+ dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
+ }
return rootView
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
index e134230c61..2d2059377c 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
@@ -297,6 +297,8 @@ class RoomDetailFragment @Inject constructor(
private var lockSendButton = false
private val activeCallViewHolder = ActiveCallViewHolder()
+ private lateinit var emojiPopup: EmojiPopup
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(MessageSharedActionViewModel::class.java)
@@ -512,7 +514,7 @@ class RoomDetailFragment @Inject constructor(
}
private fun setupEmojiPopup() {
- val emojiPopup = EmojiPopup
+ emojiPopup = EmojiPopup
.Builder
.fromRootView(views.rootConstraintLayout)
.setKeyboardAnimationStyle(R.style.emoji_fade_animation_style)
@@ -591,6 +593,7 @@ class RoomDetailFragment @Inject constructor(
autoCompleter.clear()
debouncer.cancelAll()
views.timelineRecyclerView.cleanup()
+ emojiPopup.dismiss()
super.onDestroyView()
}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
index 8a8701e45f..9a57d9480c 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/search/SearchFragment.kt
@@ -76,10 +76,10 @@ class SearchFragment @Inject constructor(
controller.listener = this
}
- override fun onDestroy() {
- super.onDestroy()
+ override fun onDestroyView() {
views.searchResultRecycler.cleanup()
controller.listener = null
+ super.onDestroyView()
}
override fun invalidate() = withState(searchViewModel) { state ->
diff --git a/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt
index 4b03c93321..9ea42308eb 100644
--- a/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt
@@ -155,18 +155,15 @@ class LoginWebFragment @Inject constructor(
// avoid infinite onPageFinished call
if (url.startsWith("http")) {
// Generic method to make a bridge between JS and the UIWebView
- val mxcJavascriptSendObjectMessage = assetReader.readAssetFile("sendObject.js")
- view.loadUrl(mxcJavascriptSendObjectMessage)
+ assetReader.readAssetFile("sendObject.js")?.let { view.loadUrl(it) }
if (state.signMode == SignMode.SignIn) {
// The function the fallback page calls when the login is complete
- val mxcJavascriptOnLogin = assetReader.readAssetFile("onLogin.js")
- view.loadUrl(mxcJavascriptOnLogin)
+ assetReader.readAssetFile("onLogin.js")?.let { view.loadUrl(it) }
} else {
// MODE_REGISTER
// The function the fallback page calls when the registration is complete
- val mxcJavascriptOnRegistered = assetReader.readAssetFile("onRegistered.js")
- view.loadUrl(mxcJavascriptOnRegistered)
+ assetReader.readAssetFile("onRegistered.js")?.let { view.loadUrl(it) }
}
}
}
diff --git a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt
index 24fb6159f8..28b2a8b4d5 100644
--- a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt
+++ b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt
@@ -21,6 +21,7 @@ import android.os.Build
import android.os.Handler
import android.os.Looper
import android.view.View
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
import android.widget.ImageView
import com.tapadoo.alerter.Alerter
import com.tapadoo.alerter.OnHideAlertListener
@@ -165,9 +166,7 @@ class PopupAlertManager @Inject constructor(private val avatarRenderer: Lazy
- var flags = view.systemUiVisibility
- flags = flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
- view.systemUiVisibility = flags
+ view.windowInsetsController?.setSystemBarsAppearance(0, APPEARANCE_LIGHT_STATUS_BARS)
}
}
@@ -179,9 +178,7 @@ class PopupAlertManager @Inject constructor(private val avatarRenderer: Lazy
- var flags = view.systemUiVisibility
- flags = flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
- view.systemUiVisibility = flags
+ view.windowInsetsController?.setSystemBarsAppearance(APPEARANCE_LIGHT_STATUS_BARS, APPEARANCE_LIGHT_STATUS_BARS)
}
}
diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt
index 7be7624a48..1a03fc6c47 100755
--- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt
+++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt
@@ -21,7 +21,6 @@ import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
-import android.os.AsyncTask
import android.os.Build
import android.view.View
import androidx.fragment.app.DialogFragment
@@ -37,6 +36,11 @@ import im.vector.app.features.settings.devtools.GossipingEventsSerializer
import im.vector.app.features.settings.locale.SystemLocaleProvider
import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.version.VersionProvider
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import okhttp3.Call
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
@@ -98,6 +102,8 @@ class BugReporter @Inject constructor(
var screenshot: Bitmap? = null
private set
+ private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
+
private val LOGCAT_CMD_ERROR = arrayOf("logcat", // /< Run 'logcat' command
"-d", // /< Dump the log rather than continue outputting it
"-v", // formatting
@@ -160,13 +166,13 @@ class BugReporter @Inject constructor(
withScreenshot: Boolean,
theBugDescription: String,
listener: IMXBugReportListener?) {
- object : AsyncTask() {
- // enumerate files to delete
- val mBugReportFiles: MutableList = ArrayList()
+ // enumerate files to delete
+ val mBugReportFiles: MutableList = ArrayList()
- override fun doInBackground(vararg voids: Void?): String? {
+ coroutineScope.launch {
+ var serverError: String? = null
+ withContext(Dispatchers.IO) {
var bugDescription = theBugDescription
- var serverError: String? = null
val crashCallStack = getCrashDescription(context)
if (null != crashCallStack) {
@@ -342,7 +348,11 @@ class BugReporter @Inject constructor(
}
Timber.v("## onWrite() : $percentage%")
- publishProgress(percentage)
+ try {
+ listener?.onProgress(percentage)
+ } catch (e: Exception) {
+ Timber.e(e, "## onProgress() : failed")
+ }
}
// build the request
@@ -386,11 +396,13 @@ class BugReporter @Inject constructor(
}
// check if the error message
- try {
- val responseJSON = JSONObject(serverError)
- serverError = responseJSON.getString("error")
- } catch (e: JSONException) {
- Timber.e(e, "doInBackground ; Json conversion failed")
+ serverError?.let {
+ try {
+ val responseJSON = JSONObject(it)
+ serverError = responseJSON.getString("error")
+ } catch (e: JSONException) {
+ Timber.e(e, "doInBackground ; Json conversion failed")
+ }
}
// should never happen
@@ -403,21 +415,9 @@ class BugReporter @Inject constructor(
}
}
}
-
- return serverError
}
- override fun onProgressUpdate(vararg progress: Int?) {
- if (null != listener) {
- try {
- listener.onProgress(progress[0] ?: 0)
- } catch (e: Exception) {
- Timber.e(e, "## onProgress() : failed")
- }
- }
- }
-
- override fun onPostExecute(reason: String?) {
+ withContext(Dispatchers.Main) {
mBugReportCall = null
// delete when the bug report has been successfully sent
@@ -429,17 +429,17 @@ class BugReporter @Inject constructor(
try {
if (mIsCancelled) {
listener.onUploadCancelled()
- } else if (null == reason) {
+ } else if (null == serverError) {
listener.onUploadSucceed()
} else {
- listener.onUploadFailed(reason)
+ listener.onUploadFailed(serverError)
}
} catch (e: Exception) {
Timber.e(e, "## onPostExecute() : failed")
}
}
}
- }.execute()
+ }
}
/**
@@ -457,9 +457,9 @@ class BugReporter @Inject constructor(
activity.startActivity(intent)
}
- // ==============================================================================================================
- // crash report management
- // ==============================================================================================================
+// ==============================================================================================================
+// crash report management
+// ==============================================================================================================
/**
* Provides the crash file
@@ -529,9 +529,9 @@ class BugReporter @Inject constructor(
return null
}
- // ==============================================================================================================
- // Screenshot management
- // ==============================================================================================================
+// ==============================================================================================================
+// Screenshot management
+// ==============================================================================================================
/**
* Take a screenshot of the display.
@@ -598,9 +598,9 @@ class BugReporter @Inject constructor(
}
}
- // ==============================================================================================================
- // Logcat management
- // ==============================================================================================================
+// ==============================================================================================================
+// Logcat management
+// ==============================================================================================================
/**
* Save the logcat
@@ -660,9 +660,9 @@ class BugReporter @Inject constructor(
}
}
- // ==============================================================================================================
- // File compression management
- // ==============================================================================================================
+// ==============================================================================================================
+// File compression management
+// ==============================================================================================================
/**
* GZip a file
diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt
index 84a419c6c6..fe6dc86165 100644
--- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt
@@ -16,6 +16,7 @@
package im.vector.app.features.roomprofile.uploads.media
+import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.LayoutInflater
@@ -78,9 +79,14 @@ class RoomUploadsMediaFragment @Inject constructor(
controller.listener = this
}
+ @Suppress("DEPRECATION")
private fun getNumberOfColumns(): Int {
val displayMetrics = DisplayMetrics()
- requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ requireContext().display?.getMetrics(displayMetrics)
+ } else {
+ requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
+ }
return dimensionConverter.pxToDp(displayMetrics.widthPixels) / IMAGE_SIZE_DP
}
diff --git a/vector/src/main/java/im/vector/app/features/webview/VectorWebViewActivity.kt b/vector/src/main/java/im/vector/app/features/webview/VectorWebViewActivity.kt
index 68c13c300e..e4d2571333 100644
--- a/vector/src/main/java/im/vector/app/features/webview/VectorWebViewActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/webview/VectorWebViewActivity.kt
@@ -64,7 +64,9 @@ class VectorWebViewActivity : VectorBaseActivity()
// Allow use of Local Storage
domStorageEnabled = true
+ @Suppress("DEPRECATION")
allowFileAccessFromFileURLs = true
+ @Suppress("DEPRECATION")
allowUniversalAccessFromFileURLs = true
displayZoomControls = false
@@ -73,7 +75,7 @@ class VectorWebViewActivity : VectorBaseActivity()
val cookieManager = android.webkit.CookieManager.getInstance()
cookieManager.setAcceptThirdPartyCookies(views.simpleWebview, true)
- val url = intent.extras?.getString(EXTRA_URL)
+ val url = intent.extras?.getString(EXTRA_URL) ?: return
val title = intent.extras?.getString(EXTRA_TITLE, USE_TITLE_FROM_WEB_PAGE)
if (title != USE_TITLE_FROM_WEB_PAGE) {
setTitle(title)
diff --git a/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt b/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt
index 446bc1663f..d30baef55a 100644
--- a/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt
+++ b/vector/src/main/java/im/vector/app/features/widgets/webview/WidgetWebView.kt
@@ -54,7 +54,9 @@ fun WebView.setupForWidget(webViewEventListener: WebViewEventListener) {
// Allow use of Local Storage
settings.domStorageEnabled = true
+ @Suppress("DEPRECATION")
settings.allowFileAccessFromFileURLs = true
+ @Suppress("DEPRECATION")
settings.allowUniversalAccessFromFileURLs = true
settings.displayZoomControls = false
@@ -75,7 +77,6 @@ fun WebView.clearAfterWidget() {
// Make sure you remove the WebView from its parent view before doing anything.
(parent as? ViewGroup)?.removeAllViews()
webChromeClient = null
- webViewClient = null
clearHistory()
// NOTE: clears RAM cache, if you pass true, it will also clear the disk cache.
clearCache(true)