Merge pull request #4389 from nextcloud/issue-4377-show-no-msg-saved

User now knows if no offline messages are saved when entering a conversation
This commit is contained in:
Marcel Hibbe 2024-12-03 10:51:17 +01:00 committed by GitHub
commit ff74202e1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 77 additions and 6 deletions

View file

@ -194,6 +194,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -444,7 +445,7 @@ class ChatActivity :
this.lifecycleScope.launch { this.lifecycleScope.launch {
delay(DELAY_TO_SHOW_PROGRESS_BAR) delay(DELAY_TO_SHOW_PROGRESS_BAR)
if (adapter?.isEmpty == true) { if (adapter?.isEmpty == true && networkMonitor.isOnline.first()) {
binding.progressBar.visibility = View.VISIBLE binding.progressBar.visibility = View.VISIBLE
} }
} }
@ -939,6 +940,20 @@ class ChatActivity :
.collect() .collect()
} }
this.lifecycleScope.launch {
chatViewModel.getGeneralUIFlow.onEach { key ->
when (key) {
NO_OFFLINE_MESSAGES_FOUND -> {
if (networkMonitor.isOnline.first().not()) {
binding.offline.root.visibility = View.VISIBLE
}
}
else -> {}
}
}.collect()
}
chatViewModel.reactionDeletedViewState.observe(this) { state -> chatViewModel.reactionDeletedViewState.observe(this) { state ->
when (state) { when (state) {
is ChatViewModel.ReactionDeletedSuccessState -> { is ChatViewModel.ReactionDeletedSuccessState -> {
@ -2810,14 +2825,10 @@ class ChatActivity :
message1.timestamp message1.timestamp
) )
val isLessThan5Min = timeDifference > FIVE_MINUTES_IN_SECONDS val isLessThan5Min = timeDifference > FIVE_MINUTES_IN_SECONDS
if (isSameDayMessages(message2, message1) && return isSameDayMessages(message2, message1) &&
(message2.actorId == message1.actorId) && (message2.actorId == message1.actorId) &&
(!isLessThan5Min) && (!isLessThan5Min) &&
(message2.lastEditTimestamp == 0L || message1.lastEditTimestamp == 0L) (message2.lastEditTimestamp == 0L || message1.lastEditTimestamp == 0L)
) {
return true
}
return false
} }
private fun determinePreviousMessageIds(chatMessageList: List<ChatMessage>) { private fun determinePreviousMessageIds(chatMessageList: List<ChatMessage>) {
@ -3848,5 +3859,6 @@ class ChatActivity :
private const val DELAY_TO_SHOW_PROGRESS_BAR = 1000L private const val DELAY_TO_SHOW_PROGRESS_BAR = 1000L
private const val FIVE_MINUTES_IN_SECONDS: Long = 300 private const val FIVE_MINUTES_IN_SECONDS: Long = 300
const val CONVERSATION_INTERNAL_ID = "CONVERSATION_INTERNAL_ID" const val CONVERSATION_INTERNAL_ID = "CONVERSATION_INTERNAL_ID"
const val NO_OFFLINE_MESSAGES_FOUND = "NO_OFFLINE_MESSAGES_FOUND"
} }
} }

View file

@ -35,6 +35,12 @@ interface ChatMessageRepository : LifecycleAwareManager {
val lastReadMessageFlow: Flow<Int> val lastReadMessageFlow: Flow<Int>
/**
* Used for informing the user of the underlying processing behind offline support, [String] is the key
* which is handled in a switch statement in ChatActivity.
*/
val generalUIFlow: Flow<String>
fun setData(conversationModel: ConversationModel, credentials: String, urlForChatting: String) fun setData(conversationModel: ConversationModel, credentials: String, urlForChatting: String)
fun loadInitialMessages(withNetworkParams: Bundle): Job fun loadInitialMessages(withNetworkParams: Bundle): Job

View file

@ -10,6 +10,7 @@ package com.nextcloud.talk.chat.data.network
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.chat.data.ChatMessageRepository import com.nextcloud.talk.chat.data.ChatMessageRepository
import com.nextcloud.talk.chat.data.model.ChatMessage import com.nextcloud.talk.chat.data.model.ChatMessage
import com.nextcloud.talk.data.database.dao.ChatBlocksDao import com.nextcloud.talk.data.database.dao.ChatBlocksDao
@ -91,6 +92,11 @@ class OfflineFirstChatRepository @Inject constructor(
private val _lastReadMessageFlow: private val _lastReadMessageFlow:
MutableSharedFlow<Int> = MutableSharedFlow() MutableSharedFlow<Int> = MutableSharedFlow()
override val generalUIFlow: Flow<String>
get() = _generalUIFlow
private val _generalUIFlow: MutableSharedFlow<String> = MutableSharedFlow()
private var newXChatLastCommonRead: Int? = null private var newXChatLastCommonRead: Int? = null
private var itIsPaused = false private var itIsPaused = false
private val scope = CoroutineScope(Dispatchers.IO) private val scope = CoroutineScope(Dispatchers.IO)
@ -133,6 +139,7 @@ class OfflineFirstChatRepository @Inject constructor(
} else { } else {
if (!weAlreadyHaveSomeOfflineMessages) { if (!weAlreadyHaveSomeOfflineMessages) {
Log.d(TAG, "An online request for newest 100 messages is made because offline chat is empty") Log.d(TAG, "An online request for newest 100 messages is made because offline chat is empty")
_generalUIFlow.emit(ChatActivity.NO_OFFLINE_MESSAGES_FOUND)
} else { } else {
Log.d( Log.d(
TAG, TAG,

View file

@ -137,6 +137,8 @@ class ChatViewModel @Inject constructor(
_getRoomViewState.value = GetRoomErrorState _getRoomViewState.value = GetRoomErrorState
} }
val getGeneralUIFlow = chatRepository.generalUIFlow
sealed interface ViewState sealed interface ViewState
object GetReminderStartState : ViewState object GetReminderStartState : ViewState

View file

@ -98,6 +98,12 @@
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1"> android:layout_weight="1">
<include
android:id="@+id/offline"
layout="@layout/no_saved_messages_view"
android:visibility="gone"
tools:visibility="visible" />
<include <include
android:id="@+id/lobby" android:id="@+id/lobby"
layout="@layout/lobby_view" layout="@layout/lobby_view"

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2024 Julius Linus <juliuslinus1@gmail.com>
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/offline_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/offline_image_view"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_above="@id/offline_text_view"
android:layout_centerHorizontal="true"
android:layout_margin="@dimen/margin_between_elements"
android:contentDescription="@string/nc_lobby"
android:src="@drawable/ic_signal_wifi_off_white_24dp"
app:tint="@color/grey_600" />
<TextView
android:id="@+id/offline_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="@dimen/standard_margin"
android:text="@string/no_offline_messages_saved"
android:textAlignment="center"
android:textColor="@color/grey_600"
android:textSize="16sp"
android:autoLink="web" />
</RelativeLayout>

View file

@ -834,6 +834,7 @@ How to translate with transifex:
<string name="archived">Archived</string> <string name="archived">Archived</string>
<string name="archive_hint">Once a conversation is archived, it will be hidden by default. Select the filter \"Archived\" to view archived conversations. Direct mentions will still be received.</string> <string name="archive_hint">Once a conversation is archived, it will be hidden by default. Select the filter \"Archived\" to view archived conversations. Direct mentions will still be received.</string>
<string name="unarchive_hint">Once a conversation is unarchived, it will be shown by default again.</string> <string name="unarchive_hint">Once a conversation is unarchived, it will be shown by default again.</string>
<string name="no_offline_messages_saved">No offline messages saved</string>
<string name="previously_set">Previously set</string> <string name="previously_set">Previously set</string>
<string name="conversation_read_only_failed">Failed to set conversation Read-only</string> <string name="conversation_read_only_failed">Failed to set conversation Read-only</string>
<string name="status_reverted">Status Reverted</string> <string name="status_reverted">Status Reverted</string>