Skip to content

Commit

Permalink
Merge pull request #4622 from nextcloud/backport/4598/manualBackportT…
Browse files Browse the repository at this point in the history
…ooManyRequestsException

manual backport of PR #4598 (TooManyRequestsException)
  • Loading branch information
mahibi authored Jan 16, 2025
2 parents 237b6fa + 36f4c4f commit 2e52eab
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class OutcomingTextMessageViewHolder(itemView: View) :
).first()
}

parentChatMessage!!.activeUser = message.activeUser
parentChatMessage.activeUser = message.activeUser
parentChatMessage.imageUrl?.let {
binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
binding.messageQuote.quotedMessageImage.load(it) {
Expand All @@ -207,7 +207,6 @@ class OutcomingTextMessageViewHolder(itemView: View) :
viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)

binding.messageQuote.quotedChatMessageView.setOnClickListener {
val chatActivity = commonMessageInterface as ChatActivity
chatActivity.jumpToQuotedMessage(parentChatMessage)
}
} catch (e: Exception) {
Expand Down
5 changes: 2 additions & 3 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -428,7 +427,7 @@ class ChatActivity :

this.lifecycleScope.launch {
delay(DELAY_TO_SHOW_PROGRESS_BAR)
if (adapter?.isEmpty == true && networkMonitor.isOnline.first()) {
if (adapter?.isEmpty == true && networkMonitor.isOnline.value) {
binding.progressBar.visibility = View.VISIBLE
}
}
Expand Down Expand Up @@ -923,7 +922,7 @@ class ChatActivity :
chatViewModel.getGeneralUIFlow.onEach { key ->
when (key) {
NO_OFFLINE_MESSAGES_FOUND -> {
if (networkMonitor.isOnline.first().not()) {
if (networkMonitor.isOnline.value.not()) {
binding.offline.root.visibility = View.VISIBLE
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import com.nextcloud.talk.models.json.chat.ChatMessageJson
import com.nextcloud.talk.models.json.chat.ChatOverall
import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import com.nextcloud.talk.utils.preferences.AppPreferences
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
Expand All @@ -45,8 +44,7 @@ class OfflineFirstChatRepository @Inject constructor(
private val chatDao: ChatMessagesDao,
private val chatBlocksDao: ChatBlocksDao,
private val network: ChatNetworkDataSource,
private val datastore: AppPreferences,
private val monitor: NetworkMonitor,
private val networkMonitor: NetworkMonitor,
private val userProvider: CurrentUserProviderNew
) : ChatMessageRepository {

Expand All @@ -71,8 +69,7 @@ class OfflineFirstChatRepository @Inject constructor(
>
> = MutableSharedFlow()

override val updateMessageFlow:
Flow<ChatMessage>
override val updateMessageFlow: Flow<ChatMessage>
get() = _updateMessageFlow

private val _updateMessageFlow:
Expand All @@ -85,8 +82,7 @@ class OfflineFirstChatRepository @Inject constructor(
private val _lastCommonReadFlow:
MutableSharedFlow<Int> = MutableSharedFlow()

override val lastReadMessageFlow:
Flow<Int>
override val lastReadMessageFlow: Flow<Int>
get() = _lastReadMessageFlow

private val _lastReadMessageFlow:
Expand Down Expand Up @@ -278,7 +274,7 @@ class OfflineFirstChatRepository @Inject constructor(
var showUnreadMessagesMarker = true

while (true) {
if (!monitor.isOnline.first() || itIsPaused) {
if (!networkMonitor.isOnline.value || itIsPaused) {
Thread.sleep(HALF_SECOND)
} else {
// sync database with server
Expand Down Expand Up @@ -469,7 +465,7 @@ class OfflineFirstChatRepository @Inject constructor(
}

private suspend fun sync(bundle: Bundle): List<ChatMessageEntity>? {
if (!monitor.isOnline.first()) {
if (!networkMonitor.isOnline.value) {
Log.d(TAG, "Device is offline, can't load chat messages from server")
return null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.BehaviorSubject
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.apache.commons.lang3.builder.CompareToBuilder
Expand Down Expand Up @@ -1359,7 +1358,7 @@ class ConversationsListActivity :

override fun onItemLongClick(position: Int) {
this.lifecycleScope.launch {
if (showShareToScreen || !networkMonitor.isOnline.first()) {
if (showShareToScreen || !networkMonitor.isOnline.value) {
Log.d(TAG, "sharing to multiple rooms not yet implemented. onItemLongClick is ignored.")
} else {
val clickedItem: Any? = adapter!!.getItem(position)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ package com.nextcloud.talk.conversationlist.data.network

import android.util.Log
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
import com.nextcloud.talk.chat.data.network.OfflineFirstChatRepository
import com.nextcloud.talk.conversationlist.data.OfflineConversationsRepository
import com.nextcloud.talk.data.database.dao.ConversationsDao
import com.nextcloud.talk.data.database.mappers.asEntity
Expand Down Expand Up @@ -40,7 +39,7 @@ class OfflineFirstConversationsRepository @Inject constructor(
private val dao: ConversationsDao,
private val network: ConversationsNetworkDataSource,
private val chatNetworkDataSource: ChatNetworkDataSource,
private val monitor: NetworkMonitor,
private val networkMonitor: NetworkMonitor,
private val currentUserProviderNew: CurrentUserProviderNew
) : OfflineConversationsRepository {
override val roomListFlow: Flow<List<ConversationModel>>
Expand All @@ -59,7 +58,7 @@ class OfflineFirstConversationsRepository @Inject constructor(
val initialConversationModels = getListOfConversations(user.id!!)
_roomListFlow.emit(initialConversationModels)

if (monitor.isOnline.first()) {
if (networkMonitor.isOnline.value) {
val conversationEntitiesFromSync = getRoomsFromServer()
if (!conversationEntitiesFromSync.isNullOrEmpty()) {
val conversationModelsFromSync = conversationEntitiesFromSync.map(ConversationEntity::asModel)
Expand Down Expand Up @@ -106,8 +105,8 @@ class OfflineFirstConversationsRepository @Inject constructor(
private suspend fun getRoomsFromServer(): List<ConversationEntity>? {
var conversationsFromSync: List<ConversationEntity>? = null

if (!monitor.isOnline.first()) {
Log.d(OfflineFirstChatRepository.TAG, "Device is offline, can't load conversations from server")
if (!networkMonitor.isOnline.value) {
Log.d(TAG, "Device is offline, can't load conversations from server")
return null
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ import com.nextcloud.talk.translate.repositories.TranslateRepositoryImpl
import com.nextcloud.talk.users.UserManager
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import com.nextcloud.talk.utils.preferences.AppPreferences
import dagger.Module
import dagger.Provides
import okhttp3.OkHttpClient
Expand Down Expand Up @@ -180,15 +179,13 @@ class RepositoryModule {
chatMessagesDao: ChatMessagesDao,
chatBlocksDao: ChatBlocksDao,
dataSource: ChatNetworkDataSource,
appPreferences: AppPreferences,
networkMonitor: NetworkMonitor,
userProvider: CurrentUserProviderNew
): ChatMessageRepository {
return OfflineFirstChatRepository(
chatMessagesDao,
chatBlocksDao,
dataSource,
appPreferences,
networkMonitor,
userProvider
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Julius Linus <juliuslinus1@gmail.com>
* SPDX-FileCopyrightText: 2024 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package com.nextcloud.talk.data.network

import androidx.lifecycle.LiveData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow

/**
* Utility for reporting app connectivity status.
Expand All @@ -17,7 +18,7 @@ interface NetworkMonitor {
/**
* Returns the device's current connectivity status.
*/
val isOnline: Flow<Boolean>
val isOnline: StateFlow<Boolean>

/**
* Returns the device's current connectivity status as LiveData for better interop with Java code.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Julius Linus <juliuslinus1@gmail.com>
* SPDX-FileCopyrightText: 2024 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

Expand All @@ -11,67 +12,75 @@ import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest.Builder
import android.util.Log
import androidx.core.content.getSystemService
import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class NetworkMonitorImpl @Inject constructor(
private val context: Context
) : NetworkMonitor {

private val connectivityManager = context.getSystemService<ConnectivityManager>()!!

override val isOnlineLiveData: LiveData<Boolean>
get() = isOnline.asLiveData()

override val isOnline: Flow<Boolean> = callbackFlow {
val connectivityManager = context.getSystemService<ConnectivityManager>()
if (connectivityManager == null) {
channel.trySend(false)
channel.close()
return@callbackFlow
}

val networkRequest = Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
override val isOnline: StateFlow<Boolean> get() = _isOnline

val networkCallback = object : ConnectivityManager.NetworkCallback() {
private val networks = mutableSetOf<Network>()
private val _isOnline: StateFlow<Boolean> = callbackFlow {
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities)
val connected = networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED
)
trySend(connected)
Log.d(TAG, "Network status changed: $connected")
}

override fun onAvailable(network: Network) {
networks += network
channel.trySend(true)
override fun onUnavailable() {
super.onUnavailable()
trySend(false)
Log.d(TAG, "Network status: onUnavailable")
}

override fun onLost(network: Network) {
networks -= network
channel.trySend(networks.isNotEmpty())
super.onLost(network)
trySend(false)
Log.d(TAG, "Network status: onLost")
}
}

connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
override fun onAvailable(network: Network) {
super.onAvailable(network)
trySend(true)
Log.d(TAG, "Network status: onAvailable")
}
}

channel.trySend(connectivityManager.isCurrentlyConnected())
connectivityManager.registerDefaultNetworkCallback(callback)

awaitClose {
connectivityManager.unregisterNetworkCallback(networkCallback)
connectivityManager.unregisterNetworkCallback(callback)
}
}
.distinctUntilChanged()
.flowOn(Dispatchers.IO)
.conflate()
}.stateIn(
CoroutineScope(Dispatchers.IO),
SharingStarted.WhileSubscribed(COROUTINE_TIMEOUT),
false
)

private fun ConnectivityManager.isCurrentlyConnected() =
activeNetwork
?.let(::getNetworkCapabilities)
?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ?: false
companion object {
private val TAG = NetworkMonitorImpl::class.java.simpleName
private const val COROUTINE_TIMEOUT = 5000L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import java.util.Date
import javax.inject.Inject
Expand Down Expand Up @@ -134,7 +133,7 @@ class MessageActionsDialog(
initMenuAddToNote(
!message.isDeleted &&
!ConversationUtils.isNoteToSelfConversation(currentConversation) &&
networkMonitor.isOnline.first(),
networkMonitor.isOnline.value,
state.roomToken
)
}
Expand All @@ -147,16 +146,16 @@ class MessageActionsDialog(
}
}

initMenuItems()
initMenuItems(networkMonitor.isOnline.value)
}

private fun initMenuItems() {
private fun initMenuItems(isOnline: Boolean) {
this.lifecycleScope.launch {
initMenuItemTranslate(
!message.isDeleted &&
ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getCalculateMessageType() &&
CapabilitiesUtil.isTranslationsSupported(spreedCapabilities) &&
networkMonitor.isOnline.first()
isOnline
)
initMenuEditorDetails(message.lastEditTimestamp!! != 0L && !message.isDeleted)
initMenuReplyToMessage(message.replyable && hasChatPermission)
Expand All @@ -165,30 +164,30 @@ class MessageActionsDialog(
hasUserId(user) &&
hasUserActorId(message) &&
currentConversation?.type != ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL &&
networkMonitor.isOnline.first()
isOnline
)
initMenuEditMessage(isMessageEditable)
initMenuDeleteMessage(showMessageDeletionButton && networkMonitor.isOnline.first())
initMenuDeleteMessage(showMessageDeletionButton && isOnline)
initMenuForwardMessage(
ChatMessage.MessageType.REGULAR_TEXT_MESSAGE == message.getCalculateMessageType() &&
!(message.isDeletedCommentMessage || message.isDeleted) &&
networkMonitor.isOnline.first()
isOnline
)
initMenuRemindMessage(
!message.isDeleted &&
hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.REMIND_ME_LATER) &&
currentConversation!!.remoteServer.isNullOrEmpty() &&
networkMonitor.isOnline.first()
isOnline
)
initMenuMarkAsUnread(
message.previousMessageId > NO_PREVIOUS_MESSAGE_ID &&
ChatMessage.MessageType.SYSTEM_MESSAGE != message.getCalculateMessageType() &&
networkMonitor.isOnline.first()
isOnline
)
initMenuShare(messageHasFileAttachment || messageHasRegularText && networkMonitor.isOnline.first())
initMenuShare(messageHasFileAttachment || messageHasRegularText && isOnline)
initMenuItemOpenNcApp(
ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE == message.getCalculateMessageType() &&
networkMonitor.isOnline.first()
isOnline
)
initMenuItemSave(message.getCalculateMessageType() == ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE)
}
Expand Down

0 comments on commit 2e52eab

Please sign in to comment.