Merge branch 'element-hq:develop' into yostyle/fix_crypto_migration
This commit is contained in:
commit
7f8e73ee4d
18
CHANGES.md
18
CHANGES.md
|
@ -1,3 +1,21 @@
|
||||||
|
Changes in Element v1.6.8 (2023-11-28)
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Bugfixes 🐛
|
||||||
|
----------
|
||||||
|
- Stop incoming call ringing if the call is cancelled or answered on another session. ([#4066](https://github.com/vector-im/element-android/issues/4066))
|
||||||
|
- Ensure the incoming call will not ring forever, in case the call is not ended by another way. ([#8178](https://github.com/vector-im/element-android/issues/8178))
|
||||||
|
- Unified Push: Ignore the potential SSL error when the custom gateway is testing locally ([#8683](https://github.com/vector-im/element-android/issues/8683))
|
||||||
|
- Fix issue with timeline message view reuse while rich text editor is enabled ([#8688](https://github.com/vector-im/element-android/issues/8688))
|
||||||
|
|
||||||
|
Other changes
|
||||||
|
-------------
|
||||||
|
- Remove unused WebRTC dependency ([#8658](https://github.com/vector-im/element-android/issues/8658))
|
||||||
|
- Take into account boolean "io.element.disable_network_constraint" from the .well-known file. ([#8662](https://github.com/vector-im/element-android/issues/8662))
|
||||||
|
- Update regex for email address to be aligned on RFC 5322 ([#8671](https://github.com/vector-im/element-android/issues/8671))
|
||||||
|
- Bump crypto sdk bindings to v0.3.16 ([#8679](https://github.com/vector-im/element-android/issues/8679))
|
||||||
|
|
||||||
|
|
||||||
Changes in Element v1.6.6 (2023-10-05)
|
Changes in Element v1.6.6 (2023-10-05)
|
||||||
======================================
|
======================================
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Support Functional members (https://github.com/vector-im/element-meta/blob/develop/spec/functional_members.md)
|
|
@ -1 +0,0 @@
|
||||||
Ensure the incoming call will not ring forever, in case the call is not ended by another way.
|
|
|
@ -1 +0,0 @@
|
||||||
Remove unused WebRTC dependency
|
|
|
@ -1 +0,0 @@
|
||||||
Take into account boolean "io.element.disable_network_constraint" from the .well-known file.
|
|
|
@ -1 +0,0 @@
|
||||||
Update regex for email address to be aligned on RFC 5322
|
|
|
@ -1 +0,0 @@
|
||||||
Bump crypto sdk bindings to v0.3.16
|
|
|
@ -1 +0,0 @@
|
||||||
Unified Push: Ignore the potential SSL error when the custom gateway is testing locally
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Add support for Mobile Device Management.
|
||||||
|
The keys are:
|
||||||
|
- default homeserver URL `im.vector.app.serverConfigDefaultHomeserverUrlString`
|
||||||
|
- push gateway URL `im.vector.app.serverConfigSygnalAPIUrlString`
|
||||||
|
- permalink base URL `im.vector.app.clientPermalinkBaseUrl`
|
|
@ -0,0 +1,2 @@
|
||||||
|
Main changes in this version: Bugfixes.
|
||||||
|
Full changelog: https://github.com/vector-im/element-android/releases
|
|
@ -62,7 +62,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.6.8\""
|
buildConfigField "String", "SDK_VERSION", "\"1.6.10\""
|
||||||
|
|
||||||
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()}\""
|
||||||
|
|
|
@ -20,6 +20,8 @@ import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider
|
||||||
|
|
||||||
class TestRoomDisplayNameFallbackProvider : RoomDisplayNameFallbackProvider {
|
class TestRoomDisplayNameFallbackProvider : RoomDisplayNameFallbackProvider {
|
||||||
|
|
||||||
|
override fun excludedUserIds(roomId: String) = emptyList<String>()
|
||||||
|
|
||||||
override fun getNameForRoomInvite() =
|
override fun getNameForRoomInvite() =
|
||||||
"Room invite"
|
"Room invite"
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,10 @@ package org.matrix.android.sdk.api.provider
|
||||||
* *Limitation*: if the locale of the device changes, the methods will not be called again.
|
* *Limitation*: if the locale of the device changes, the methods will not be called again.
|
||||||
*/
|
*/
|
||||||
interface RoomDisplayNameFallbackProvider {
|
interface RoomDisplayNameFallbackProvider {
|
||||||
|
/**
|
||||||
|
* Return the list of user ids to ignore when computing the room display name.
|
||||||
|
*/
|
||||||
|
fun excludedUserIds(roomId: String): List<String>
|
||||||
fun getNameForRoomInvite(): String
|
fun getNameForRoomInvite(): String
|
||||||
fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List<String>): String
|
fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List<String>): String
|
||||||
fun getNameFor1member(name: String): String
|
fun getNameFor1member(name: String): String
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.matrix.android.sdk.internal.session.room
|
package org.matrix.android.sdk.internal.session.room
|
||||||
|
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
@ -31,7 +32,12 @@ import org.matrix.android.sdk.internal.di.UserId
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
|
import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class RoomAvatarResolver @Inject constructor(@UserId private val userId: String) {
|
internal class RoomAvatarResolver @Inject constructor(
|
||||||
|
matrixConfiguration: MatrixConfiguration,
|
||||||
|
@UserId private val userId: String
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val roomDisplayNameFallbackProvider = matrixConfiguration.roomDisplayNameFallbackProvider
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the room avatar url.
|
* Compute the room avatar url.
|
||||||
|
@ -40,21 +46,26 @@ internal class RoomAvatarResolver @Inject constructor(@UserId private val userId
|
||||||
* @return the room avatar url, can be a fallback to a room member avatar or null
|
* @return the room avatar url, can be a fallback to a room member avatar or null
|
||||||
*/
|
*/
|
||||||
fun resolve(realm: Realm, roomId: String): String? {
|
fun resolve(realm: Realm, roomId: String): String? {
|
||||||
val roomName = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_AVATAR, stateKey = "")
|
val roomAvatarUrl = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_AVATAR, stateKey = "")
|
||||||
?.root
|
?.root
|
||||||
?.asDomain()
|
?.asDomain()
|
||||||
?.content
|
?.content
|
||||||
?.toModel<RoomAvatarContent>()
|
?.toModel<RoomAvatarContent>()
|
||||||
?.avatarUrl
|
?.avatarUrl
|
||||||
if (!roomName.isNullOrEmpty()) {
|
if (!roomAvatarUrl.isNullOrEmpty()) {
|
||||||
return roomName
|
return roomAvatarUrl
|
||||||
}
|
}
|
||||||
val roomMembers = RoomMemberHelper(realm, roomId)
|
|
||||||
val members = roomMembers.queryActiveRoomMembersEvent().findAll()
|
|
||||||
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
|
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
|
||||||
val isDirectRoom = RoomSummaryEntity.where(realm, roomId).findFirst()?.isDirect.orFalse()
|
val isDirectRoom = RoomSummaryEntity.where(realm, roomId).findFirst()?.isDirect.orFalse()
|
||||||
|
|
||||||
if (isDirectRoom) {
|
if (isDirectRoom) {
|
||||||
|
val excludedUserIds = roomDisplayNameFallbackProvider.excludedUserIds(roomId)
|
||||||
|
val roomMembers = RoomMemberHelper(realm, roomId)
|
||||||
|
val members = roomMembers
|
||||||
|
.queryActiveRoomMembersEvent()
|
||||||
|
.not().`in`(RoomMemberSummaryEntityFields.USER_ID, excludedUserIds.toTypedArray())
|
||||||
|
.findAll()
|
||||||
|
|
||||||
if (members.size == 1) {
|
if (members.size == 1) {
|
||||||
// Use avatar of a left user
|
// Use avatar of a left user
|
||||||
val firstLeftAvatarUrl = roomMembers.queryLeftRoomMembersEvent()
|
val firstLeftAvatarUrl = roomMembers.queryLeftRoomMembersEvent()
|
||||||
|
|
|
@ -92,18 +92,20 @@ internal class RoomDisplayNameResolver @Inject constructor(
|
||||||
}
|
}
|
||||||
?: roomDisplayNameFallbackProvider.getNameForRoomInvite()
|
?: roomDisplayNameFallbackProvider.getNameForRoomInvite()
|
||||||
} else if (roomEntity?.membership == Membership.JOIN) {
|
} else if (roomEntity?.membership == Membership.JOIN) {
|
||||||
|
val excludedUserIds = roomDisplayNameFallbackProvider.excludedUserIds(roomId)
|
||||||
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
|
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
|
||||||
val invitedCount = roomSummary?.invitedMembersCount ?: 0
|
val invitedCount = roomSummary?.invitedMembersCount ?: 0
|
||||||
val joinedCount = roomSummary?.joinedMembersCount ?: 0
|
val joinedCount = roomSummary?.joinedMembersCount ?: 0
|
||||||
val otherMembersSubset: List<RoomMemberSummaryEntity> = if (roomSummary?.heroes?.isNotEmpty() == true) {
|
val otherMembersSubset: List<RoomMemberSummaryEntity> = if (roomSummary?.heroes?.isNotEmpty() == true) {
|
||||||
roomSummary.heroes.mapNotNull { userId ->
|
roomSummary.heroes.mapNotNull { userId ->
|
||||||
roomMembers.getLastRoomMember(userId)?.takeIf {
|
roomMembers.getLastRoomMember(userId)?.takeIf {
|
||||||
it.membership == Membership.INVITE || it.membership == Membership.JOIN
|
(it.membership == Membership.INVITE || it.membership == Membership.JOIN) && !excludedUserIds.contains(it.userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
activeMembers.where()
|
activeMembers.where()
|
||||||
.notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
.notEqualTo(RoomMemberSummaryEntityFields.USER_ID, userId)
|
||||||
|
.not().`in`(RoomMemberSummaryEntityFields.USER_ID, excludedUserIds.toTypedArray())
|
||||||
.limit(5)
|
.limit(5)
|
||||||
.findAll()
|
.findAll()
|
||||||
.createSnapshot()
|
.createSnapshot()
|
||||||
|
@ -113,6 +115,7 @@ internal class RoomDisplayNameResolver @Inject constructor(
|
||||||
0 -> {
|
0 -> {
|
||||||
// Get left members if any
|
// Get left members if any
|
||||||
val leftMembersNames = roomMembers.queryLeftRoomMembersEvent()
|
val leftMembersNames = roomMembers.queryLeftRoomMembersEvent()
|
||||||
|
.not().`in`(RoomMemberSummaryEntityFields.USER_ID, excludedUserIds.toTypedArray())
|
||||||
.findAll()
|
.findAll()
|
||||||
.map { displayNameResolver.getBestName(it.toMatrixItem()) }
|
.map { displayNameResolver.getBestName(it.toMatrixItem()) }
|
||||||
val directUserId = roomSummary?.directUserId
|
val directUserId = roomSummary?.directUserId
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Generated file, do not edit -->
|
||||||
|
<string name="verification_emoji_dog">狗</string>
|
||||||
|
<string name="verification_emoji_cat">貓</string>
|
||||||
|
<string name="verification_emoji_lion">獅子</string>
|
||||||
|
<string name="verification_emoji_horse">馬</string>
|
||||||
|
<string name="verification_emoji_unicorn">獨角獸</string>
|
||||||
|
<string name="verification_emoji_pig">豬</string>
|
||||||
|
<string name="verification_emoji_elephant">大象</string>
|
||||||
|
<string name="verification_emoji_rabbit">兔子</string>
|
||||||
|
<string name="verification_emoji_panda">熊貓</string>
|
||||||
|
<string name="verification_emoji_rooster">公雞</string>
|
||||||
|
<string name="verification_emoji_penguin">企鵝</string>
|
||||||
|
<string name="verification_emoji_turtle">烏龜</string>
|
||||||
|
<string name="verification_emoji_fish">魚</string>
|
||||||
|
<string name="verification_emoji_octopus">章魚</string>
|
||||||
|
<string name="verification_emoji_butterfly">蝴蝶</string>
|
||||||
|
<string name="verification_emoji_flower">花</string>
|
||||||
|
<string name="verification_emoji_tree">樹</string>
|
||||||
|
<string name="verification_emoji_cactus">仙人掌</string>
|
||||||
|
<string name="verification_emoji_mushroom">蘑菇</string>
|
||||||
|
<string name="verification_emoji_globe">地球</string>
|
||||||
|
<string name="verification_emoji_moon">月亮</string>
|
||||||
|
<string name="verification_emoji_cloud">雲朵</string>
|
||||||
|
<string name="verification_emoji_fire">火</string>
|
||||||
|
<string name="verification_emoji_banana">香蕉</string>
|
||||||
|
<string name="verification_emoji_apple">蘋果</string>
|
||||||
|
<string name="verification_emoji_strawberry">草莓</string>
|
||||||
|
<string name="verification_emoji_corn">玉米</string>
|
||||||
|
<string name="verification_emoji_pizza">披薩</string>
|
||||||
|
<string name="verification_emoji_cake">蛋糕</string>
|
||||||
|
<string name="verification_emoji_heart">愛心</string>
|
||||||
|
<string name="verification_emoji_smiley">笑臉</string>
|
||||||
|
<string name="verification_emoji_robot">機器人</string>
|
||||||
|
<string name="verification_emoji_hat">帽子</string>
|
||||||
|
<string name="verification_emoji_glasses">眼鏡</string>
|
||||||
|
<string name="verification_emoji_spanner">扳手</string>
|
||||||
|
<string name="verification_emoji_santa">聖誕老人</string>
|
||||||
|
<string name="verification_emoji_thumbs_up">讚</string>
|
||||||
|
<string name="verification_emoji_umbrella">雨傘</string>
|
||||||
|
<string name="verification_emoji_hourglass">沙漏</string>
|
||||||
|
<string name="verification_emoji_clock">時鐘</string>
|
||||||
|
<string name="verification_emoji_gift">禮物</string>
|
||||||
|
<string name="verification_emoji_light_bulb">燈泡</string>
|
||||||
|
<string name="verification_emoji_book">書</string>
|
||||||
|
<string name="verification_emoji_pencil">鉛筆</string>
|
||||||
|
<string name="verification_emoji_paperclip">迴紋針</string>
|
||||||
|
<string name="verification_emoji_scissors">剪刀</string>
|
||||||
|
<string name="verification_emoji_lock">鎖頭</string>
|
||||||
|
<string name="verification_emoji_key">鑰匙</string>
|
||||||
|
<string name="verification_emoji_hammer">鎚子</string>
|
||||||
|
<string name="verification_emoji_telephone">電話</string>
|
||||||
|
<string name="verification_emoji_flag">旗幟</string>
|
||||||
|
<string name="verification_emoji_train">火車</string>
|
||||||
|
<string name="verification_emoji_bicycle">腳踏車</string>
|
||||||
|
<string name="verification_emoji_aeroplane">飛機</string>
|
||||||
|
<string name="verification_emoji_rocket">火箭</string>
|
||||||
|
<string name="verification_emoji_trophy">獎盃</string>
|
||||||
|
<string name="verification_emoji_ball">足球</string>
|
||||||
|
<string name="verification_emoji_guitar">吉他</string>
|
||||||
|
<string name="verification_emoji_trumpet">喇叭</string>
|
||||||
|
<string name="verification_emoji_bell">鈴鐺</string>
|
||||||
|
<string name="verification_emoji_anchor">船錨</string>
|
||||||
|
<string name="verification_emoji_headphones">耳機</string>
|
||||||
|
<string name="verification_emoji_folder">資料夾</string>
|
||||||
|
<string name="verification_emoji_pin">圖釘</string>
|
||||||
|
</resources>
|
|
@ -96,7 +96,8 @@ write_file(os.path.join(data_defs_dir, "values/strings_sas.xml"), default)
|
||||||
for lang in cumul:
|
for lang in cumul:
|
||||||
androidLang = lang\
|
androidLang = lang\
|
||||||
.replace("_", "-r")\
|
.replace("_", "-r")\
|
||||||
.replace("zh-rHans", "zh-rCN")
|
.replace("zh-rHans", "zh-rCN") \
|
||||||
|
.replace("zh-rHant", "zh-rTW")
|
||||||
write_file(os.path.join(data_defs_dir, "values-" + androidLang + "/strings_sas.xml"), cumul[lang])
|
write_file(os.path.join(data_defs_dir, "values-" + androidLang + "/strings_sas.xml"), cumul[lang])
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
|
@ -160,11 +160,11 @@ adb -e uninstall im.vector.app.debug.test
|
||||||
|
|
||||||
printf "\n================================================================================\n"
|
printf "\n================================================================================\n"
|
||||||
printf "Running the integration test UiAllScreensSanityTest.allScreensTest()...\n"
|
printf "Running the integration test UiAllScreensSanityTest.allScreensTest()...\n"
|
||||||
./gradlew connectedGplayRustCryptoDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest
|
./gradlew connectedGplayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest
|
||||||
|
|
||||||
printf "\n================================================================================\n"
|
printf "\n================================================================================\n"
|
||||||
printf "Building the app...\n"
|
printf "Building the app...\n"
|
||||||
./gradlew assembleGplayRustCryptoDebug
|
./gradlew assembleGplayDebug
|
||||||
|
|
||||||
printf "\n================================================================================\n"
|
printf "\n================================================================================\n"
|
||||||
printf "Uninstalling previous debug app if any...\n"
|
printf "Uninstalling previous debug app if any...\n"
|
||||||
|
@ -172,7 +172,7 @@ adb -e uninstall im.vector.app.debug
|
||||||
|
|
||||||
printf "\n================================================================================\n"
|
printf "\n================================================================================\n"
|
||||||
printf "Installing the app...\n"
|
printf "Installing the app...\n"
|
||||||
adb -e install ./vector-app/build/outputs/apk/gplayRustCrypto/debug/vector-gplay-rustCrypto-arm64-v8a-debug.apk
|
adb -e install ./vector-app/build/outputs/apk/gplay/debug/vector-gplay-arm64-v8a-debug.apk
|
||||||
|
|
||||||
printf "\n================================================================================\n"
|
printf "\n================================================================================\n"
|
||||||
printf "Running the app...\n"
|
printf "Running the app...\n"
|
||||||
|
@ -293,67 +293,67 @@ printf "Unzipping the artifact...\n"
|
||||||
unzip ${targetPath}/vector-gplay-release-unsigned.zip -d ${targetPath}
|
unzip ${targetPath}/vector-gplay-release-unsigned.zip -d ${targetPath}
|
||||||
|
|
||||||
# Flatten folder hierarchy
|
# Flatten folder hierarchy
|
||||||
mv ${targetPath}/gplayRustCrypto/release/* ${targetPath}
|
mv ${targetPath}/gplay/release/* ${targetPath}
|
||||||
rm -rf ${targetPath}/gplay
|
rm -rf ${targetPath}/gplay
|
||||||
|
|
||||||
printf "\n================================================================================\n"
|
printf "\n================================================================================\n"
|
||||||
printf "Signing the APKs...\n"
|
printf "Signing the APKs...\n"
|
||||||
|
|
||||||
cp ${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-unsigned.apk \
|
cp ${targetPath}/vector-gplay-arm64-v8a-release-unsigned.apk \
|
||||||
${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-signed.apk
|
${targetPath}/vector-gplay-arm64-v8a-release-signed.apk
|
||||||
./tools/release/sign_apk_unsafe.sh \
|
./tools/release/sign_apk_unsafe.sh \
|
||||||
${keyStorePath} \
|
${keyStorePath} \
|
||||||
${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-signed.apk \
|
${targetPath}/vector-gplay-arm64-v8a-release-signed.apk \
|
||||||
${keyStorePassword} \
|
${keyStorePassword} \
|
||||||
${keyPassword}
|
${keyPassword}
|
||||||
|
|
||||||
cp ${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-unsigned.apk \
|
cp ${targetPath}/vector-gplay-armeabi-v7a-release-unsigned.apk \
|
||||||
${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-signed.apk
|
${targetPath}/vector-gplay-armeabi-v7a-release-signed.apk
|
||||||
./tools/release/sign_apk_unsafe.sh \
|
./tools/release/sign_apk_unsafe.sh \
|
||||||
${keyStorePath} \
|
${keyStorePath} \
|
||||||
${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-signed.apk \
|
${targetPath}/vector-gplay-armeabi-v7a-release-signed.apk \
|
||||||
${keyStorePassword} \
|
${keyStorePassword} \
|
||||||
${keyPassword}
|
${keyPassword}
|
||||||
|
|
||||||
cp ${targetPath}/vector-gplay-rustCrypto-x86-release-unsigned.apk \
|
cp ${targetPath}/vector-gplay-x86-release-unsigned.apk \
|
||||||
${targetPath}/vector-gplay-rustCrypto-x86-release-signed.apk
|
${targetPath}/vector-gplay-x86-release-signed.apk
|
||||||
./tools/release/sign_apk_unsafe.sh \
|
./tools/release/sign_apk_unsafe.sh \
|
||||||
${keyStorePath} \
|
${keyStorePath} \
|
||||||
${targetPath}/vector-gplay-rustCrypto-x86-release-signed.apk \
|
${targetPath}/vector-gplay-x86-release-signed.apk \
|
||||||
${keyStorePassword} \
|
${keyStorePassword} \
|
||||||
${keyPassword}
|
${keyPassword}
|
||||||
|
|
||||||
cp ${targetPath}/vector-gplay-rustCrypto-x86_64-release-unsigned.apk \
|
cp ${targetPath}/vector-gplay-x86_64-release-unsigned.apk \
|
||||||
${targetPath}/vector-gplay-rustCrypto-x86_64-release-signed.apk
|
${targetPath}/vector-gplay-x86_64-release-signed.apk
|
||||||
./tools/release/sign_apk_unsafe.sh \
|
./tools/release/sign_apk_unsafe.sh \
|
||||||
${keyStorePath} \
|
${keyStorePath} \
|
||||||
${targetPath}/vector-gplay-rustCrypto-x86_64-release-signed.apk \
|
${targetPath}/vector-gplay-x86_64-release-signed.apk \
|
||||||
${keyStorePassword} \
|
${keyStorePassword} \
|
||||||
${keyPassword}
|
${keyPassword}
|
||||||
|
|
||||||
# Ref: https://docs.fastlane.tools/getting-started/android/beta-deployment/#uploading-your-app
|
# Ref: https://docs.fastlane.tools/getting-started/android/beta-deployment/#uploading-your-app
|
||||||
# set SUPPLY_APK_PATHS="${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-unsigned.apk,${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-unsigned.apk,${targetPath}/vector-gplay-rustCrypto-x86-release-unsigned.apk,${targetPath}/vector-gplay-rustCrypto-x86_64-release-unsigned.apk"
|
# set SUPPLY_APK_PATHS="${targetPath}/vector-gplay-arm64-v8a-release-unsigned.apk,${targetPath}/vector-gplay-armeabi-v7a-release-unsigned.apk,${targetPath}/vector-gplay-x86-release-unsigned.apk,${targetPath}/vector-gplay-x86_64-release-unsigned.apk"
|
||||||
#
|
#
|
||||||
# ./fastlane beta
|
# ./fastlane beta
|
||||||
|
|
||||||
printf "\n================================================================================\n"
|
printf "\n================================================================================\n"
|
||||||
printf "Please check the information below:\n"
|
printf "Please check the information below:\n"
|
||||||
|
|
||||||
printf "File vector-gplay-rustCrypto-arm64-v8a-release-signed.apk:\n"
|
printf "File vector-gplay-arm64-v8a-release-signed.apk:\n"
|
||||||
${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-signed.apk | grep package
|
${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-arm64-v8a-release-signed.apk | grep package
|
||||||
printf "File vector-gplay-rustCrypto-armeabi-v7a-release-signed.apk:\n"
|
printf "File vector-gplay-armeabi-v7a-release-signed.apk:\n"
|
||||||
${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-rustCrypto-armeabi-v7a-release-signed.apk | grep package
|
${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-armeabi-v7a-release-signed.apk | grep package
|
||||||
printf "File vector-gplay-rustCrypto-x86-release-signed.apk:\n"
|
printf "File vector-gplay-x86-release-signed.apk:\n"
|
||||||
${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-rustCrypto-x86-release-signed.apk | grep package
|
${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-x86-release-signed.apk | grep package
|
||||||
printf "File vector-gplay-rustCrypto-x86_64-release-signed.apk:\n"
|
printf "File vector-gplay-x86_64-release-signed.apk:\n"
|
||||||
${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-rustCrypto-x86_64-release-signed.apk | grep package
|
${buildToolsPath}/aapt dump badging ${targetPath}/vector-gplay-x86_64-release-signed.apk | grep package
|
||||||
|
|
||||||
printf "\n"
|
printf "\n"
|
||||||
read -p "Does it look correct? Press enter when it's done."
|
read -p "Does it look correct? Press enter when it's done."
|
||||||
|
|
||||||
printf "\n================================================================================\n"
|
printf "\n================================================================================\n"
|
||||||
read -p "Installing apk on a real device, press enter when a real device is connected. "
|
read -p "Installing apk on a real device, press enter when a real device is connected. "
|
||||||
apkPath="${targetPath}/vector-gplay-rustCrypto-arm64-v8a-release-signed.apk"
|
apkPath="${targetPath}/vector-gplay-arm64-v8a-release-signed.apk"
|
||||||
adb -d install ${apkPath}
|
adb -d install ${apkPath}
|
||||||
|
|
||||||
read -p "Please run the APK on your phone to check that the upgrade went well (no init sync, etc.). Press enter when it's done."
|
read -p "Please run the APK on your phone to check that the upgrade went well (no init sync, etc.). Press enter when it's done."
|
||||||
|
|
|
@ -37,7 +37,7 @@ ext.versionMinor = 6
|
||||||
// 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 = 8
|
ext.versionPatch = 10
|
||||||
|
|
||||||
static def getGitTimestamp() {
|
static def getGitTimestamp() {
|
||||||
def cmd = 'git show -s --format=%ct'
|
def cmd = 'git show -s --format=%ct'
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package im.vector.app.core.utils
|
package im.vector.app.core.utils
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import im.vector.app.features.room.VectorRoomDisplayNameFallbackProvider
|
|
||||||
import org.matrix.android.sdk.api.Matrix
|
import org.matrix.android.sdk.api.Matrix
|
||||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.SyncConfig
|
import org.matrix.android.sdk.api.SyncConfig
|
||||||
|
@ -25,7 +24,7 @@ import org.matrix.android.sdk.api.SyncConfig
|
||||||
fun getMatrixInstance(): Matrix {
|
fun getMatrixInstance(): Matrix {
|
||||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
val configuration = MatrixConfiguration(
|
val configuration = MatrixConfiguration(
|
||||||
roomDisplayNameFallbackProvider = VectorRoomDisplayNameFallbackProvider(context),
|
roomDisplayNameFallbackProvider = TestRoomDisplayNameFallbackProvider(),
|
||||||
syncConfig = SyncConfig(longPollTimeout = 5_000L),
|
syncConfig = SyncConfig(longPollTimeout = 5_000L),
|
||||||
)
|
)
|
||||||
return Matrix(context, configuration)
|
return Matrix(context, configuration)
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider
|
||||||
|
|
||||||
|
class TestRoomDisplayNameFallbackProvider : RoomDisplayNameFallbackProvider {
|
||||||
|
|
||||||
|
override fun excludedUserIds(roomId: String) = emptyList<String>()
|
||||||
|
|
||||||
|
override fun getNameForRoomInvite() =
|
||||||
|
"Room invite"
|
||||||
|
|
||||||
|
override fun getNameForEmptyRoom(isDirect: Boolean, leftMemberNames: List<String>) =
|
||||||
|
"Empty room"
|
||||||
|
|
||||||
|
override fun getNameFor1member(name: String) =
|
||||||
|
name
|
||||||
|
|
||||||
|
override fun getNameFor2members(name1: String, name2: String) =
|
||||||
|
"$name1 and $name2"
|
||||||
|
|
||||||
|
override fun getNameFor3members(name1: String, name2: String, name3: String) =
|
||||||
|
"$name1, $name2 and $name3"
|
||||||
|
|
||||||
|
override fun getNameFor4members(name1: String, name2: String, name3: String, name4: String) =
|
||||||
|
"$name1, $name2, $name3 and $name4"
|
||||||
|
|
||||||
|
override fun getNameFor4membersAndMore(name1: String, name2: String, name3: String, remainingCount: Int) =
|
||||||
|
"$name1, $name2, $name3 and $remainingCount others"
|
||||||
|
}
|
|
@ -26,6 +26,8 @@ import im.vector.app.core.pushers.PushParser
|
||||||
import im.vector.app.core.pushers.PushersManager
|
import im.vector.app.core.pushers.PushersManager
|
||||||
import im.vector.app.core.pushers.UnifiedPushHelper
|
import im.vector.app.core.pushers.UnifiedPushHelper
|
||||||
import im.vector.app.core.pushers.VectorPushHandler
|
import im.vector.app.core.pushers.VectorPushHandler
|
||||||
|
import im.vector.app.features.mdm.MdmData
|
||||||
|
import im.vector.app.features.mdm.MdmService
|
||||||
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.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
@ -46,6 +48,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
@Inject lateinit var pushParser: PushParser
|
@Inject lateinit var pushParser: PushParser
|
||||||
@Inject lateinit var vectorPushHandler: VectorPushHandler
|
@Inject lateinit var vectorPushHandler: VectorPushHandler
|
||||||
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
||||||
|
@Inject lateinit var mdmService: MdmService
|
||||||
|
|
||||||
private val scope = CoroutineScope(SupervisorJob())
|
private val scope = CoroutineScope(SupervisorJob())
|
||||||
|
|
||||||
|
@ -53,6 +56,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
scope.cancel()
|
scope.cancel()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewToken(token: String) {
|
override fun onNewToken(token: String) {
|
||||||
Timber.tag(loggerTag.value).d("New Firebase token")
|
Timber.tag(loggerTag.value).d("New Firebase token")
|
||||||
fcmHelper.storeFcmToken(token)
|
fcmHelper.storeFcmToken(token)
|
||||||
|
@ -62,7 +66,13 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
unifiedPushHelper.isEmbeddedDistributor()
|
unifiedPushHelper.isEmbeddedDistributor()
|
||||||
) {
|
) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
pushersManager.enqueueRegisterPusher(token, getString(R.string.pusher_http_url))
|
pushersManager.enqueueRegisterPusher(
|
||||||
|
pushKey = token,
|
||||||
|
gateway = mdmService.getData(
|
||||||
|
mdmData = MdmData.DefaultPushGatewayUrl,
|
||||||
|
defaultValue = getString(R.string.pusher_http_url),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
tools:ignore="UnusedAttribute"
|
tools:ignore="UnusedAttribute"
|
||||||
tools:replace="android:allowBackup">
|
tools:replace="android:allowBackup">
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.content.APP_RESTRICTIONS"
|
||||||
|
android:resource="@xml/vector_app_restrictions" />
|
||||||
|
|
||||||
<!-- Activity alias for the launcher Activity (must be declared after the Activity it targets) -->
|
<!-- Activity alias for the launcher Activity (must be declared after the Activity it targets) -->
|
||||||
<!-- exported="true" is required to launch application -->
|
<!-- exported="true" is required to launch application -->
|
||||||
<activity-alias
|
<activity-alias
|
||||||
|
|
|
@ -108,6 +108,7 @@ class VectorApplication :
|
||||||
@Inject lateinit var buildMeta: BuildMeta
|
@Inject lateinit var buildMeta: BuildMeta
|
||||||
@Inject lateinit var leakDetector: LeakDetector
|
@Inject lateinit var leakDetector: LeakDetector
|
||||||
@Inject lateinit var vectorLocale: VectorLocale
|
@Inject lateinit var vectorLocale: VectorLocale
|
||||||
|
@Inject lateinit var webRtcCallManager: WebRtcCallManager
|
||||||
|
|
||||||
// font thread handler
|
// font thread handler
|
||||||
private var fontThreadHandler: Handler? = null
|
private var fontThreadHandler: Handler? = null
|
||||||
|
@ -167,20 +168,37 @@ class VectorApplication :
|
||||||
notificationUtils.createNotificationChannels()
|
notificationUtils.createNotificationChannels()
|
||||||
|
|
||||||
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
|
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||||
|
private var stopBackgroundSync = false
|
||||||
|
|
||||||
override fun onResume(owner: LifecycleOwner) {
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
Timber.i("App entered foreground")
|
Timber.i("App entered foreground")
|
||||||
fcmHelper.onEnterForeground(activeSessionHolder)
|
fcmHelper.onEnterForeground(activeSessionHolder)
|
||||||
activeSessionHolder.getSafeActiveSessionAsync {
|
if (webRtcCallManager.currentCall.get() == null) {
|
||||||
it?.syncService()?.stopAnyBackgroundSync()
|
Timber.i("App entered foreground and no active call: stop any background sync")
|
||||||
|
activeSessionHolder.getSafeActiveSessionAsync {
|
||||||
|
it?.syncService()?.stopAnyBackgroundSync()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Timber.i("App entered foreground: there is an active call, set stopBackgroundSync to true")
|
||||||
|
stopBackgroundSync = true
|
||||||
}
|
}
|
||||||
// activeSessionHolder.getSafeActiveSession()?.also {
|
|
||||||
// it.syncService().stopAnyBackgroundSync()
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause(owner: LifecycleOwner) {
|
override fun onPause(owner: LifecycleOwner) {
|
||||||
Timber.i("App entered background")
|
Timber.i("App entered background")
|
||||||
fcmHelper.onEnterBackground(activeSessionHolder)
|
fcmHelper.onEnterBackground(activeSessionHolder)
|
||||||
|
|
||||||
|
if (stopBackgroundSync) {
|
||||||
|
if (webRtcCallManager.currentCall.get() == null) {
|
||||||
|
Timber.i("App entered background: stop any background sync")
|
||||||
|
activeSessionHolder.getSafeActiveSessionAsync {
|
||||||
|
it?.syncService()?.stopAnyBackgroundSync()
|
||||||
|
}
|
||||||
|
stopBackgroundSync = false
|
||||||
|
} else {
|
||||||
|
Timber.i("App entered background: there is an active call do not stop background sync")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
ProcessLifecycleOwner.get().lifecycle.addObserver(spaceStateHandler)
|
ProcessLifecycleOwner.get().lifecycle.addObserver(spaceStateHandler)
|
||||||
|
|
|
@ -50,6 +50,9 @@ import im.vector.app.features.analytics.metrics.VectorPlugins
|
||||||
import im.vector.app.features.configuration.VectorCustomEventTypesProvider
|
import im.vector.app.features.configuration.VectorCustomEventTypesProvider
|
||||||
import im.vector.app.features.invite.AutoAcceptInvites
|
import im.vector.app.features.invite.AutoAcceptInvites
|
||||||
import im.vector.app.features.invite.CompileTimeAutoAcceptInvites
|
import im.vector.app.features.invite.CompileTimeAutoAcceptInvites
|
||||||
|
import im.vector.app.features.mdm.DefaultMdmService
|
||||||
|
import im.vector.app.features.mdm.MdmData
|
||||||
|
import im.vector.app.features.mdm.MdmService
|
||||||
import im.vector.app.features.navigation.DefaultNavigator
|
import im.vector.app.features.navigation.DefaultNavigator
|
||||||
import im.vector.app.features.navigation.Navigator
|
import im.vector.app.features.navigation.Navigator
|
||||||
import im.vector.app.features.pin.PinCodeStore
|
import im.vector.app.features.pin.PinCodeStore
|
||||||
|
@ -108,6 +111,9 @@ import javax.inject.Singleton
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindEmojiSpanify(emojiCompatWrapper: EmojiCompatWrapper): EmojiSpanify
|
abstract fun bindEmojiSpanify(emojiCompatWrapper: EmojiCompatWrapper): EmojiSpanify
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindMdmService(service: DefaultMdmService): MdmService
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindFontScale(fontScale: FontScalePreferencesImpl): FontScalePreferences
|
abstract fun bindFontScale(fontScale: FontScalePreferencesImpl): FontScalePreferences
|
||||||
|
|
||||||
|
@ -145,6 +151,7 @@ import javax.inject.Singleton
|
||||||
flipperProxy: FlipperProxy,
|
flipperProxy: FlipperProxy,
|
||||||
vectorPlugins: VectorPlugins,
|
vectorPlugins: VectorPlugins,
|
||||||
vectorCustomEventTypesProvider: VectorCustomEventTypesProvider,
|
vectorCustomEventTypesProvider: VectorCustomEventTypesProvider,
|
||||||
|
mdmService: MdmService,
|
||||||
): MatrixConfiguration {
|
): MatrixConfiguration {
|
||||||
return MatrixConfiguration(
|
return MatrixConfiguration(
|
||||||
applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION,
|
applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION,
|
||||||
|
@ -156,6 +163,7 @@ import javax.inject.Singleton
|
||||||
metricPlugins = vectorPlugins.plugins(),
|
metricPlugins = vectorPlugins.plugins(),
|
||||||
cryptoAnalyticsPlugin = vectorPlugins.cryptoMetricPlugin,
|
cryptoAnalyticsPlugin = vectorPlugins.cryptoMetricPlugin,
|
||||||
customEventTypesProvider = vectorCustomEventTypesProvider,
|
customEventTypesProvider = vectorCustomEventTypesProvider,
|
||||||
|
clientPermalinkBaseUrl = mdmService.getData(MdmData.PermalinkBaseUrl),
|
||||||
syncConfig = SyncConfig(
|
syncConfig = SyncConfig(
|
||||||
syncFilterParams = SyncFilterParams(lazyLoadMembersForStateEvents = true, useThreadNotifications = true)
|
syncFilterParams = SyncFilterParams(lazyLoadMembersForStateEvents = true, useThreadNotifications = true)
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,4 +2,8 @@
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- The https://github.com/LikeTheSalad/android-stem requires a non empty strings.xml -->
|
<!-- The https://github.com/LikeTheSalad/android-stem requires a non empty strings.xml -->
|
||||||
<string name="ignored_placeholder" tools:ignore="UnusedResources">ignored</string>
|
<string name="ignored_placeholder" tools:ignore="UnusedResources">ignored</string>
|
||||||
|
|
||||||
|
<string name="restriction_default_homeserver_url_title">Default homeserver URL</string>
|
||||||
|
<string name="restriction_default_push_gateway_title">Default Push gateway</string>
|
||||||
|
<string name="restriction_permalink_base_url_title">Permalink base url</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<restriction
|
||||||
|
android:key="im.vector.app.serverConfigDefaultHomeserverUrlString"
|
||||||
|
android:restrictionType="string"
|
||||||
|
android:title="@string/restriction_default_homeserver_url_title" />
|
||||||
|
|
||||||
|
<restriction
|
||||||
|
android:key="im.vector.app.serverConfigSygnalAPIUrlString"
|
||||||
|
android:restrictionType="string"
|
||||||
|
android:title="@string/restriction_default_push_gateway_title" />
|
||||||
|
|
||||||
|
<restriction
|
||||||
|
android:key="im.vector.app.clientPermalinkBaseUrl"
|
||||||
|
android:restrictionType="string"
|
||||||
|
android:title="@string/restriction_permalink_base_url_title" />
|
||||||
|
|
||||||
|
</restrictions>
|
|
@ -42,6 +42,12 @@ object Config {
|
||||||
const val ENABLE_LOCATION_SHARING = true
|
const val ENABLE_LOCATION_SHARING = true
|
||||||
const val LOCATION_MAP_TILER_KEY = "fU3vlMsMn4Jb6dnEIFsx"
|
const val LOCATION_MAP_TILER_KEY = "fU3vlMsMn4Jb6dnEIFsx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to read the `io.element.functional_members` state event
|
||||||
|
* and exclude any service members when computing a room's name and avatar.
|
||||||
|
*/
|
||||||
|
const val SUPPORT_FUNCTIONAL_MEMBERS = true
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum length of voice messages in milliseconds.
|
* The maximum length of voice messages in milliseconds.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -76,6 +76,7 @@ import im.vector.app.features.analytics.AnalyticsTracker
|
||||||
import im.vector.app.features.analytics.plan.MobileScreen
|
import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
import im.vector.app.features.configuration.VectorConfiguration
|
import im.vector.app.features.configuration.VectorConfiguration
|
||||||
import im.vector.app.features.consent.ConsentNotGivenHelper
|
import im.vector.app.features.consent.ConsentNotGivenHelper
|
||||||
|
import im.vector.app.features.mdm.MdmService
|
||||||
import im.vector.app.features.navigation.Navigator
|
import im.vector.app.features.navigation.Navigator
|
||||||
import im.vector.app.features.pin.PinLocker
|
import im.vector.app.features.pin.PinLocker
|
||||||
import im.vector.app.features.pin.PinMode
|
import im.vector.app.features.pin.PinMode
|
||||||
|
@ -171,6 +172,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
||||||
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||||
@Inject lateinit var vectorPreferences: VectorPreferences
|
@Inject lateinit var vectorPreferences: VectorPreferences
|
||||||
@Inject lateinit var errorFormatter: ErrorFormatter
|
@Inject lateinit var errorFormatter: ErrorFormatter
|
||||||
|
@Inject lateinit var mdmService: MdmService
|
||||||
|
|
||||||
// For debug only
|
// For debug only
|
||||||
@Inject lateinit var debugReceiver: DebugReceiver
|
@Inject lateinit var debugReceiver: DebugReceiver
|
||||||
|
@ -412,6 +414,10 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
||||||
rageShake.start()
|
rageShake.start()
|
||||||
}
|
}
|
||||||
debugReceiver.register(this)
|
debugReceiver.register(this)
|
||||||
|
mdmService.registerListener(this) {
|
||||||
|
// Just log that a change occurred.
|
||||||
|
Timber.w("MDM data has been updated")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val postResumeScheduledActions = mutableListOf<() -> Unit>()
|
private val postResumeScheduledActions = mutableListOf<() -> Unit>()
|
||||||
|
@ -442,6 +448,7 @@ abstract class VectorBaseActivity<VB : ViewBinding> : AppCompatActivity(), Maver
|
||||||
|
|
||||||
rageShake.stop()
|
rageShake.stop()
|
||||||
debugReceiver.unregister(this)
|
debugReceiver.unregister(this)
|
||||||
|
mdmService.unregisterListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
|
|
|
@ -22,6 +22,8 @@ import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.resources.AppNameProvider
|
import im.vector.app.core.resources.AppNameProvider
|
||||||
import im.vector.app.core.resources.LocaleProvider
|
import im.vector.app.core.resources.LocaleProvider
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import im.vector.app.features.mdm.MdmData
|
||||||
|
import im.vector.app.features.mdm.MdmService
|
||||||
import org.matrix.android.sdk.api.session.pushers.HttpPusher
|
import org.matrix.android.sdk.api.session.pushers.HttpPusher
|
||||||
import org.matrix.android.sdk.api.session.pushers.Pusher
|
import org.matrix.android.sdk.api.session.pushers.Pusher
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
@ -37,6 +39,7 @@ class PushersManager @Inject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val appNameProvider: AppNameProvider,
|
private val appNameProvider: AppNameProvider,
|
||||||
private val getDeviceInfoUseCase: GetDeviceInfoUseCase,
|
private val getDeviceInfoUseCase: GetDeviceInfoUseCase,
|
||||||
|
private val mdmService: MdmService,
|
||||||
) {
|
) {
|
||||||
suspend fun testPush() {
|
suspend fun testPush() {
|
||||||
val currentSession = activeSessionHolder.getActiveSession()
|
val currentSession = activeSessionHolder.getActiveSession()
|
||||||
|
@ -50,7 +53,10 @@ class PushersManager @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun enqueueRegisterPusherWithFcmKey(pushKey: String): UUID {
|
suspend fun enqueueRegisterPusherWithFcmKey(pushKey: String): UUID {
|
||||||
return enqueueRegisterPusher(pushKey, stringProvider.getString(R.string.pusher_http_url))
|
return enqueueRegisterPusher(
|
||||||
|
pushKey = pushKey,
|
||||||
|
gateway = mdmService.getData(MdmData.DefaultPushGatewayUrl, stringProvider.getString(R.string.pusher_http_url))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun enqueueRegisterPusher(
|
suspend fun enqueueRegisterPusher(
|
||||||
|
|
|
@ -24,6 +24,8 @@ import com.squareup.moshi.JsonClass
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.utils.getApplicationLabel
|
import im.vector.app.core.utils.getApplicationLabel
|
||||||
|
import im.vector.app.features.mdm.MdmData
|
||||||
|
import im.vector.app.features.mdm.MdmService
|
||||||
import org.matrix.android.sdk.api.Matrix
|
import org.matrix.android.sdk.api.Matrix
|
||||||
import org.matrix.android.sdk.api.cache.CacheStrategy
|
import org.matrix.android.sdk.api.cache.CacheStrategy
|
||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
|
@ -40,6 +42,7 @@ class UnifiedPushHelper @Inject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val matrix: Matrix,
|
private val matrix: Matrix,
|
||||||
private val fcmHelper: FcmHelper,
|
private val fcmHelper: FcmHelper,
|
||||||
|
private val mdmService: MdmService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@MainThread
|
@MainThread
|
||||||
|
@ -99,7 +102,12 @@ class UnifiedPushHelper @Inject constructor(
|
||||||
// register app_id type upfcm on sygnal
|
// register app_id type upfcm on sygnal
|
||||||
// the pushkey if FCM key
|
// the pushkey if FCM key
|
||||||
if (UnifiedPush.getDistributor(context) == context.packageName) {
|
if (UnifiedPush.getDistributor(context) == context.packageName) {
|
||||||
unifiedPushStore.storePushGateway(stringProvider.getString(R.string.pusher_http_url))
|
unifiedPushStore.storePushGateway(
|
||||||
|
gateway = mdmService.getData(
|
||||||
|
mdmData = MdmData.DefaultPushGatewayUrl,
|
||||||
|
defaultValue = stringProvider.getString(R.string.pusher_http_url),
|
||||||
|
)
|
||||||
|
)
|
||||||
onDoneRunnable?.run()
|
onDoneRunnable?.run()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -185,7 +193,13 @@ class UnifiedPushHelper @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPushGateway(): String? {
|
fun getPushGateway(): String? {
|
||||||
return if (isEmbeddedDistributor()) stringProvider.getString(R.string.pusher_http_url)
|
return if (isEmbeddedDistributor()) {
|
||||||
else unifiedPushStore.getPushGateway()
|
mdmService.getData(
|
||||||
|
mdmData = MdmData.DefaultPushGatewayUrl,
|
||||||
|
defaultValue = stringProvider.getString(R.string.pusher_http_url),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
unifiedPushStore.getPushGateway()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,7 @@ class WebRtcCallManager @Inject constructor(
|
||||||
private val rootEglBase by lazy { EglUtils.rootEglBase }
|
private val rootEglBase by lazy { EglUtils.rootEglBase }
|
||||||
|
|
||||||
private var isInBackground: Boolean = true
|
private var isInBackground: Boolean = true
|
||||||
|
private var syncStartedWhenInBackground: Boolean = false
|
||||||
|
|
||||||
override fun onResume(owner: LifecycleOwner) {
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
isInBackground = false
|
isInBackground = false
|
||||||
|
@ -274,13 +275,15 @@ class WebRtcCallManager @Inject constructor(
|
||||||
peerConnectionFactory = null
|
peerConnectionFactory = null
|
||||||
audioManager.setMode(CallAudioManager.Mode.DEFAULT)
|
audioManager.setMode(CallAudioManager.Mode.DEFAULT)
|
||||||
// did we start background sync? so we should stop it
|
// did we start background sync? so we should stop it
|
||||||
if (isInBackground) {
|
if (syncStartedWhenInBackground) {
|
||||||
if (!unifiedPushHelper.isBackgroundSync()) {
|
if (!unifiedPushHelper.isBackgroundSync()) {
|
||||||
|
Timber.tag(loggerTag.value).v("Sync started when in background, stop it")
|
||||||
currentSession?.syncService()?.stopAnyBackgroundSync()
|
currentSession?.syncService()?.stopAnyBackgroundSync()
|
||||||
} else {
|
} else {
|
||||||
// for fdroid we should not stop, it should continue syncing
|
// for fdroid we should not stop, it should continue syncing
|
||||||
// maybe we should restore default timeout/delay though?
|
// maybe we should restore default timeout/delay though?
|
||||||
}
|
}
|
||||||
|
syncStartedWhenInBackground = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,6 +386,7 @@ class WebRtcCallManager @Inject constructor(
|
||||||
if (isInBackground) {
|
if (isInBackground) {
|
||||||
if (!unifiedPushHelper.isBackgroundSync()) {
|
if (!unifiedPushHelper.isBackgroundSync()) {
|
||||||
// only for push version as fdroid version is already doing it?
|
// only for push version as fdroid version is already doing it?
|
||||||
|
syncStartedWhenInBackground = true
|
||||||
currentSession?.syncService()?.startAutomaticBackgroundSync(30, 0)
|
currentSession?.syncService()?.startAutomaticBackgroundSync(30, 0)
|
||||||
} else {
|
} else {
|
||||||
// Maybe increase sync freq? but how to set back to default values?
|
// Maybe increase sync freq? but how to set back to default values?
|
||||||
|
|
|
@ -370,10 +370,6 @@ class MessageActionsViewModel @AssistedInject constructor(
|
||||||
add(EventSharedAction.ViewReactions(informationData))
|
add(EventSharedAction.ViewReactions(informationData))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canQuote(timelineEvent, messageContent, actionPermissions)) {
|
|
||||||
add(EventSharedAction.Quote(eventId))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timelineEvent.hasBeenEdited()) {
|
if (timelineEvent.hasBeenEdited()) {
|
||||||
add(EventSharedAction.ViewEditHistory(informationData))
|
add(EventSharedAction.ViewEditHistory(informationData))
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,8 +85,13 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
|
||||||
}
|
}
|
||||||
holder.previewUrlView.delegate = previewUrlCallback
|
holder.previewUrlView.delegate = previewUrlCallback
|
||||||
holder.previewUrlView.renderMessageLayout(attributes.informationData.messageLayout)
|
holder.previewUrlView.renderMessageLayout(attributes.informationData.messageLayout)
|
||||||
|
if (useRichTextEditorStyle) {
|
||||||
val messageView: AppCompatTextView = if (useRichTextEditorStyle) holder.richMessageView else holder.plainMessageView
|
holder.plainMessageView?.isVisible = false
|
||||||
|
} else {
|
||||||
|
holder.richMessageView?.isVisible = false
|
||||||
|
}
|
||||||
|
val messageView: AppCompatTextView = if (useRichTextEditorStyle) holder.requireRichMessageView() else holder.requirePlainMessageView()
|
||||||
|
messageView.isVisible = true
|
||||||
if (useBigFont) {
|
if (useBigFont) {
|
||||||
messageView.textSize = 44F
|
messageView.textSize = 44F
|
||||||
} else {
|
} else {
|
||||||
|
@ -133,11 +138,21 @@ abstract class MessageTextItem : AbsMessageItem<MessageTextItem.Holder>() {
|
||||||
val previewUrlView by bind<PreviewUrlView>(R.id.messageUrlPreview)
|
val previewUrlView by bind<PreviewUrlView>(R.id.messageUrlPreview)
|
||||||
private val richMessageStub by bind<ViewStub>(R.id.richMessageTextViewStub)
|
private val richMessageStub by bind<ViewStub>(R.id.richMessageTextViewStub)
|
||||||
private val plainMessageStub by bind<ViewStub>(R.id.plainMessageTextViewStub)
|
private val plainMessageStub by bind<ViewStub>(R.id.plainMessageTextViewStub)
|
||||||
val richMessageView: AppCompatTextView by lazy {
|
var richMessageView: AppCompatTextView? = null
|
||||||
richMessageStub.inflate().findViewById(R.id.messageTextView)
|
private set
|
||||||
|
var plainMessageView: AppCompatTextView? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun requireRichMessageView(): AppCompatTextView {
|
||||||
|
val view = richMessageView ?: richMessageStub.inflate().findViewById(R.id.messageTextView)
|
||||||
|
richMessageView = view
|
||||||
|
return view
|
||||||
}
|
}
|
||||||
val plainMessageView: AppCompatTextView by lazy {
|
|
||||||
plainMessageStub.inflate().findViewById(R.id.messageTextView)
|
fun requirePlainMessageView(): AppCompatTextView {
|
||||||
|
val view = plainMessageView ?: plainMessageStub.inflate().findViewById(R.id.messageTextView)
|
||||||
|
plainMessageView = view
|
||||||
|
return view
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object to store and retrieve home and identity server urls.
|
* Object to store and retrieve home and identity server urls.
|
||||||
|
* Note: this class is not used.
|
||||||
*/
|
*/
|
||||||
class ServerUrlsRepository @Inject constructor(
|
class ServerUrlsRepository @Inject constructor(
|
||||||
@DefaultPreferences
|
@DefaultPreferences
|
||||||
|
@ -89,5 +90,5 @@ class ServerUrlsRepository @Inject constructor(
|
||||||
/**
|
/**
|
||||||
* Return default homeserver url from resources.
|
* Return default homeserver url from resources.
|
||||||
*/
|
*/
|
||||||
fun getDefaultHomeServerUrl() = stringProvider.getString(R.string.matrix_org_server_url)
|
private fun getDefaultHomeServerUrl() = stringProvider.getString(R.string.matrix_org_server_url)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.features.mdm
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.content.RestrictionsManager
|
||||||
|
import androidx.core.content.getSystemService
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class DefaultMdmService @Inject constructor(
|
||||||
|
@ApplicationContext applicationContext: Context
|
||||||
|
) : MdmService {
|
||||||
|
private val restrictionsManager = applicationContext.getSystemService<RestrictionsManager>()
|
||||||
|
private var onChangedListener: (() -> Unit)? = null
|
||||||
|
|
||||||
|
private val restrictionsReceiver = object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
Timber.w("Restrictions changed")
|
||||||
|
onChangedListener?.invoke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerListener(context: Context, onChangedListener: () -> Unit) {
|
||||||
|
val restrictionsFilter = IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED)
|
||||||
|
this.onChangedListener = onChangedListener
|
||||||
|
context.registerReceiver(restrictionsReceiver, restrictionsFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterListener(context: Context) {
|
||||||
|
context.unregisterReceiver(restrictionsReceiver)
|
||||||
|
this.onChangedListener = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getData(mdmData: MdmData): String? {
|
||||||
|
return restrictionsManager?.applicationRestrictions?.getString(mdmData.key)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.features.mdm
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
enum class MdmData(val key: String) {
|
||||||
|
DefaultHomeserverUrl(key = "im.vector.app.serverConfigDefaultHomeserverUrlString"),
|
||||||
|
DefaultPushGatewayUrl(key = "im.vector.app.serverConfigSygnalAPIUrlString"),
|
||||||
|
PermalinkBaseUrl(key = "im.vector.app.clientPermalinkBaseUrl"),
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MdmService {
|
||||||
|
fun registerListener(context: Context, onChangedListener: () -> Unit)
|
||||||
|
fun unregisterListener(context: Context)
|
||||||
|
fun getData(mdmData: MdmData): String?
|
||||||
|
fun getData(mdmData: MdmData, defaultValue: String): String {
|
||||||
|
return getData(mdmData)
|
||||||
|
?.also {
|
||||||
|
Timber.w("Using MDM data for ${mdmData.name}: $it")
|
||||||
|
}
|
||||||
|
?: defaultValue
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,6 +46,8 @@ import im.vector.app.features.login.LoginMode
|
||||||
import im.vector.app.features.login.ReAuthHelper
|
import im.vector.app.features.login.ReAuthHelper
|
||||||
import im.vector.app.features.login.ServerType
|
import im.vector.app.features.login.ServerType
|
||||||
import im.vector.app.features.login.SignMode
|
import im.vector.app.features.login.SignMode
|
||||||
|
import im.vector.app.features.mdm.MdmData
|
||||||
|
import im.vector.app.features.mdm.MdmService
|
||||||
import im.vector.app.features.onboarding.OnboardingAction.AuthenticateAction
|
import im.vector.app.features.onboarding.OnboardingAction.AuthenticateAction
|
||||||
import im.vector.app.features.onboarding.StartAuthenticationFlowUseCase.StartAuthenticationResult
|
import im.vector.app.features.onboarding.StartAuthenticationFlowUseCase.StartAuthenticationResult
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
@ -93,6 +95,7 @@ class OnboardingViewModel @AssistedInject constructor(
|
||||||
private val registrationActionHandler: RegistrationActionHandler,
|
private val registrationActionHandler: RegistrationActionHandler,
|
||||||
private val sdkIntProvider: BuildVersionSdkIntProvider,
|
private val sdkIntProvider: BuildVersionSdkIntProvider,
|
||||||
private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase,
|
private val configureAndStartSessionUseCase: ConfigureAndStartSessionUseCase,
|
||||||
|
mdmService: MdmService,
|
||||||
) : VectorViewModel<OnboardingViewState, OnboardingAction, OnboardingViewEvents>(initialState) {
|
) : VectorViewModel<OnboardingViewState, OnboardingAction, OnboardingViewEvents>(initialState) {
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
|
@ -143,7 +146,7 @@ class OnboardingViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
|
private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash()
|
||||||
private val defaultHomeserverUrl = matrixOrgUrl
|
private val defaultHomeserverUrl = mdmService.getData(MdmData.DefaultHomeserverUrl, matrixOrgUrl)
|
||||||
|
|
||||||
private val registrationWizard: RegistrationWizard
|
private val registrationWizard: RegistrationWizard
|
||||||
get() = authenticationService.getRegistrationWizard()
|
get() = authenticationService.getRegistrationWizard()
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.features.room
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
import org.matrix.android.sdk.api.session.room.state.StateService
|
||||||
|
|
||||||
|
private const val FUNCTIONAL_MEMBERS_STATE_EVENT_TYPE = "io.element.functional_members"
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class FunctionalMembersContent(
|
||||||
|
@Json(name = "service_members") val userIds: List<String>? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
fun StateService.getFunctionalMembers(): List<String> {
|
||||||
|
return getStateEvent(FUNCTIONAL_MEMBERS_STATE_EVENT_TYPE, QueryStringValue.IsEmpty)
|
||||||
|
?.content
|
||||||
|
?.toModel<FunctionalMembersContent>()
|
||||||
|
?.userIds
|
||||||
|
.orEmpty()
|
||||||
|
}
|
|
@ -18,13 +18,28 @@ package im.vector.app.features.room
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
import im.vector.app.config.Config
|
||||||
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider
|
import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider
|
||||||
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Provider
|
||||||
|
|
||||||
class VectorRoomDisplayNameFallbackProvider @Inject constructor(
|
class VectorRoomDisplayNameFallbackProvider @Inject constructor(
|
||||||
private val context: Context
|
private val context: Context,
|
||||||
|
private val activeSessionHolder: Provider<ActiveSessionHolder>,
|
||||||
) : RoomDisplayNameFallbackProvider {
|
) : RoomDisplayNameFallbackProvider {
|
||||||
|
|
||||||
|
override fun excludedUserIds(roomId: String): List<String> {
|
||||||
|
if (!Config.SUPPORT_FUNCTIONAL_MEMBERS) return emptyList()
|
||||||
|
return activeSessionHolder.get()
|
||||||
|
.getSafeActiveSession()
|
||||||
|
?.getRoom(roomId)
|
||||||
|
?.stateService()
|
||||||
|
?.getFunctionalMembers()
|
||||||
|
.orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
override fun getNameForRoomInvite(): String {
|
override fun getNameForRoomInvite(): String {
|
||||||
return context.getString(R.string.room_displayname_room_invite)
|
return context.getString(R.string.room_displayname_room_invite)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package im.vector.app.core.pushers
|
package im.vector.app.core.pushers
|
||||||
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
import im.vector.app.features.mdm.NoOpMdmService
|
||||||
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
||||||
import im.vector.app.test.fakes.FakeAppNameProvider
|
import im.vector.app.test.fakes.FakeAppNameProvider
|
||||||
import im.vector.app.test.fakes.FakeGetDeviceInfoUseCase
|
import im.vector.app.test.fakes.FakeGetDeviceInfoUseCase
|
||||||
|
@ -54,6 +55,7 @@ class PushersManagerTest {
|
||||||
stringProvider.instance,
|
stringProvider.instance,
|
||||||
appNameProvider,
|
appNameProvider,
|
||||||
getDeviceInfoUseCase,
|
getDeviceInfoUseCase,
|
||||||
|
NoOpMdmService(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.features.mdm
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
class NoOpMdmService : MdmService {
|
||||||
|
override fun registerListener(context: Context, onChangedListener: () -> Unit) = Unit
|
||||||
|
override fun unregisterListener(context: Context) = Unit
|
||||||
|
override fun getData(mdmData: MdmData): String? = null
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import im.vector.app.features.login.LoginMode
|
||||||
import im.vector.app.features.login.ReAuthHelper
|
import im.vector.app.features.login.ReAuthHelper
|
||||||
import im.vector.app.features.login.ServerType
|
import im.vector.app.features.login.ServerType
|
||||||
import im.vector.app.features.login.SignMode
|
import im.vector.app.features.login.SignMode
|
||||||
|
import im.vector.app.features.mdm.NoOpMdmService
|
||||||
import im.vector.app.features.onboarding.RegistrationStateFixture.aRegistrationState
|
import im.vector.app.features.onboarding.RegistrationStateFixture.aRegistrationState
|
||||||
import im.vector.app.features.onboarding.StartAuthenticationFlowUseCase.StartAuthenticationResult
|
import im.vector.app.features.onboarding.StartAuthenticationFlowUseCase.StartAuthenticationResult
|
||||||
import im.vector.app.test.TestBuildVersionSdkIntProvider
|
import im.vector.app.test.TestBuildVersionSdkIntProvider
|
||||||
|
@ -1121,6 +1122,7 @@ class OnboardingViewModelTest {
|
||||||
fakeRegistrationActionHandler.instance,
|
fakeRegistrationActionHandler.instance,
|
||||||
TestBuildVersionSdkIntProvider().also { it.value = Build.VERSION_CODES.O },
|
TestBuildVersionSdkIntProvider().also { it.value = Build.VERSION_CODES.O },
|
||||||
fakeConfigureAndStartSessionUseCase,
|
fakeConfigureAndStartSessionUseCase,
|
||||||
|
NoOpMdmService()
|
||||||
).also {
|
).also {
|
||||||
viewModel = it
|
viewModel = it
|
||||||
initialState = state
|
initialState = state
|
||||||
|
|
Loading…
Reference in New Issue