Make room and timeline nullable. Sometimes use initialState.roomId
instead of room.roomId
.
This commit is contained in:
parent
388cb16481
commit
f56f4e1160
@ -992,9 +992,9 @@ class TimelineFragment :
|
||||
views.jumpToBottomView.debouncedClicks {
|
||||
timelineViewModel.handle(RoomDetailAction.ExitTrackingUnreadMessagesState)
|
||||
views.jumpToBottomView.visibility = View.INVISIBLE
|
||||
if (!timelineViewModel.timeline.isLive) {
|
||||
if (timelineViewModel.timeline?.isLive == false) {
|
||||
scrollOnNewMessageCallback.forceScrollOnNextUpdate()
|
||||
timelineViewModel.timeline.restartWithEventId(null)
|
||||
timelineViewModel.timeline?.restartWithEventId(null)
|
||||
} else {
|
||||
layoutManager.scrollToPosition(0)
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ import org.matrix.android.sdk.api.session.events.model.toContent
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.file.FileService
|
||||
import org.matrix.android.sdk.api.session.getRoom
|
||||
import org.matrix.android.sdk.api.session.room.Room
|
||||
import org.matrix.android.sdk.api.session.room.getStateEvent
|
||||
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||
import org.matrix.android.sdk.api.session.room.location.UpdateLiveLocationShareResult
|
||||
@ -143,16 +144,16 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
private val cryptoConfig: CryptoConfig,
|
||||
buildMeta: BuildMeta,
|
||||
timelineFactory: TimelineFactory,
|
||||
spaceStateHandler: SpaceStateHandler,
|
||||
private val spaceStateHandler: SpaceStateHandler,
|
||||
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState),
|
||||
Timeline.Listener, ChatEffectManager.Delegate, CallProtocolsChecker.Listener, LocationSharingServiceConnection.Callback {
|
||||
|
||||
private val room = session.getRoom(initialState.roomId)!!
|
||||
private val room = session.getRoom(initialState.roomId)
|
||||
private val eventId = initialState.eventId
|
||||
private val invisibleEventsSource = BehaviorDataSource<RoomDetailAction.TimelineEventTurnsInvisible>()
|
||||
private val visibleEventsSource = BehaviorDataSource<RoomDetailAction.TimelineEventTurnsVisible>()
|
||||
private var timelineEvents = MutableSharedFlow<List<TimelineEvent>>(0)
|
||||
val timeline = timelineFactory.createTimeline(viewModelScope, room, eventId, initialState.rootThreadEventId)
|
||||
val timeline: Timeline?
|
||||
|
||||
// Same lifecycle than the ViewModel (survive to screen rotation)
|
||||
val previewUrlRetriever = PreviewUrlRetriever(session, viewModelScope, buildMeta)
|
||||
@ -181,9 +182,20 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
init {
|
||||
// This method will take care of a null room to update the state.
|
||||
observeRoomSummary()
|
||||
if (room == null) {
|
||||
timeline = null
|
||||
} else {
|
||||
// Nominal case, we have retrieved the room.
|
||||
timeline = timelineFactory.createTimeline(viewModelScope, room, eventId, initialState.rootThreadEventId)
|
||||
initSafe(room, timeline)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initSafe(room: Room, timeline: Timeline) {
|
||||
timeline.start(initialState.rootThreadEventId)
|
||||
timeline.addListener(this)
|
||||
observeRoomSummary()
|
||||
observeMembershipChanges()
|
||||
observeSummaryState()
|
||||
getUnreadState()
|
||||
@ -265,6 +277,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun prepareForEncryption() {
|
||||
if (room == null) return
|
||||
// check if there is not already a call made, or if there has been an error
|
||||
if (prepareToEncrypt.shouldLoad) {
|
||||
prepareToEncrypt = Loading()
|
||||
@ -281,6 +294,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun observePowerLevel() {
|
||||
if (room == null) return
|
||||
PowerLevelsFlowFactory(room).createFlow()
|
||||
.onEach {
|
||||
val canInvite = PowerLevelsHelper(it).isUserAbleToInvite(session.myUserId)
|
||||
@ -329,6 +343,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun observeMyRoomMember() {
|
||||
if (room == null) return
|
||||
val queryParams = roomMemberQueryParams {
|
||||
this.userId = QueryStringValue.Equals(session.myUserId, QueryStringValue.Case.SENSITIVE)
|
||||
}
|
||||
@ -344,6 +359,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun setupPreviewUrlObservers() {
|
||||
if (room == null) return
|
||||
if (!vectorPreferences.showUrlPreviews()) {
|
||||
return
|
||||
}
|
||||
@ -372,6 +388,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
* This is a local implementation has nothing to do with APIs.
|
||||
*/
|
||||
private fun markThreadTimelineAsReadLocal() {
|
||||
if (room == null) return
|
||||
initialState.rootThreadEventId?.let {
|
||||
session.coroutineScope.launch {
|
||||
room.threadsLocalService().markThreadAsRead(it)
|
||||
@ -383,6 +400,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
* Observe local unread threads.
|
||||
*/
|
||||
private fun observeLocalThreadNotifications() {
|
||||
if (room == null) return
|
||||
room.flow()
|
||||
.liveLocalUnreadThreadList()
|
||||
.execute {
|
||||
@ -514,6 +532,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleSetNewAvatar(action: RoomDetailAction.SetAvatarAction) {
|
||||
if (room == null) return
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
room.stateService().updateAvatar(action.newAvatarUri, action.newAvatarFileName)
|
||||
@ -533,11 +552,13 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleJumpToReadReceipt(action: RoomDetailAction.JumpToReadReceipt) {
|
||||
if (room == null) return
|
||||
room.readService().getUserReadReceipt(action.userId)
|
||||
?.let { handleNavigateToEvent(RoomDetailAction.NavigateToEvent(it, true)) }
|
||||
}
|
||||
|
||||
private fun handleSendSticker(action: RoomDetailAction.SendSticker) {
|
||||
if (room == null) return
|
||||
val content = initialState.rootThreadEventId?.let {
|
||||
action.stickerContent.copy(
|
||||
relatesTo = RelationDefaultContent(
|
||||
@ -552,6 +573,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleStartCall(action: RoomDetailAction.StartCall) {
|
||||
if (room == null) return
|
||||
viewModelScope.launch {
|
||||
room.roomSummary()?.otherMemberIds?.firstOrNull()?.let {
|
||||
callManager.startOutgoingCall(room.roomId, it, action.isVideo)
|
||||
@ -597,7 +619,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val widget = jitsiService.createJitsiWidget(room.roomId, action.withVideo)
|
||||
val widget = jitsiService.createJitsiWidget(initialState.roomId, action.withVideo)
|
||||
_viewEvents.post(RoomDetailViewEvents.JoinJitsiConference(widget, action.withVideo))
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowMessage(stringProvider.getString(R.string.failed_to_add_widget)))
|
||||
@ -616,7 +638,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
} else {
|
||||
_viewEvents.post(RoomDetailViewEvents.ShowWaitingView)
|
||||
}
|
||||
session.widgetService().destroyRoomWidget(room.roomId, widgetId)
|
||||
session.widgetService().destroyRoomWidget(initialState.roomId, widgetId)
|
||||
// local echo
|
||||
setState {
|
||||
copy(
|
||||
@ -665,6 +687,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun stopTrackingUnreadMessages() {
|
||||
if (room == null) return
|
||||
if (trackUnreadMessages.getAndSet(false)) {
|
||||
mostRecentDisplayedEvent?.root?.eventId?.also {
|
||||
session.coroutineScope.launch {
|
||||
@ -681,10 +704,11 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
fun getMember(userId: String): RoomMemberSummary? {
|
||||
return room.membershipService().getRoomMember(userId)
|
||||
return room?.membershipService()?.getRoomMember(userId)
|
||||
}
|
||||
|
||||
private fun handleComposerFocusChange(action: RoomDetailAction.ComposerFocusChange) {
|
||||
if (room == null) return
|
||||
// Ensure outbound session keys
|
||||
if (room.roomCryptoService().isEncrypted()) {
|
||||
rawService.withElementWellKnown(viewModelScope, session.sessionParams) {
|
||||
@ -774,11 +798,12 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
// PRIVATE METHODS *****************************************************************************
|
||||
|
||||
private fun handleSendReaction(action: RoomDetailAction.SendReaction) {
|
||||
if (room == null) return
|
||||
room.relationService().sendReaction(action.targetEventId, action.reaction)
|
||||
}
|
||||
|
||||
private fun handleRedactEvent(action: RoomDetailAction.RedactAction) {
|
||||
val event = room.getTimelineEvent(action.targetEventId) ?: return
|
||||
val event = room?.getTimelineEvent(action.targetEventId) ?: return
|
||||
if (event.isLiveLocation()) {
|
||||
viewModelScope.launch {
|
||||
redactLiveLocationShareEventUseCase.execute(event.root, room, action.reason)
|
||||
@ -789,6 +814,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleUndoReact(action: RoomDetailAction.UndoReaction) {
|
||||
if (room == null) return
|
||||
viewModelScope.launch {
|
||||
tryOrNull {
|
||||
room.relationService().undoReaction(action.targetEventId, action.reaction)
|
||||
@ -797,6 +823,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleUpdateQuickReaction(action: RoomDetailAction.UpdateQuickReactAction) {
|
||||
if (room == null) return
|
||||
if (action.add) {
|
||||
room.relationService().sendReaction(action.targetEventId, action.selectedReaction)
|
||||
} else {
|
||||
@ -809,6 +836,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleSendMedia(action: RoomDetailAction.SendMedia) {
|
||||
if (room == null) return
|
||||
room.sendService().sendMedias(
|
||||
action.attachments,
|
||||
action.compressBeforeSending,
|
||||
@ -818,6 +846,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleEventVisible(action: RoomDetailAction.TimelineEventTurnsVisible) {
|
||||
if (room == null) return
|
||||
viewModelScope.launch(Dispatchers.Default) {
|
||||
if (action.event.root.sendState.isSent()) { // ignore pending/local events
|
||||
visibleEventsSource.post(action)
|
||||
@ -845,6 +874,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleLoadMore(action: RoomDetailAction.LoadMoreTimelineEvents) {
|
||||
if (timeline == null) return
|
||||
timeline.paginate(action.direction, PAGINATION_COUNT)
|
||||
}
|
||||
|
||||
@ -852,7 +882,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(initialState.roomId) }
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
session.roomService().leaveRoom(room.roomId)
|
||||
session.roomService().leaveRoom(initialState.roomId)
|
||||
} catch (throwable: Throwable) {
|
||||
_viewEvents.post(RoomDetailViewEvents.Failure(throwable, showInDialog = true))
|
||||
}
|
||||
@ -863,7 +893,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
notificationDrawerManager.updateEvents { it.clearMemberShipNotificationForRoom(initialState.roomId) }
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
session.roomService().joinRoom(room.roomId)
|
||||
session.roomService().joinRoom(initialState.roomId)
|
||||
trackRoomJoined()
|
||||
} catch (throwable: Throwable) {
|
||||
_viewEvents.post(RoomDetailViewEvents.Failure(throwable, showInDialog = true))
|
||||
@ -872,6 +902,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun trackRoomJoined() {
|
||||
if (room == null) return
|
||||
val trigger = if (initialState.isInviteAlreadyAccepted) {
|
||||
JoinedRoom.Trigger.Invite
|
||||
} else {
|
||||
@ -929,6 +960,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleNavigateToEvent(action: RoomDetailAction.NavigateToEvent) {
|
||||
if (timeline == null) return
|
||||
val targetEventId: String = action.eventId
|
||||
val indexOfEvent = timeline.getIndexOfEvent(targetEventId)
|
||||
if (indexOfEvent == null) {
|
||||
@ -942,6 +974,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleResendEvent(action: RoomDetailAction.ResendMessage) {
|
||||
if (room == null) return
|
||||
val targetEventId = action.eventId
|
||||
room.getTimelineEvent(targetEventId)?.let {
|
||||
// State must be UNDELIVERED or Failed
|
||||
@ -960,6 +993,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleRemove(action: RoomDetailAction.RemoveFailedEcho) {
|
||||
if (room == null) return
|
||||
val targetEventId = action.eventId
|
||||
room.getTimelineEvent(targetEventId)?.let {
|
||||
// State must be UNDELIVERED or Failed
|
||||
@ -972,6 +1006,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleCancel(action: RoomDetailAction.CancelSend) {
|
||||
if (room == null) return
|
||||
if (action.force) {
|
||||
room.sendService().cancelSend(action.eventId)
|
||||
return
|
||||
@ -988,14 +1023,17 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleResendAll() {
|
||||
if (room == null) return
|
||||
room.sendService().resendAllFailedMessages()
|
||||
}
|
||||
|
||||
private fun handleRemoveAllFailedMessages() {
|
||||
if (room == null) return
|
||||
room.sendService().cancelAllFailedMessages()
|
||||
}
|
||||
|
||||
private fun observeEventDisplayedActions() {
|
||||
if (room == null) return
|
||||
// We are buffering scroll events for one second
|
||||
// and keep the most recent one to set the read receipt on.
|
||||
|
||||
@ -1027,9 +1065,10 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
* Returns the index of event in the timeline.
|
||||
* Returns Int.MAX_VALUE if not found
|
||||
*/
|
||||
private fun TimelineEvent.indexOfEvent(): Int = timeline.getIndexOfEvent(eventId) ?: Int.MAX_VALUE
|
||||
private fun TimelineEvent.indexOfEvent(): Int = timeline?.getIndexOfEvent(eventId) ?: Int.MAX_VALUE
|
||||
|
||||
private fun handleMarkAllAsRead() {
|
||||
if (room == null) return
|
||||
setState { copy(unreadState = UnreadState.HasNoUnread) }
|
||||
viewModelScope.launch {
|
||||
tryOrNull { room.readService().markAsRead(ReadService.MarkAsReadParams.BOTH) }
|
||||
@ -1037,6 +1076,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleReportContent(action: RoomDetailAction.ReportContent) {
|
||||
if (room == null) return
|
||||
viewModelScope.launch {
|
||||
val event = try {
|
||||
room.reportingService().reportContent(action.eventId, -100, action.reason)
|
||||
@ -1065,11 +1105,11 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleAcceptVerification(action: RoomDetailAction.AcceptVerificationRequest) {
|
||||
Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${room.roomId}, txId:${action.transactionId}")
|
||||
Timber.v("## SAS handleAcceptVerification ${action.otherUserId}, roomId:${initialState.roomId}, txId:${action.transactionId}")
|
||||
if (session.cryptoService().verificationService().readyPendingVerificationInDMs(
|
||||
supportedVerificationMethodsProvider.provide(),
|
||||
action.otherUserId,
|
||||
room.roomId,
|
||||
initialState.roomId,
|
||||
action.transactionId
|
||||
)) {
|
||||
_viewEvents.post(RoomDetailViewEvents.ActionSuccess(action))
|
||||
@ -1082,7 +1122,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
session.cryptoService().verificationService().declineVerificationRequestInDMs(
|
||||
action.otherUserId,
|
||||
action.transactionId,
|
||||
room.roomId
|
||||
initialState.roomId
|
||||
)
|
||||
}
|
||||
|
||||
@ -1093,7 +1133,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
|
||||
private fun handleResumeRequestVerification(action: RoomDetailAction.ResumeVerification) {
|
||||
// Check if this request is still active and handled by me
|
||||
session.cryptoService().verificationService().getExistingVerificationRequestInRoom(room.roomId, action.transactionId)?.let {
|
||||
session.cryptoService().verificationService().getExistingVerificationRequestInRoom(initialState.roomId, action.transactionId)?.let {
|
||||
if (it.handledByOtherSession) return
|
||||
if (!it.isFinished) {
|
||||
_viewEvents.post(
|
||||
@ -1108,6 +1148,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleReRequestKeys(action: RoomDetailAction.ReRequestKeys) {
|
||||
if (room == null) return
|
||||
// Check if this request is still active and handled by me
|
||||
room.getTimelineEvent(action.eventId)?.let {
|
||||
session.cryptoService().reRequestRoomKeyForEvent(it.root)
|
||||
@ -1116,6 +1157,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleTapOnFailedToDecrypt(action: RoomDetailAction.TapOnFailedToDecrypt) {
|
||||
if (room == null) return
|
||||
room.getTimelineEvent(action.eventId)?.let {
|
||||
val code = when (it.root.mCryptoError) {
|
||||
MXCryptoError.ErrorType.KEYS_WITHHELD -> {
|
||||
@ -1129,6 +1171,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleVoteToPoll(action: RoomDetailAction.VoteToPoll) {
|
||||
if (room == null) return
|
||||
// Do not allow to vote unsent local echo of the poll event
|
||||
if (LocalEcho.isLocalEchoId(action.eventId)) return
|
||||
// Do not allow to vote the same option twice
|
||||
@ -1141,6 +1184,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun handleEndPoll(eventId: String) {
|
||||
if (room == null) return
|
||||
room.sendService().endPoll(eventId)
|
||||
}
|
||||
|
||||
@ -1160,7 +1204,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
|
||||
private fun handleStopLiveLocationSharing() {
|
||||
viewModelScope.launch {
|
||||
val result = stopLiveLocationShareUseCase.execute(room.roomId)
|
||||
val result = stopLiveLocationShareUseCase.execute(initialState.roomId)
|
||||
if (result is UpdateLiveLocationShareResult.Failure) {
|
||||
_viewEvents.post(RoomDetailViewEvents.Failure(throwable = result.error, showInDialog = true))
|
||||
}
|
||||
@ -1168,16 +1212,26 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun observeRoomSummary() {
|
||||
room.flow().liveRoomSummary()
|
||||
.unwrap()
|
||||
.execute { async ->
|
||||
copy(
|
||||
asyncRoomSummary = async
|
||||
)
|
||||
}
|
||||
if (room == null) {
|
||||
Timber.w("Warning, room with Id ${initialState.roomId} is not found.")
|
||||
setState {
|
||||
copy(
|
||||
asyncRoomSummary = Fail(IllegalStateException("Room Not Found"))
|
||||
)
|
||||
}
|
||||
} else {
|
||||
room.flow().liveRoomSummary()
|
||||
.unwrap()
|
||||
.execute { async ->
|
||||
copy(
|
||||
asyncRoomSummary = async
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUnreadState() {
|
||||
if (room == null) return
|
||||
combine(
|
||||
timelineEvents,
|
||||
room.flow().liveRoomSummary().unwrap()
|
||||
@ -1202,6 +1256,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun computeUnreadState(events: List<TimelineEvent>, roomSummary: RoomSummary): UnreadState {
|
||||
if (timeline == null) return UnreadState.Unknown
|
||||
if (events.isEmpty()) return UnreadState.Unknown
|
||||
val readMarkerIdSnapshot = roomSummary.readMarkerId ?: return UnreadState.Unknown
|
||||
val firstDisplayableEventIndex = timeline.getIndexOfEvent(readMarkerIdSnapshot)
|
||||
@ -1248,6 +1303,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private fun observeSummaryState() {
|
||||
if (room == null) return
|
||||
onAsync(RoomDetailViewState::asyncRoomSummary) { summary ->
|
||||
setState {
|
||||
val typingMessage = typingHelper.getTypingMessage(summary.typingUsers)
|
||||
@ -1291,6 +1347,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
*/
|
||||
private var threadPermalinkHandled = false
|
||||
private fun navigateToThreadEventIfNeeded(snapshot: List<TimelineEvent>) {
|
||||
if (timeline == null) return
|
||||
if (eventId != null && initialState.rootThreadEventId != null) {
|
||||
// When we have a permalink and we are in a thread timeline
|
||||
if (snapshot.firstOrNull { it.eventId == eventId } != null && !threadPermalinkHandled) {
|
||||
@ -1313,6 +1370,7 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
override fun onTimelineFailure(throwable: Throwable) {
|
||||
if (timeline == null) return
|
||||
// If we have a critical timeline issue, we get back to live.
|
||||
timeline.restartWithEventId(null)
|
||||
_viewEvents.post(RoomDetailViewEvents.Failure(throwable))
|
||||
@ -1338,11 +1396,11 @@ class TimelineViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
timeline.dispose()
|
||||
timeline.removeAllListeners()
|
||||
decryptionFailureTracker.onTimeLineDisposed(room.roomId)
|
||||
timeline?.dispose()
|
||||
timeline?.removeAllListeners()
|
||||
decryptionFailureTracker.onTimeLineDisposed(initialState.roomId)
|
||||
if (vectorPreferences.sendTypingNotifs()) {
|
||||
room.typingService().userStopsTyping()
|
||||
room?.typingService()?.userStopsTyping()
|
||||
}
|
||||
chatEffectManager.delegate = null
|
||||
chatEffectManager.dispose()
|
||||
|
Loading…
x
Reference in New Issue
Block a user