diff --git a/CHANGES.md b/CHANGES.md index 94eca36ff9..9d89e9fe9d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,7 @@ Features ✨: - Improvements 🙌: - - + - Render events m.room.encryption and m.room.guest_access in the timeline Other changes: - @@ -17,7 +17,7 @@ Translations 🗣: - Build 🧱: - - + - Change the way versionCode is computed (#827) Changes in RiotX 0.12.0 (2020-01-09) =================================================== diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EventType.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EventType.kt index 903df0cace..224b4262ab 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EventType.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EventType.kt @@ -91,7 +91,8 @@ object EventType { STATE_ROOM_CANONICAL_ALIAS, STATE_ROOM_HISTORY_VISIBILITY, STATE_ROOM_RELATED_GROUPS, - STATE_ROOM_PINNED_EVENT + STATE_ROOM_PINNED_EVENT, + STATE_ROOM_ENCRYPTION ) fun isStateEvent(type: String): Boolean { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/members/RoomMemberQueryParams.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/members/RoomMemberQueryParams.kt index 19003632ca..b8ad55213c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/members/RoomMemberQueryParams.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/members/RoomMemberQueryParams.kt @@ -28,17 +28,20 @@ fun roomMemberQueryParams(init: (RoomMemberQueryParams.Builder.() -> Unit) = {}) */ data class RoomMemberQueryParams( val displayName: QueryStringValue, - val memberships: List + val memberships: List, + val excludeSelf: Boolean ) { class Builder { var displayName: QueryStringValue = QueryStringValue.IsNotEmpty var memberships: List = Membership.all() + var excludeSelf: Boolean = false fun build() = RoomMemberQueryParams( displayName = displayName, - memberships = memberships + memberships = memberships, + excludeSelf = excludeSelf ) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomGuestAccessContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomGuestAccessContent.kt new file mode 100644 index 0000000000..4c814f7914 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomGuestAccessContent.kt @@ -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") +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomParams.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomParams.kt index dbdd5b5a34..2c192ee8c7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomParams.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomParams.kt @@ -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.RoomHistoryVisibility 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 @@ -88,7 +90,7 @@ class CreateRoomParams { * 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. * 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") var initialStates: MutableList? = null @@ -120,14 +122,14 @@ class CreateRoomParams { * * @param algorithm the algorithm */ - fun addCryptoAlgorithm(algorithm: String) { - if (algorithm.isNotBlank()) { - val contentMap = HashMap() - contentMap["algorithm"] = algorithm + fun enableEncryptionWithAlgorithm(algorithm: String) { + if (algorithm == MXCRYPTO_ALGORITHM_MEGOLM) { + val contentMap = mapOf("algorithm" to algorithm) - val algoEvent = Event(type = EventType.STATE_ROOM_ENCRYPTION, - stateKey = "", - content = contentMap.toContent() + val algoEvent = Event( + type = EventType.STATE_ROOM_ENCRYPTION, + stateKey = "", + content = contentMap.toContent() ) if (null == initialStates) { @@ -135,6 +137,8 @@ class CreateRoomParams { } else { initialStates!!.add(algoEvent) } + } else { + Timber.e("Unsupported algorithm: $algorithm") } } @@ -145,15 +149,15 @@ class CreateRoomParams { */ fun setHistoryVisibility(historyVisibility: RoomHistoryVisibility?) { // 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) { - val contentMap = HashMap() - contentMap["history_visibility"] = historyVisibility + val contentMap = mapOf("history_visibility" to historyVisibility) - val historyVisibilityEvent = Event(type = EventType.STATE_ROOM_HISTORY_VISIBILITY, - stateKey = "", - content = contentMap.toContent()) + val historyVisibilityEvent = Event( + type = EventType.STATE_ROOM_HISTORY_VISIBILITY, + stateKey = "", + content = contentMap.toContent()) if (null == initialStates) { initialStates = mutableListOf(historyVisibilityEvent) @@ -192,8 +196,8 @@ class CreateRoomParams { */ fun isDirect(): Boolean { return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT - && isDirect == true - && (1 == getInviteCount() || 1 == getInvite3PidCount()) + && isDirect == true + && (1 == getInviteCount() || 1 == getInvite3PidCount()) } /** @@ -218,8 +222,8 @@ class CreateRoomParams { invite3pids = ArrayList() } val pid = Invite3Pid(idServer = hsConfig.identityServerUri.host!!, - medium = ThreePidMedium.EMAIL, - address = id) + medium = ThreePidMedium.EMAIL, + address = id) invite3pids!!.add(pid) } else if (isUserId(id)) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt index 679f4a050b..dc44359666 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/DefaultMembershipService.kt @@ -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.model.RoomMemberEntity 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.session.room.membership.joining.InviteTask 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.RealmQuery -internal class DefaultMembershipService @AssistedInject constructor(@Assisted private val roomId: String, - private val monarchy: Monarchy, - private val taskExecutor: TaskExecutor, - private val loadRoomMembersTask: LoadRoomMembersTask, - private val inviteTask: InviteTask, - private val joinTask: JoinRoomTask, - private val leaveRoomTask: LeaveRoomTask +internal class DefaultMembershipService @AssistedInject constructor( + @Assisted private val roomId: String, + private val monarchy: Monarchy, + private val taskExecutor: TaskExecutor, + private val loadRoomMembersTask: LoadRoomMembersTask, + private val inviteTask: InviteTask, + private val joinTask: JoinRoomTask, + private val leaveRoomTask: LeaveRoomTask, + @UserId + private val userId: String ) : MembershipService { @AssistedInject.Factory @@ -95,6 +99,11 @@ internal class DefaultMembershipService @AssistedInject constructor(@Assisted pr return RoomMembers(realm, roomId).queryRoomMembersEvent() .process(RoomMemberEntityFields.MEMBERSHIP_STR, queryParams.memberships) .process(RoomMemberEntityFields.DISPLAY_NAME, queryParams.displayName) + .apply { + if (queryParams.excludeSelf) { + notEqualTo(RoomMemberEntityFields.USER_ID, userId) + } + } } override fun getNumberOfJoinedMembers(): Int { diff --git a/matrix-sdk-android/src/main/res/values/strings.xml b/matrix-sdk-android/src/main/res/values/strings.xml index c0506dd549..d5cd7a117b 100644 --- a/matrix-sdk-android/src/main/res/values/strings.xml +++ b/matrix-sdk-android/src/main/res/values/strings.xml @@ -272,4 +272,7 @@ "%1$s set the main address for this room to %2$s." "%1$s removed the main address for this room." + "%1$s has allowed guests to join the room." + "%1$s has prevented guests from joining the room." + diff --git a/vector/build.gradle b/vector/build.gradle index 19bdd1dd8c..4960c6b796 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -24,12 +24,16 @@ static def getGitTimestamp() { } static def generateVersionCodeFromTimestamp() { - // It's unix timestamp divided by 10: It's incremented by one every 10 seconds. - return (getGitTimestamp() / 10).toInteger() + // It's unix timestamp, minus timestamp of October 3rd 2018 (first commit date) divided by 100: It's incremented by one every 100 seconds. + // 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() { - 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() { @@ -77,8 +81,8 @@ project.android.buildTypes.all { buildType -> ] } -// map for the version codes -// 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 +// map for the version codes last digit +// x86 must have greater values than arm // 64 bits have greater value than 32 bits ext.abiVersionCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86": 3, "x86_64": 4].withDefault { 0 } @@ -144,7 +148,7 @@ android { variant.outputs.each { output -> def baseAbiVersionCode = project.ext.abiVersionCodes.get(output.getFilter(OutputFile.ABI)) // 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 } } } diff --git a/vector/src/main/java/im/vector/riotx/core/error/fatal.kt b/vector/src/main/java/im/vector/riotx/core/error/fatal.kt index 800e1ea7ad..ad6a99928a 100644 --- a/vector/src/main/java/im/vector/riotx/core/error/fatal.kt +++ b/vector/src/main/java/im/vector/riotx/core/error/fatal.kt @@ -16,14 +16,13 @@ package im.vector.riotx.core.error -import im.vector.riotx.BuildConfig import timber.log.Timber /** * throw in debug, only log in production. As this method does not always throw, next statement should be a return */ -fun fatalError(message: String) { - if (BuildConfig.DEBUG) { +fun fatalError(message: String, failFast: Boolean) { + if (failFast) { error(message) } else { Timber.e(message) diff --git a/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt b/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt index d8828eb1b8..bd87251a58 100644 --- a/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt +++ b/vector/src/main/java/im/vector/riotx/core/rx/RxConfig.kt @@ -16,7 +16,6 @@ package im.vector.riotx.core.rx -import im.vector.riotx.BuildConfig import im.vector.riotx.features.settings.VectorPreferences import io.reactivex.plugins.RxJavaPlugins import timber.log.Timber @@ -33,8 +32,8 @@ class RxConfig @Inject constructor( RxJavaPlugins.setErrorHandler { throwable -> Timber.e(throwable, "RxError") - // Avoid crash in production - if (BuildConfig.DEBUG || vectorPreferences.failFast()) { + // Avoid crash in production, except if user wants it + if (vectorPreferences.failFast()) { throw throwable } } diff --git a/vector/src/main/java/im/vector/riotx/features/autocomplete/member/AutocompleteMemberPresenter.kt b/vector/src/main/java/im/vector/riotx/features/autocomplete/member/AutocompleteMemberPresenter.kt index 84a33173b8..bc50b12e6e 100644 --- a/vector/src/main/java/im/vector/riotx/features/autocomplete/member/AutocompleteMemberPresenter.kt +++ b/vector/src/main/java/im/vector/riotx/features/autocomplete/member/AutocompleteMemberPresenter.kt @@ -63,6 +63,7 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context, QueryStringValue.Contains(query.toString(), QueryStringValue.Case.INSENSITIVE) } memberships = listOf(Membership.JOIN) + excludeSelf = true } val members = room.getRoomMembers(queryParams) .asSequence() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index c93358a04e..cd8032481d 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -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.rx.rx import im.vector.matrix.rx.unwrap -import im.vector.riotx.BuildConfig import im.vector.riotx.R import im.vector.riotx.core.extensions.postLiveEvent 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) { R.id.clear_message_queue -> /* 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.clear_all -> timeline.failedToDeliverEventCount() > 0 else -> false diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/DefaultItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/DefaultItemFactory.kt index 94d7812512..d9bed98b1f 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/DefaultItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/DefaultItemFactory.kt @@ -47,8 +47,8 @@ class DefaultItemFactory @Inject constructor(private val avatarSizeProvider: Ava fun create(event: TimelineEvent, highlight: Boolean, callback: TimelineEventController.Callback?, - exception: Exception? = null): DefaultItem { - val text = if (exception == null) { + throwable: Throwable? = null): DefaultItem { + val text = if (throwable == null) { "${event.root.getClearType()} events are not yet handled" } else { "an exception occurred when rendering the event ${event.root.eventId}" diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt deleted file mode 100644 index fd29fe6bf5..0000000000 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt +++ /dev/null @@ -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() ?: return null - stringProvider.getString(R.string.notice_end_to_end, senderName, content.algorithm) - } - else -> null - } - } -} diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt index 861be5cc86..6d27cf7211 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/factory/TimelineItemFactory.kt @@ -24,11 +24,12 @@ import im.vector.riotx.features.home.room.detail.timeline.TimelineEventControlle import timber.log.Timber import javax.inject.Inject -class TimelineItemFactory @Inject constructor(private val messageItemFactory: MessageItemFactory, - private val encryptedItemFactory: EncryptedItemFactory, - private val noticeItemFactory: NoticeItemFactory, - private val defaultItemFactory: DefaultItemFactory, - private val roomCreateItemFactory: RoomCreateItemFactory) { +class TimelineItemFactory @Inject constructor( + private val messageItemFactory: MessageItemFactory, + private val encryptedItemFactory: EncryptedItemFactory, + private val noticeItemFactory: NoticeItemFactory, + private val defaultItemFactory: DefaultItemFactory, + private val roomCreateItemFactory: RoomCreateItemFactory) { fun create(event: TimelineEvent, nextEvent: TimelineEvent?, @@ -49,6 +50,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me EventType.STATE_ROOM_CANONICAL_ALIAS, EventType.STATE_ROOM_JOIN_RULES, EventType.STATE_ROOM_HISTORY_VISIBILITY, + EventType.STATE_ROOM_GUEST_ACCESS, EventType.CALL_INVITE, EventType.CALL_HANGUP, EventType.CALL_ANSWER, @@ -74,9 +76,9 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me null } } - } catch (e: Exception) { - Timber.e(e, "failed to create message item") - defaultItemFactory.create(event, highlight, callback, e) + } catch (throwable: Throwable) { + Timber.e(throwable, "failed to create message item") + defaultItemFactory.create(event, highlight, callback, throwable) } return (computedModel ?: EmptyItem_()) } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt index a201890912..563a970cfb 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/format/NoticeEventFormatter.kt @@ -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.call.CallInviteContent 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.di.ActiveSessionHolder 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_CANONICAL_ALIAS -> formatRoomCanonicalAliasEvent(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.CALL_INVITE, 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) } + 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() ?: 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 { val displayText = StringBuilder() // Check display name has been changed diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt index d669068cd7..1c9ff6dac5 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt @@ -35,6 +35,7 @@ object TimelineDisplayableEvents { EventType.CALL_ANSWER, EventType.ENCRYPTED, EventType.STATE_ROOM_ENCRYPTION, + EventType.STATE_ROOM_GUEST_ACCESS, EventType.STATE_ROOM_THIRD_PARTY_INVITE, EventType.STICKER, EventType.STATE_ROOM_CREATE, diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt index 48422056b4..8784ec662d 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt @@ -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.createroom.CreateRoomActivity 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.share.SharedData import timber.log.Timber @@ -44,12 +45,13 @@ import javax.inject.Singleton @Singleton class DefaultNavigator @Inject constructor( - private val sessionHolder: ActiveSessionHolder + private val sessionHolder: ActiveSessionHolder, + private val vectorPreferences: VectorPreferences ) : Navigator { override fun openRoom(context: Context, roomId: String, eventId: String?, buildTask: Boolean) { 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 } diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt index 72f8cf01dd..c734558c0e 100755 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorPreferences.kt @@ -24,6 +24,7 @@ import android.provider.MediaStore import androidx.core.content.edit import androidx.preference.PreferenceManager import com.squareup.seismic.ShakeDetector +import im.vector.riotx.BuildConfig import im.vector.riotx.R import im.vector.riotx.features.homeserver.ServerUrlsRepository import im.vector.riotx.features.themes.ThemeUtils @@ -268,7 +269,7 @@ class VectorPreferences @Inject constructor(private val context: Context) { } 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)) } /**