There were crash reports for:
Exception java.lang.RuntimeException:
...
Caused by com.nextcloud.talk.utils.NoSupportedApiException:
at com.nextcloud.talk.utils.ApiUtils.getConversationApiVersion (ApiUtils.kt:134)
at com.nextcloud.talk.contacts.ContactsRepositoryImpl.<init> (ContactsRepositoryImpl.kt:28)
This could happen because of missing capabilities for user and should be fixed.
As a fallback, API v4 is guessed
Adding this as comment in the code as the root cause must be found..
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
For v21.0.0, the following crash was reported:
Exception java.lang.NullPointerException: null cannot be cast to non-null type com.nextcloud.talk.chat.data.model.ChatMessage
at com.nextcloud.talk.chat.ChatActivity.onLoadMore (ChatActivity.kt:3107)
at com.stfalcon.chatkit.messages.MessagesListAdapter.onLoadMore (MessagesListAdapter.java:148)
at com.stfalcon.chatkit.messages.RecyclerScrollMoreListener.onScrolled (RecyclerScrollMoreListener.java:82)
at androidx.recyclerview.widget.RecyclerView.dispatchOnScrolled (RecyclerView.java:5688)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep3 (RecyclerView.java:4741)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout (RecyclerView.java:4367)
at androidx.recyclerview.widget.RecyclerView.onLayout (RecyclerView.java:4919)
This is now improved:
- lastOrNull prevents exceptions if no matching item is found
- as? is a safe cast that returns null if the cast fails
Whole expression becomes null-safe, and id will be null if anything along the way doesn't match. Only when not null, onLoadMore continues.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
to be discussed: does it make sense to show a dialog instead? At least when it's created via 1:1 conversation
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
snackbars disaapear with the switch to a different screen. Toasts survive the switch so they are visible during the activities switch
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
switch video capture for calls between 4:3 and 16:9 ratio depending on portrait/landscape mode
Also: simplify placement of self video view (it was buggy) as well as applying the ratio there as well
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
The new photo picker does not need files permission. For other features, the permissions are already checked elsewhere
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
for ConversationInfoActivity, the old ContactsActivity was still used to add participants. This is now replaced by the ContactsActivityCompose, so ContactsActivity is now deleted
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
SetStatusBarColor() was called outside of the MaterialTheme() block
Also, "surface" has to be used to get the 'light primary color'
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
... as "components" package should be used for jetpack compose components that can be shared for multiple screens
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
- Most code removed from ChatActivity
- Most work in MediaPlayerManager
- Added BackgroundVoiceMessageCard
Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
A NPE was reported for ConversationsListActivity.kt:537
Adapter is accessed with !! while it is not safe to access in term of lifecycle.
So there could have been a race condition.
The overall problem is not solved and may even have to wait for migration to Compose.
This is just a quickfix for v21.0.0
Reported crash was :
Exception java.lang.NullPointerException:
at com.nextcloud.talk.conversationlist.ConversationsListActivity.filterConversation (ConversationsListActivity.kt:537)
at com.nextcloud.talk.conversationlist.ConversationsListActivity.setConversationList (ConversationsListActivity.kt:472)
at com.nextcloud.talk.conversationlist.ConversationsListActivity.access$setConversationList (ConversationsListActivity.kt:158)
at com.nextcloud.talk.conversationlist.ConversationsListActivity$initObservers$5$1.invokeSuspend (ConversationsListActivity.kt:398)
at com.nextcloud.talk.conversationlist.ConversationsListActivity$initObservers$5$1.invoke (Unknown Source:8)
at com.nextcloud.talk.conversationlist.ConversationsListActivity$initObservers$5$1.invoke (Unknown Source:4)
at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit (Emitters.kt:219)
at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catchImpl$2.emit (Errors.kt:154)
at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit (Emitters.kt:220)
at kotlinx.coroutines.flow.SharedFlowImpl.collect$suspendImpl (SharedFlow.kt:392)
at kotlinx.coroutines.flow.SharedFlowImpl.collect (Unknown Source)
at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1.collect (SafeCollector.common.kt:112)
at kotlinx.coroutines.flow.FlowKt__ErrorsKt.catchImpl (Errors.kt:152)
at kotlinx.coroutines.flow.FlowKt.catchImpl (Unknown Source:1)
at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catch$$inlined$unsafeFlow$1.collect (SafeCollector.common.kt:112)
at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1.collect (SafeCollector.common.kt:112)
at kotlinx.coroutines.flow.FlowKt__CollectKt.collect (Collect.kt:26)
at kotlinx.coroutines.flow.FlowKt.collect (Unknown Source:1)
at com.nextcloud.talk.conversationlist.ConversationsListActivity$initObservers$5.invokeSuspend (ConversationsListActivity.kt:399)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith (DispatchedContinuation.kt:363)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable (Cancellable.kt:26)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default (Cancellable.kt:21)
at kotlinx.coroutines.CoroutineStart.invoke (CoroutineStart.kt:88)
at kotlinx.coroutines.AbstractCoroutine.start (AbstractCoroutine.kt:123)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch (Builders.common.kt:52)
at kotlinx.coroutines.BuildersKt.launch (Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default (Builders.common.kt:43)
at kotlinx.coroutines.BuildersKt.launch$default (Unknown Source:1)
at com.nextcloud.talk.conversationlist.ConversationsListActivity.initObservers (ConversationsListActivity.kt:395)
at com.nextcloud.talk.conversationlist.ConversationsListActivity.onCreate (ConversationsListActivity.kt:261)
at android.app.Activity.performCreate (Activity.java:9149)
at android.app.Activity.performCreate (Activity.java:9127)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1526)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:4152)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:4361)
at android.app.ActivityThread.handleRelaunchActivityInner (ActivityThread.java:6446)
at android.app.ActivityThread.handleRelaunchActivity (ActivityThread.java:6329)
at android.app.servertransaction.ActivityRelaunchItem.execute (ActivityRelaunchItem.java:82)
at android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:60)
at android.app.servertransaction.TransactionExecutor.executeNonLifecycleItem (TransactionExecutor.java:174)
at android.app.servertransaction.TransactionExecutor.executeTransactionItems (TransactionExecutor.java:109)
at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:81)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2747)
at android.os.Handler.dispatchMessage (Handler.java:112)
at android.os.Looper.loopOnce (Looper.java:268)
at android.os.Looper.loop (Looper.java:384)
at android.app.ActivityThread.main (ActivityThread.java:8921)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:580)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:907)
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
without this fix, the scope may not have been initialized which threw the following exception:
Exception java.lang.RuntimeException:
at android.app.ActivityThread.callActivityOnStop (ActivityThread.java:5658)
at android.app.ActivityThread.performStopActivityInner (ActivityThread.java:5630)
at android.app.ActivityThread.handleStopActivity (ActivityThread.java:5695)
at android.app.servertransaction.StopActivityItem.execute (StopActivityItem.java:43)
at android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:60)
at android.app.servertransaction.TransactionExecutor.executeLifecycleItem (TransactionExecutor.java:282)
at android.app.servertransaction.TransactionExecutor.executeTransactionItems (TransactionExecutor.java:150)
at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:93)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2595)
at android.os.Handler.dispatchMessage (Handler.java:107)
at android.os.Looper.loopOnce (Looper.java:232)
at android.os.Looper.loop (Looper.java:317)
at android.app.ActivityThread.main (ActivityThread.java:8592)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:580)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:878)
Caused by kotlin.UninitializedPropertyAccessException: lateinit property scope has not been initialized
at com.nextcloud.talk.chat.data.network.OfflineFirstChatRepository.handleOnStop (OfflineFirstChatRepository.kt:807)
at com.nextcloud.talk.chat.viewmodels.ChatViewModel.onStop (ChatViewModel.kt:103)
at androidx.lifecycle.DefaultLifecycleObserverAdapter.onStateChanged (DefaultLifecycleObserverAdapter.kt:28)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent (LifecycleRegistry.jvm.kt:320)
at androidx.lifecycle.LifecycleRegistry.backwardPass (LifecycleRegistry.jvm.kt:272)
at androidx.lifecycle.LifecycleRegistry.sync (LifecycleRegistry.jvm.kt:289)
at androidx.lifecycle.LifecycleRegistry.moveToState (LifecycleRegistry.jvm.kt:142)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent (LifecycleRegistry.jvm.kt:124)
at androidx.lifecycle.ReportFragment$Companion.dispatch$lifecycle_runtime_release (ReportFragment.android.kt:190)
at androidx.lifecycle.ReportFragment$LifecycleCallbacks.onActivityPreStopped (ReportFragment.android.kt:135)
at android.app.Activity.dispatchActivityPreStopped (Activity.java:1633)
at android.app.Activity.performStop (Activity.java:9197)
at android.app.ActivityThread.callActivityOnStop (ActivityThread.java:5650)
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
because setData was called too late (after sendTempChatMessages was called from messageInputFragment, internalConversationId was not initialized in repository).
With this change, internalConversationId, credentials and urlForChatting are initialized earlier which should avoid the issue.
However conversationModel is still initialized quite late and should be accessed with caution. This could may be improved by better architecture..
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
onDestroy is not called when navigating to the next activity or bringing the app to background. That's why the adapter was not set to null and all messages were added another time the next time the activity comes to foreground. With this fix, the adapter is set to null in onStop.
All in all, the adapter handling may not be the best, but will be replaced by Compose anyway..
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
userManager.currentUser was called too often. I was not able to prove that a bug is related to it but i think it may fix some hidden bugs.
CurrentUserProviderImpl is now used throughout the code to access the current user.
userManager.currentUser is only used from CurrentUserProviderImpl whenever the _currentUser was null (should only happen on app startup)
To avoid multiple initialization of CurrentUserProviderImpl it was changed to be a @Singleton
The handling should soon be replaced with coroutine flows. However for the v21.0.0 release it's still done with RxJava to avoid bugs.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
- Uncommented out fetchOpenConversations
- Added fetchUsers to conversationList
- Made the messages appear first
Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
It could happen that when sending a message it was received on server but if the servers response is not received, the retry was triggered in the talk app.
This sometimes happened when internet connection was not the best.
Best would be that messages with the same referenceId would be refused on server side, but this won't be the case for now. So messages with the same referenceId are NOT refused as this would be too much overhead as there would be additional queries on server for every received message)
For now, the automatic retry logic is just removed so duplicated messages won't be created automatically.
However it's still possible to manually trigger the retry via button. In this case it is not guaranteed that there won't be duplicates.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
usersDao.getActiveUser() will return only one current users even if multiple exist for whatever reason.
By executing setUserAsActiveWithId(it.id) with the same user, it is made sure all other users current status is set to 0.
This change won't fix the root cause if multiple users are set to current, but it will make sure the state is fixed as soon as there is a query to get the active user.
In fact, this change might also make it harder to find the root cause because debugging may be more difficult! When searching for the root cause, always keep this in mind and maybe revert the change.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
To make sure getAnyUserAndSetAsActive() is invoked lazily and avoid any side effects, it's explicitly wrapped it in a lambda.
Maybe.defer ensures that getAnyUserAndSetAsActive() is not invoked until switchIfEmpty decides it’s needed.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Before, getAnyUserAndSetAsActive did only set a random first user to current=true without to check if there is any other current user.
So it was up to the calling function of getAnyUserAndSetAsActive to check this.
I did not identify a scenario where the getAnyUserAndSetAsActive could cause to set multiple users to current, but anyway the new implementation might fix some scenario that i could not reproduce.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
- First commit - Made options yellow
- Now possible to archive/unarchive conversations from dialog
- Now possible to archive and unarchive conversations in settings without leaving the screen
- Better UX
- Unread message bubble fix - no longer shows up when archive filter is set
Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
when being offline and no messages are set -> hide shimmer
when messages are received -> hide shimmer and "offlineNoMessages"-info
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Because long polling may have to be informed that the scopep was cancelled, the isActive checks are added so it can't happen that messages are added when they shouldn't.
I could not reproduce the scenario, anyway the checks should make sense in my opinion.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This is necessary especially to cancel the long polling when configuration change was made, e.g. screen was rotated. Otherwise multiple long polling requests would be running after configuration changes.
Because it not possible to launch a new coroutine in a scope that was canceled, it is necessary to re-initialize the scope.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
if chatMessageList is empty after handleSystemMessages it makes no sense to call the following methods.
Also processMessagesFromTheFuture was executed which caused that the popup was shown.
A better solution for the future should be to handle(remove) the "to-hide" system messages already in the repo or viewmodel
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
The idea to show the progress bar (aka shimmer animation) was that it show not be shown at all if loading messages happens in less than a second (this was a better UX in my opinion).
The idea was to hide the progress bar when
ChatMessageStartState was triggered.
However there can be moment when adapter is still empty after ChatMessageStartState and if in this moment the DELAY_TO_SHOW_PROGRESS_BAR is reached before the adapter is actually filled, the overlay happens.
It could be a solution to move the hiding of the progress bar, however then special cases might have to be handled.
For simplicity, the logic for DELAY_TO_SHOW_PROGRESS_BAR is removed. Progress bar is always shown without a delay so it wont be triggered on a later moment and can't overlay the chat.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
By using
networkMonitor.isOnline.first()
the function
unregisterNetworkCallback
was triggered, which sometimes causes the ConnectivityManager$TooManyRequestsException.
So each time isOnline.first() was called, the callbackFlow would:
- Register a new NetworkCallback.
- Emit a value and cancel the flow.
- Unregister the NetworkCallback.
The exception was:
Exception android.net.ConnectivityManager$TooManyRequestsException:
at android.net.ConnectivityManager.convertServiceException (ConnectivityManager.java:3771)
at android.net.ConnectivityManager.sendRequestForNetwork (ConnectivityManager.java:3960)
at android.net.ConnectivityManager.sendRequestForNetwork (ConnectivityManager.java:3967)
at android.net.ConnectivityManager.registerNetworkCallback (ConnectivityManager.java:4349)
at android.net.ConnectivityManager.registerNetworkCallback (ConnectivityManager.java:4319)
at com.nextcloud.talk.data.network.NetworkMonitorImpl$isOnline$1.invokeSuspend (NetworkMonitorImpl.kt:61)
To fix this, the cold flow from callbackFlow is converted to a StateFlow.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
It seems there could have been a race condition because currentUser was initialized too late.
I was not able to reproduce but hopefully this fixes it:
- initialize currentUser earlier (moved from onResume to onCreate)
- use currentUserProvider instead userManager
NPEs were reported via gplay:
1)
Exception java.lang.NullPointerException:
at com.nextcloud.talk.conversationlist.ConversationsListActivity.addToConversationItems (ConversationsListActivity.kt:851)
at com.nextcloud.talk.conversationlist.ConversationsListActivity.access$addToConversationItems (ConversationsListActivity.kt:151)
at com.nextcloud.talk.conversationlist.ConversationsListActivity$initObservers$5$1.invokeSuspend (ConversationsListActivity.kt:394)
at com.nextcloud.talk.conversationlist.ConversationsListActivity$initObservers$5$1.invoke (Unknown Source:8)
at com.nextcloud.talk.conversationlist.ConversationsListActivity$initObservers$5$1.invoke (Unknown Source:4)
2)
Exception java.lang.RuntimeException:
at android.app.ActivityThread.performResumeActivity (ActivityThread.java:5427)
at android.app.ActivityThread.handleResumeActivity (ActivityThread.java:5508)
...
Caused by java.lang.NullPointerException:
at com.nextcloud.talk.conversationlist.ConversationsListActivity.shouldShowNotificationWarning (ConversationsListActivity.kt:1557)
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
by moving networkMonitor.isOnline to separate check and by setting
binding.checkMark.visibility = View.INVISIBLE
binding.sendingProgress.visibility = View.GONE
before setting the status icons
to to handle recyclerview behavior
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
If user sent a message as a first message in today's chat, the temp message will be deleted when messages are retrieved from server, but also the date has to be deleted as it will be added again when the chat messages are added from server. Otherwise date "Today" would be shown twice.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
reason was that the UI was not yet loaded but isScrolledToBottom was already called, so findFirstVisibleItemPosition returned -1.
Fix for now is to return true for isScrolledToBottom when position is -1
They does not solve the root cause for now. It should be made sure the code is not executed until UI is ready.
A quick try with
repeatOnLifecycle(Lifecycle.State.STARTED)
when collecting getMessageFlow did not help.
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
TODO:
check id type --> see TODO "currentTimeMillies fails as id because later on in the model it's not Long but Int!!!!" in OfflineFirstChatRepository.kt
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>