commit
3c682430d9
@ -5,7 +5,7 @@ Features ✨:
|
|||||||
-
|
-
|
||||||
|
|
||||||
Improvements 🙌:
|
Improvements 🙌:
|
||||||
-
|
- Render events m.room.encryption and m.room.guest_access in the timeline
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
-
|
||||||
@ -17,7 +17,7 @@ Translations 🗣:
|
|||||||
-
|
-
|
||||||
|
|
||||||
Build 🧱:
|
Build 🧱:
|
||||||
-
|
- Change the way versionCode is computed (#827)
|
||||||
|
|
||||||
Changes in RiotX 0.12.0 (2020-01-09)
|
Changes in RiotX 0.12.0 (2020-01-09)
|
||||||
===================================================
|
===================================================
|
||||||
|
@ -91,7 +91,8 @@ object EventType {
|
|||||||
STATE_ROOM_CANONICAL_ALIAS,
|
STATE_ROOM_CANONICAL_ALIAS,
|
||||||
STATE_ROOM_HISTORY_VISIBILITY,
|
STATE_ROOM_HISTORY_VISIBILITY,
|
||||||
STATE_ROOM_RELATED_GROUPS,
|
STATE_ROOM_RELATED_GROUPS,
|
||||||
STATE_ROOM_PINNED_EVENT
|
STATE_ROOM_PINNED_EVENT,
|
||||||
|
STATE_ROOM_ENCRYPTION
|
||||||
)
|
)
|
||||||
|
|
||||||
fun isStateEvent(type: String): Boolean {
|
fun isStateEvent(type: String): Boolean {
|
||||||
|
@ -28,17 +28,20 @@ fun roomMemberQueryParams(init: (RoomMemberQueryParams.Builder.() -> Unit) = {})
|
|||||||
*/
|
*/
|
||||||
data class RoomMemberQueryParams(
|
data class RoomMemberQueryParams(
|
||||||
val displayName: QueryStringValue,
|
val displayName: QueryStringValue,
|
||||||
val memberships: List<Membership>
|
val memberships: List<Membership>,
|
||||||
|
val excludeSelf: Boolean
|
||||||
) {
|
) {
|
||||||
|
|
||||||
class Builder {
|
class Builder {
|
||||||
|
|
||||||
var displayName: QueryStringValue = QueryStringValue.IsNotEmpty
|
var displayName: QueryStringValue = QueryStringValue.IsNotEmpty
|
||||||
var memberships: List<Membership> = Membership.all()
|
var memberships: List<Membership> = Membership.all()
|
||||||
|
var excludeSelf: Boolean = false
|
||||||
|
|
||||||
fun build() = RoomMemberQueryParams(
|
fun build() = RoomMemberQueryParams(
|
||||||
displayName = displayName,
|
displayName = displayName,
|
||||||
memberships = memberships
|
memberships = memberships,
|
||||||
|
excludeSelf = excludeSelf
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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.matrix.android.api.session.room.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing the EventType.STATE_ROOM_GUEST_ACCESS state event content
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/latest#m-room-guest-access
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class RoomGuestAccessContent(
|
||||||
|
// Required. Whether guests can join the room. One of: ["can_join", "forbidden"]
|
||||||
|
@Json(name = "guest_access") val guestAccess: GuestAccess? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class GuestAccess(val value: String) {
|
||||||
|
@Json(name = "can_join")
|
||||||
|
CanJoin("can_join"),
|
||||||
|
@Json(name = "forbidden")
|
||||||
|
Forbidden("forbidden")
|
||||||
|
}
|
@ -28,6 +28,8 @@ import im.vector.matrix.android.api.session.room.model.PowerLevels
|
|||||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||||
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
||||||
|
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameter to create a room, with facilities functions to configure it
|
* Parameter to create a room, with facilities functions to configure it
|
||||||
@ -88,7 +90,7 @@ class CreateRoomParams {
|
|||||||
* A list of state events to set in the new room.
|
* A list of state events to set in the new room.
|
||||||
* This allows the user to override the default state events set in the new room.
|
* This allows the user to override the default state events set in the new room.
|
||||||
* The expected format of the state events are an object with type, state_key and content keys set.
|
* The expected format of the state events are an object with type, state_key and content keys set.
|
||||||
* Takes precedence over events set by presets, but gets overriden by name and topic keys.
|
* Takes precedence over events set by presets, but gets overridden by name and topic keys.
|
||||||
*/
|
*/
|
||||||
@Json(name = "initial_state")
|
@Json(name = "initial_state")
|
||||||
var initialStates: MutableList<Event>? = null
|
var initialStates: MutableList<Event>? = null
|
||||||
@ -120,12 +122,12 @@ class CreateRoomParams {
|
|||||||
*
|
*
|
||||||
* @param algorithm the algorithm
|
* @param algorithm the algorithm
|
||||||
*/
|
*/
|
||||||
fun addCryptoAlgorithm(algorithm: String) {
|
fun enableEncryptionWithAlgorithm(algorithm: String) {
|
||||||
if (algorithm.isNotBlank()) {
|
if (algorithm == MXCRYPTO_ALGORITHM_MEGOLM) {
|
||||||
val contentMap = HashMap<String, String>()
|
val contentMap = mapOf("algorithm" to algorithm)
|
||||||
contentMap["algorithm"] = algorithm
|
|
||||||
|
|
||||||
val algoEvent = Event(type = EventType.STATE_ROOM_ENCRYPTION,
|
val algoEvent = Event(
|
||||||
|
type = EventType.STATE_ROOM_ENCRYPTION,
|
||||||
stateKey = "",
|
stateKey = "",
|
||||||
content = contentMap.toContent()
|
content = contentMap.toContent()
|
||||||
)
|
)
|
||||||
@ -135,6 +137,8 @@ class CreateRoomParams {
|
|||||||
} else {
|
} else {
|
||||||
initialStates!!.add(algoEvent)
|
initialStates!!.add(algoEvent)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Timber.e("Unsupported algorithm: $algorithm")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +149,13 @@ class CreateRoomParams {
|
|||||||
*/
|
*/
|
||||||
fun setHistoryVisibility(historyVisibility: RoomHistoryVisibility?) {
|
fun setHistoryVisibility(historyVisibility: RoomHistoryVisibility?) {
|
||||||
// Remove the existing value if any.
|
// Remove the existing value if any.
|
||||||
initialStates?.removeAll { it.getClearType() == EventType.STATE_ROOM_HISTORY_VISIBILITY }
|
initialStates?.removeAll { it.type == EventType.STATE_ROOM_HISTORY_VISIBILITY }
|
||||||
|
|
||||||
if (historyVisibility != null) {
|
if (historyVisibility != null) {
|
||||||
val contentMap = HashMap<String, RoomHistoryVisibility>()
|
val contentMap = mapOf("history_visibility" to historyVisibility)
|
||||||
contentMap["history_visibility"] = historyVisibility
|
|
||||||
|
|
||||||
val historyVisibilityEvent = Event(type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
val historyVisibilityEvent = Event(
|
||||||
|
type = EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||||
stateKey = "",
|
stateKey = "",
|
||||||
content = contentMap.toContent())
|
content = contentMap.toContent())
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import im.vector.matrix.android.api.util.Cancelable
|
|||||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
import im.vector.matrix.android.internal.database.model.RoomMemberEntity
|
||||||
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
|
import im.vector.matrix.android.internal.database.model.RoomMemberEntityFields
|
||||||
|
import im.vector.matrix.android.internal.di.UserId
|
||||||
import im.vector.matrix.android.internal.query.process
|
import im.vector.matrix.android.internal.query.process
|
||||||
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
|
||||||
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
|
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
|
||||||
@ -39,13 +40,16 @@ import im.vector.matrix.android.internal.util.fetchCopied
|
|||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
|
|
||||||
internal class DefaultMembershipService @AssistedInject constructor(@Assisted private val roomId: String,
|
internal class DefaultMembershipService @AssistedInject constructor(
|
||||||
|
@Assisted private val roomId: String,
|
||||||
private val monarchy: Monarchy,
|
private val monarchy: Monarchy,
|
||||||
private val taskExecutor: TaskExecutor,
|
private val taskExecutor: TaskExecutor,
|
||||||
private val loadRoomMembersTask: LoadRoomMembersTask,
|
private val loadRoomMembersTask: LoadRoomMembersTask,
|
||||||
private val inviteTask: InviteTask,
|
private val inviteTask: InviteTask,
|
||||||
private val joinTask: JoinRoomTask,
|
private val joinTask: JoinRoomTask,
|
||||||
private val leaveRoomTask: LeaveRoomTask
|
private val leaveRoomTask: LeaveRoomTask,
|
||||||
|
@UserId
|
||||||
|
private val userId: String
|
||||||
) : MembershipService {
|
) : MembershipService {
|
||||||
|
|
||||||
@AssistedInject.Factory
|
@AssistedInject.Factory
|
||||||
@ -95,6 +99,11 @@ internal class DefaultMembershipService @AssistedInject constructor(@Assisted pr
|
|||||||
return RoomMembers(realm, roomId).queryRoomMembersEvent()
|
return RoomMembers(realm, roomId).queryRoomMembersEvent()
|
||||||
.process(RoomMemberEntityFields.MEMBERSHIP_STR, queryParams.memberships)
|
.process(RoomMemberEntityFields.MEMBERSHIP_STR, queryParams.memberships)
|
||||||
.process(RoomMemberEntityFields.DISPLAY_NAME, queryParams.displayName)
|
.process(RoomMemberEntityFields.DISPLAY_NAME, queryParams.displayName)
|
||||||
|
.apply {
|
||||||
|
if (queryParams.excludeSelf) {
|
||||||
|
notEqualTo(RoomMemberEntityFields.USER_ID, userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getNumberOfJoinedMembers(): Int {
|
override fun getNumberOfJoinedMembers(): Int {
|
||||||
|
@ -272,4 +272,7 @@
|
|||||||
<string name="notice_room_canonical_alias_set">"%1$s set the main address for this room to %2$s."</string>
|
<string name="notice_room_canonical_alias_set">"%1$s set the main address for this room to %2$s."</string>
|
||||||
<string name="notice_room_canonical_alias_unset">"%1$s removed the main address for this room."</string>
|
<string name="notice_room_canonical_alias_unset">"%1$s removed the main address for this room."</string>
|
||||||
|
|
||||||
|
<string name="notice_room_guest_access_can_join">"%1$s has allowed guests to join the room."</string>
|
||||||
|
<string name="notice_room_guest_access_forbidden">"%1$s has prevented guests from joining the room."</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -24,12 +24,16 @@ static def getGitTimestamp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static def generateVersionCodeFromTimestamp() {
|
static def generateVersionCodeFromTimestamp() {
|
||||||
// It's unix timestamp divided by 10: It's incremented by one every 10 seconds.
|
// It's unix timestamp, minus timestamp of October 3rd 2018 (first commit date) divided by 100: It's incremented by one every 100 seconds.
|
||||||
return (getGitTimestamp() / 10).toInteger()
|
// plus 20_000_000 for compatibility reason with the previous way the Version Code was computed
|
||||||
|
// Note that the result will be multiplied by 10 when adding the digit for the arch
|
||||||
|
return ((getGitTimestamp() - 1_538_524_800 ) / 100).toInteger() + 20_000_000
|
||||||
}
|
}
|
||||||
|
|
||||||
def generateVersionCodeFromVersionName() {
|
def generateVersionCodeFromVersionName() {
|
||||||
return versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch
|
// plus 4_000_000 for compatibility reason with the previous way the Version Code was computed
|
||||||
|
// Note that the result will be multiplied by 10 when adding the digit for the arch
|
||||||
|
return (versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch) + 4_000_000
|
||||||
}
|
}
|
||||||
|
|
||||||
def getVersionCode() {
|
def getVersionCode() {
|
||||||
@ -77,8 +81,8 @@ project.android.buildTypes.all { buildType ->
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// map for the version codes
|
// map for the version codes last digit
|
||||||
// x86 must have greater values than arm, see https://software.intel.com/en-us/android/articles/google-play-supports-cpu-architecture-filtering-for-multiple-apk
|
// x86 must have greater values than arm
|
||||||
// 64 bits have greater value than 32 bits
|
// 64 bits have greater value than 32 bits
|
||||||
ext.abiVersionCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86": 3, "x86_64": 4].withDefault { 0 }
|
ext.abiVersionCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86": 3, "x86_64": 4].withDefault { 0 }
|
||||||
|
|
||||||
@ -144,7 +148,7 @@ android {
|
|||||||
variant.outputs.each { output ->
|
variant.outputs.each { output ->
|
||||||
def baseAbiVersionCode = project.ext.abiVersionCodes.get(output.getFilter(OutputFile.ABI))
|
def baseAbiVersionCode = project.ext.abiVersionCodes.get(output.getFilter(OutputFile.ABI))
|
||||||
// Known limitation: it does not modify the value in the BuildConfig.java generated file
|
// Known limitation: it does not modify the value in the BuildConfig.java generated file
|
||||||
output.versionCodeOverride = baseAbiVersionCode * 10_000_000 + variant.versionCode
|
output.versionCodeOverride = variant.versionCode * 10 + baseAbiVersionCode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,13 @@
|
|||||||
|
|
||||||
package im.vector.riotx.core.error
|
package im.vector.riotx.core.error
|
||||||
|
|
||||||
import im.vector.riotx.BuildConfig
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* throw in debug, only log in production. As this method does not always throw, next statement should be a return
|
* throw in debug, only log in production. As this method does not always throw, next statement should be a return
|
||||||
*/
|
*/
|
||||||
fun fatalError(message: String) {
|
fun fatalError(message: String, failFast: Boolean) {
|
||||||
if (BuildConfig.DEBUG) {
|
if (failFast) {
|
||||||
error(message)
|
error(message)
|
||||||
} else {
|
} else {
|
||||||
Timber.e(message)
|
Timber.e(message)
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.riotx.core.rx
|
package im.vector.riotx.core.rx
|
||||||
|
|
||||||
import im.vector.riotx.BuildConfig
|
|
||||||
import im.vector.riotx.features.settings.VectorPreferences
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
import io.reactivex.plugins.RxJavaPlugins
|
import io.reactivex.plugins.RxJavaPlugins
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -33,8 +32,8 @@ class RxConfig @Inject constructor(
|
|||||||
RxJavaPlugins.setErrorHandler { throwable ->
|
RxJavaPlugins.setErrorHandler { throwable ->
|
||||||
Timber.e(throwable, "RxError")
|
Timber.e(throwable, "RxError")
|
||||||
|
|
||||||
// Avoid crash in production
|
// Avoid crash in production, except if user wants it
|
||||||
if (BuildConfig.DEBUG || vectorPreferences.failFast()) {
|
if (vectorPreferences.failFast()) {
|
||||||
throw throwable
|
throw throwable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
|
|||||||
QueryStringValue.Contains(query.toString(), QueryStringValue.Case.INSENSITIVE)
|
QueryStringValue.Contains(query.toString(), QueryStringValue.Case.INSENSITIVE)
|
||||||
}
|
}
|
||||||
memberships = listOf(Membership.JOIN)
|
memberships = listOf(Membership.JOIN)
|
||||||
|
excludeSelf = true
|
||||||
}
|
}
|
||||||
val members = room.getRoomMembers(queryParams)
|
val members = room.getRoomMembers(queryParams)
|
||||||
.asSequence()
|
.asSequence()
|
||||||
|
@ -55,7 +55,6 @@ import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
|||||||
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
|
||||||
import im.vector.matrix.rx.rx
|
import im.vector.matrix.rx.rx
|
||||||
import im.vector.matrix.rx.unwrap
|
import im.vector.matrix.rx.unwrap
|
||||||
import im.vector.riotx.BuildConfig
|
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.extensions.postLiveEvent
|
import im.vector.riotx.core.extensions.postLiveEvent
|
||||||
import im.vector.riotx.core.platform.VectorViewModel
|
import im.vector.riotx.core.platform.VectorViewModel
|
||||||
@ -308,7 +307,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||||||
fun isMenuItemVisible(@IdRes itemId: Int) = when (itemId) {
|
fun isMenuItemVisible(@IdRes itemId: Int) = when (itemId) {
|
||||||
R.id.clear_message_queue ->
|
R.id.clear_message_queue ->
|
||||||
/* For now always disable on production, worker cancellation is not working properly */
|
/* For now always disable on production, worker cancellation is not working properly */
|
||||||
timeline.pendingEventCount() > 0 && BuildConfig.DEBUG
|
timeline.pendingEventCount() > 0 && vectorPreferences.developerMode()
|
||||||
R.id.resend_all -> timeline.failedToDeliverEventCount() > 0
|
R.id.resend_all -> timeline.failedToDeliverEventCount() > 0
|
||||||
R.id.clear_all -> timeline.failedToDeliverEventCount() > 0
|
R.id.clear_all -> timeline.failedToDeliverEventCount() > 0
|
||||||
else -> false
|
else -> false
|
||||||
|
@ -47,8 +47,8 @@ class DefaultItemFactory @Inject constructor(private val avatarSizeProvider: Ava
|
|||||||
fun create(event: TimelineEvent,
|
fun create(event: TimelineEvent,
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
callback: TimelineEventController.Callback?,
|
callback: TimelineEventController.Callback?,
|
||||||
exception: Exception? = null): DefaultItem {
|
throwable: Throwable? = null): DefaultItem {
|
||||||
val text = if (exception == null) {
|
val text = if (throwable == null) {
|
||||||
"${event.root.getClearType()} events are not yet handled"
|
"${event.root.getClearType()} events are not yet handled"
|
||||||
} else {
|
} else {
|
||||||
"an exception occurred when rendering the event ${event.root.eventId}"
|
"an exception occurred when rendering the event ${event.root.eventId}"
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 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.riotx.features.home.room.detail.timeline.factory
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
|
||||||
import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent
|
|
||||||
import im.vector.riotx.R
|
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
|
||||||
import im.vector.riotx.features.home.AvatarRenderer
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.TimelineEventController
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.helper.AvatarSizeProvider
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.MessageInformationData
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem
|
|
||||||
import im.vector.riotx.features.home.room.detail.timeline.item.NoticeItem_
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class EncryptionItemFactory @Inject constructor(private val stringProvider: StringProvider,
|
|
||||||
private val avatarRenderer: AvatarRenderer,
|
|
||||||
private val avatarSizeProvider: AvatarSizeProvider) {
|
|
||||||
|
|
||||||
fun create(event: TimelineEvent,
|
|
||||||
highlight: Boolean,
|
|
||||||
callback: TimelineEventController.Callback?): NoticeItem? {
|
|
||||||
val text = buildNoticeText(event.root, event.getDisambiguatedDisplayName()) ?: return null
|
|
||||||
val informationData = MessageInformationData(
|
|
||||||
eventId = event.root.eventId ?: "?",
|
|
||||||
senderId = event.root.senderId ?: "",
|
|
||||||
sendState = event.root.sendState,
|
|
||||||
avatarUrl = event.senderAvatar,
|
|
||||||
memberName = event.getDisambiguatedDisplayName(),
|
|
||||||
showInformation = false
|
|
||||||
)
|
|
||||||
val attributes = NoticeItem.Attributes(
|
|
||||||
avatarRenderer = avatarRenderer,
|
|
||||||
informationData = informationData,
|
|
||||||
noticeText = text,
|
|
||||||
itemLongClickListener = View.OnLongClickListener { view ->
|
|
||||||
callback?.onEventLongClicked(informationData, null, view) ?: false
|
|
||||||
},
|
|
||||||
readReceiptsCallback = callback
|
|
||||||
)
|
|
||||||
return NoticeItem_()
|
|
||||||
.leftGuideline(avatarSizeProvider.leftGuideline)
|
|
||||||
.highlighted(highlight)
|
|
||||||
.attributes(attributes)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildNoticeText(event: Event, senderName: String?): CharSequence? {
|
|
||||||
return when {
|
|
||||||
EventType.STATE_ROOM_ENCRYPTION == event.getClearType() -> {
|
|
||||||
val content = event.content.toModel<EncryptionEventContent>() ?: return null
|
|
||||||
stringProvider.getString(R.string.notice_end_to_end, senderName, content.algorithm)
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,7 +24,8 @@ import im.vector.riotx.features.home.room.detail.timeline.TimelineEventControlle
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class TimelineItemFactory @Inject constructor(private val messageItemFactory: MessageItemFactory,
|
class TimelineItemFactory @Inject constructor(
|
||||||
|
private val messageItemFactory: MessageItemFactory,
|
||||||
private val encryptedItemFactory: EncryptedItemFactory,
|
private val encryptedItemFactory: EncryptedItemFactory,
|
||||||
private val noticeItemFactory: NoticeItemFactory,
|
private val noticeItemFactory: NoticeItemFactory,
|
||||||
private val defaultItemFactory: DefaultItemFactory,
|
private val defaultItemFactory: DefaultItemFactory,
|
||||||
@ -49,6 +50,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||||||
EventType.STATE_ROOM_CANONICAL_ALIAS,
|
EventType.STATE_ROOM_CANONICAL_ALIAS,
|
||||||
EventType.STATE_ROOM_JOIN_RULES,
|
EventType.STATE_ROOM_JOIN_RULES,
|
||||||
EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
EventType.STATE_ROOM_HISTORY_VISIBILITY,
|
||||||
|
EventType.STATE_ROOM_GUEST_ACCESS,
|
||||||
EventType.CALL_INVITE,
|
EventType.CALL_INVITE,
|
||||||
EventType.CALL_HANGUP,
|
EventType.CALL_HANGUP,
|
||||||
EventType.CALL_ANSWER,
|
EventType.CALL_ANSWER,
|
||||||
@ -74,9 +76,9 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (throwable: Throwable) {
|
||||||
Timber.e(e, "failed to create message item")
|
Timber.e(throwable, "failed to create message item")
|
||||||
defaultItemFactory.create(event, highlight, callback, e)
|
defaultItemFactory.create(event, highlight, callback, throwable)
|
||||||
}
|
}
|
||||||
return (computedModel ?: EmptyItem_())
|
return (computedModel ?: EmptyItem_())
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||||||
import im.vector.matrix.android.api.session.room.model.*
|
import im.vector.matrix.android.api.session.room.model.*
|
||||||
import im.vector.matrix.android.api.session.room.model.call.CallInviteContent
|
import im.vector.matrix.android.api.session.room.model.call.CallInviteContent
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
|
import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.resources.StringProvider
|
import im.vector.riotx.core.resources.StringProvider
|
||||||
@ -40,6 +41,8 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active
|
|||||||
EventType.STATE_ROOM_ALIASES -> formatRoomAliasesEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
EventType.STATE_ROOM_ALIASES -> formatRoomAliasesEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||||
EventType.STATE_ROOM_CANONICAL_ALIAS -> formatRoomCanonicalAliasEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
EventType.STATE_ROOM_CANONICAL_ALIAS -> formatRoomCanonicalAliasEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||||
EventType.STATE_ROOM_HISTORY_VISIBILITY -> formatRoomHistoryVisibilityEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
EventType.STATE_ROOM_HISTORY_VISIBILITY -> formatRoomHistoryVisibilityEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||||
|
EventType.STATE_ROOM_GUEST_ACCESS -> formatRoomGuestAccessEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||||
|
EventType.STATE_ROOM_ENCRYPTION -> formatRoomEncryptionEvent(timelineEvent.root, timelineEvent.getDisambiguatedDisplayName())
|
||||||
EventType.STATE_ROOM_TOMBSTONE -> formatRoomTombstoneEvent(timelineEvent.getDisambiguatedDisplayName())
|
EventType.STATE_ROOM_TOMBSTONE -> formatRoomTombstoneEvent(timelineEvent.getDisambiguatedDisplayName())
|
||||||
EventType.CALL_INVITE,
|
EventType.CALL_INVITE,
|
||||||
EventType.CALL_HANGUP,
|
EventType.CALL_HANGUP,
|
||||||
@ -166,6 +169,20 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active
|
|||||||
?: sp.getString(R.string.notice_room_canonical_alias_unset, senderName)
|
?: sp.getString(R.string.notice_room_canonical_alias_unset, senderName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun formatRoomGuestAccessEvent(event: Event, senderName: String?): String? {
|
||||||
|
val eventContent: RoomGuestAccessContent? = event.getClearContent().toModel()
|
||||||
|
return when (eventContent?.guestAccess) {
|
||||||
|
GuestAccess.CanJoin -> sp.getString(R.string.notice_room_guest_access_can_join, senderName)
|
||||||
|
GuestAccess.Forbidden -> sp.getString(R.string.notice_room_guest_access_forbidden, senderName)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatRoomEncryptionEvent(event: Event, senderName: String?): CharSequence? {
|
||||||
|
val content = event.content.toModel<EncryptionEventContent>() ?: return null
|
||||||
|
return sp.getString(R.string.notice_end_to_end, senderName, content.algorithm)
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildProfileNotice(event: Event, senderName: String?, eventContent: RoomMemberContent?, prevEventContent: RoomMemberContent?): String {
|
private fun buildProfileNotice(event: Event, senderName: String?, eventContent: RoomMemberContent?, prevEventContent: RoomMemberContent?): String {
|
||||||
val displayText = StringBuilder()
|
val displayText = StringBuilder()
|
||||||
// Check display name has been changed
|
// Check display name has been changed
|
||||||
|
@ -35,6 +35,7 @@ object TimelineDisplayableEvents {
|
|||||||
EventType.CALL_ANSWER,
|
EventType.CALL_ANSWER,
|
||||||
EventType.ENCRYPTED,
|
EventType.ENCRYPTED,
|
||||||
EventType.STATE_ROOM_ENCRYPTION,
|
EventType.STATE_ROOM_ENCRYPTION,
|
||||||
|
EventType.STATE_ROOM_GUEST_ACCESS,
|
||||||
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
EventType.STATE_ROOM_THIRD_PARTY_INVITE,
|
||||||
EventType.STICKER,
|
EventType.STICKER,
|
||||||
EventType.STATE_ROOM_CREATE,
|
EventType.STATE_ROOM_CREATE,
|
||||||
|
@ -36,6 +36,7 @@ import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity
|
|||||||
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity
|
import im.vector.riotx.features.roomdirectory.RoomDirectoryActivity
|
||||||
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomActivity
|
import im.vector.riotx.features.roomdirectory.createroom.CreateRoomActivity
|
||||||
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewActivity
|
import im.vector.riotx.features.roomdirectory.roompreview.RoomPreviewActivity
|
||||||
|
import im.vector.riotx.features.settings.VectorPreferences
|
||||||
import im.vector.riotx.features.settings.VectorSettingsActivity
|
import im.vector.riotx.features.settings.VectorSettingsActivity
|
||||||
import im.vector.riotx.features.share.SharedData
|
import im.vector.riotx.features.share.SharedData
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -44,12 +45,13 @@ import javax.inject.Singleton
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class DefaultNavigator @Inject constructor(
|
class DefaultNavigator @Inject constructor(
|
||||||
private val sessionHolder: ActiveSessionHolder
|
private val sessionHolder: ActiveSessionHolder,
|
||||||
|
private val vectorPreferences: VectorPreferences
|
||||||
) : Navigator {
|
) : Navigator {
|
||||||
|
|
||||||
override fun openRoom(context: Context, roomId: String, eventId: String?, buildTask: Boolean) {
|
override fun openRoom(context: Context, roomId: String, eventId: String?, buildTask: Boolean) {
|
||||||
if (sessionHolder.getSafeActiveSession()?.getRoom(roomId) == null) {
|
if (sessionHolder.getSafeActiveSession()?.getRoom(roomId) == null) {
|
||||||
fatalError("Trying to open an unknown room $roomId")
|
fatalError("Trying to open an unknown room $roomId", vectorPreferences.failFast())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ import android.provider.MediaStore
|
|||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.squareup.seismic.ShakeDetector
|
import com.squareup.seismic.ShakeDetector
|
||||||
|
import im.vector.riotx.BuildConfig
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.features.homeserver.ServerUrlsRepository
|
import im.vector.riotx.features.homeserver.ServerUrlsRepository
|
||||||
import im.vector.riotx.features.themes.ThemeUtils
|
import im.vector.riotx.features.themes.ThemeUtils
|
||||||
@ -268,7 +269,7 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun failFast(): Boolean {
|
fun failFast(): Boolean {
|
||||||
return developerMode() && defaultPrefs.getBoolean(SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, false)
|
return BuildConfig.DEBUG || (developerMode() && defaultPrefs.getBoolean(SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user