Coder Social home page Coder Social logo

getstream / stream-chat-android Goto Github PK

View Code? Open in Web Editor NEW
1.4K 47.0 260.0 319.21 MB

:speech_balloon: Android Chat SDK ➜ Stream Chat API. UI component libraries for chat apps. Kotlin & Jetpack Compose messaging SDK for Android chat

Home Page: https://getstream.io/chat/sdk/android/

License: Other

Java 2.63% Kotlin 76.80% Shell 0.05% JavaScript 0.06% MDX 20.45%
chat-sdk java android chat chat-api messaging chatview hacktoberfest kotlin android-chat

stream-chat-android's Introduction

Official Android SDK for Stream Chat

API

This is the official Android SDK for Stream Chat, a service for building chat and messaging applications. This library includes both a low-level chat SDK and a set of reusable UI components. Most users start with the UI components, and fall back to the lower level API when they want to customize things.

We're proud to say that we're the first Android Chat SDK that supports Jetpack Compose! We released our Compose UI Components one day after the official Jetpack Compose 1.0 release and our team members have been working hard on it since then.

Now it's mature and stable enough for us to officially recommend it for all new applications and all modern chat implementations. If you're looking for something highly customizable and extremely performant, check out our Compose SDK.

The Android SDK supports both Kotlin and Java, but we strongly recommend using Kotlin.

Note: The Compose SDK supports only Kotlin, since Compose uses Kotlin compiler plugins to process the UI.

🔗 Quick Links

👩‍💻 Free for Makers 👨‍💻

Stream is free for most side and hobby projects. To qualify, your project/company needs to have < 5 team members and < $10k in monthly revenue. For complete pricing details, visit our Chat Pricing Page.

🗺️ Overview and Documentation 📚

This SDK consists of two low-level artifacts you can build on:

We also have two UI SDKs. You can use our Compose UI Components SDK, or if you're using older UI solutions, the XML-based UI Components:

Learn more about the modules by visiting the documentation.

📖 Tutorial

The best place to start is the Compose Chat Messaging Tutorial. It teaches you the basics of using the Compose Chat SDK and also shows how to make frequently required changes.

Note: If you're using older UI toolkits, like XML, you can follow the Android Chat Messaging Tutorial which features the XML-based UI Components.

🛠️ Installation and Getting Started 🚀

See the Dependencies and Getting Started pages of the documentation.

🔮 Sample Apps

Compose Sample App

Our Jetpack Compose implementation comes with its own example app, which you can play with to see how awesome Compose is.

To run the sample app, start by cloning this repo:

git clone [email protected]:GetStream/stream-chat-android.git

Next, open Android Studio and open the newly created project folder. You'll want to run the stream-chat-android-compose-sample module.

Since Compose is a highly customizable SDK, we're eager to hear your feedback on how it helps you build complex Chat UI. Join us in this repo's discussions or tweet at us @getstream_io!

Sample App

However, if you're still using XML due to technical limitations, our UI Components SDK includes a fully functional example app featuring threads, reactions, typing indicators, optimistic UI updates and offline storage. To run the sample app, start by cloning this repo:

git clone [email protected]:GetStream/stream-chat-android.git

Next, open Android Studio and open the newly created project folder. You'll want to run the stream-chat-android-ui-components-sample app.

Other Sample Apps

We also maintain a dedicated repository for fully-fledged sample applications at GetStream/Android-Samples.

💡 Supported features 🎨

Here are some of the features that the SDK supports out-of-the-box:

  • Channels list UI
  • Channel UI
  • Message reactions
  • Link previews
  • Image, video and file attachments
  • Editing and deleting messages
  • Typing indicators
  • Read indicators
  • Push notifications
  • Image gallery
  • GIF support
  • Light and dark themes
  • Style customization
  • UI customization
  • Threads
  • Slash commands
  • Markdown message formatting
  • Unread message counts

For more, see the SDK's website.

🛠️ R8 / ProGuard

When utilizing R8, the rules for shrinking and obfuscation are applied automatically.

If you are using ProGuard, you will need to add the following rules from client and ui-common modules to your application.

You might also need apply rules for Coroutines, Retrofit and OkHttp which are dependencies of the SDK.

💼 We are hiring!

We've recently closed a $38 million Series B funding round and we keep actively growing. Our APIs are used by more than a billion end-users, and you'll have a chance to make a huge impact on the product within a team of the strongest engineers all over the world. Check out our current openings and apply via Stream's website.

License

Copyright (c) 2014-2022 Stream.io Inc. All rights reserved.

Licensed under the Stream License;
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   https://github.com/GetStream/stream-chat-android/blob/main/LICENSE

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.

stream-chat-android's People

Contributors

adasiewiczr avatar adrian09h avatar aleksandar-apostolov avatar andriizhumela avatar bevzaanton avatar bychkovdmitry avatar carterhudson avatar danielnovak avatar elevenetc avatar emitenma avatar filbabic avatar github-actions[bot] avatar jcminarro avatar jeffdgr8 avatar jeroenleenarts avatar kanat avatar leandroborgesferreira avatar liviu-timar avatar marintolic avatar nikomancy avatar philipbrito avatar samiuelson avatar skydoves avatar stream-pr-merger[bot] avatar stream-public-bot avatar tbarbugli avatar tgazica avatar tschellenbach avatar zetbaitsu avatar zsmb13 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stream-chat-android's Issues

Feature Request: Provide custom listener for ChannelHeaderView back button

The ChannelHeaderView has a back button that finishes the activity when pressed:

binding.tvBack.setOnClickListener(view ->{
      if(viewModel.isThread())
          viewModel.initThread();
      else
          ((Activity) getContext()).finish();
});

(ChannelHeaderView, lines: 96-101, v. 1.10.0)

My current use case calls for the Stream hierarchy of custom views to be in Fragments (the entry point being a tab within a BottomNavigationView), so it'd be nice to have this back button hook into the NavigationController of my Fragment instead. This way, my backstack will be able to coexist with the Stream custom views.

If the consumer were able to provide a click listener for the back button, that would satisfy the backstack use case.

Offline support 2.0

  1. Current offline support needs a thorough round of testing before we make it default enabled instead of default disabled.

  2. Push notifications should ensure that local storage is up to date:

  • receive push notification
  • query data and store it in the local storage
  • show the push notification to the user (and it will be there when they open the app)
  1. Background/foreground behaviour needs to improve:
  • we always send the push notification
    background:
  • we close the websocket connection after 1 minute
    foreground:
  • if the websocket connection was closed we recover
  1. Image sending
  • You should be able to send a message with an image, without waiting for the image to upload
  1. Data cleanup
  • the offline storage should remove data that is no longer needed to preserve storage
  1. Schema export
  • Once we enable offline by default we should export the room schema
  1. Correctly handle user changes (user.updated, not user.presence.changed)

  2. Muting users or hiding channels should also be stored locally

Permissions request triggered only by Activity

When user opens attachment drawer in https://github.com/GetStream/stream-chat-android/blob/master/library/src/main/java/com/getstream/sdk/chat/view/MessageInputView.java it first asks for permission using only Activity context, while Fragment is passed as null

@Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.iv_send) {
            this.onSendMessage(binding.etMessage.getText().toString(), viewModel.isEditing());
        } else if (id == R.id.iv_openAttach) {
            binding.setIsAttachFile(true);
            PermissionChecker.permissionCheck((Activity) v.getContext(), null);
            messageInputClient.onClickOpenBackGroundView(MessageInputType.ADD_FILE);
        }
    }

It would be great to be able to pass Fragment to https://github.com/GetStream/stream-chat-android/blob/master/library/src/main/java/com/getstream/sdk/chat/view/MessageInputView.java so that the permissions request is triggered by the fragment itself.
Otherwise every permission request result needs to be handed down by activity to the fragment that handles chat.

channel.query vs channel.watch

The JS library uses channel.query and channel.watch. The android lib only exposes channel.query with the behaviour of channel.watch. This is super confusing

Expose live count from channel view model

We should make it easier to get the unread count for a channel.

Proposal:

  • expose a int getUnreadCount that returns current count
  • expose a LiveData object LiveData<Number> getLiveUnreadCount

@tschellenbach what do you think, shall we expose both or just the live data?

MessageListView is scrolling/blinking for every new message

What did you do?

Sent/received new message.

What did you expect to happen?

The list to scroll to the bottom if it was scrolled before sending/receiving message, so that I can see the last message.

What happened instead?

The whole list blinks when the message is received/sent and scrolls a little bit to the top - more or less the height of 1-2 single line text messages

GetStream Environment

GetStream Chat version: 1.8.7
Android version: 9.0
Android Studio version: 3.5
Device: OnePlus 6

Additional context

Seems like the chat is scrolling every time something updates(reaction etc.)

String.equals on Null

"Crash
NPE: String.equals on a null object reference
at com.getstream.sdk.chat.view.MessageListView$1.getDrawableForAttachment(MessageListView.java:182)"

I've asked for a full stack trace, will update once i get it

NPE/Crash: channel is null in sendStoppedTyping

In some case when sample app is started NPE is thrown.

java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Date com.getstream.sdk.chat.model.Channel.getLastStartTypingEvent()' on a null object reference
    at com.getstream.sdk.chat.viewmodel.ChannelViewModel$Looper.sendStoppedTyping(ChannelViewModel.java:1147)
    at com.getstream.sdk.chat.viewmodel.ChannelViewModel$Looper.run(ChannelViewModel.java:1177)
private void sendStoppedTyping() {
    if (channel.getLastStartTypingEvent() == null) {
        return;
    }
}

MessageListView scrolls up when keyboard is opened/closed

What did you do?

Opened/closed keyboard in an activity with android:windowSoftInputMode="adjustPan"

What did you expect to happen?

The list to get panned in a way that whatever was visible on the list is still visible after opening/closing keyboard

What happened instead?

When the keyboard is opening the list scrolls up a little bit(more or less the height of 1-2 single line text messages). If you scroll it back to the bottom and close the keyboard the same issue occurs.

GetStream Environment

GetStream Chat version: 1.8.7
Android version: 9.0
Android Studio version: 3.5
Device: OnePlus 6

onSetUserCompleted issue

  • queryChannels never completes
  • its waiting for the onSetUserCompleted
  • the logs show that the client did in fact connect (health check events are there)

This is affecting Tourlina.

It's a real issue but I haven't found a way to replicate it.

  • pixel 3, api version 29

code for the channel activity fragment and layout:

Callback errors do not get reported to the SDK client

It looks like certain listeners do not allow the SDK client to handles errors. Specifically classes that implement within the SDK:

  • com.getstream.sdk.chat.storage.Storage.OnQueryListener
  • com.getstream.sdk.chat.rest.interfaces.QueryChannelListCallback

The anonymous classes that implement these interfaces don't provide a way to let the SDK client know when errors occur. Some are even marked as // TODO.

We need this functionality in order to report errors to users, debugging tools, retry, and/or alter our logic.

Some use cases that come to mind:

  • User has no network connectivity
  • Server is not responding
  • Latency is so high that we need to indicate to the user that we're in a loading state

MessageInputView stuck in disabled state after failed send

After sending a message while having poor/none connection, the MessageInputView gets stuck in a state where you cannot send any more text messages.
Clearing the textfield, editing it, resending the failed message or establishing a good connection doesn't fix it
Screenshot_20191007-104700__01

RuntimeException: Failed to call observer method

2019-10-07 19:33:30.507 10951-10951/de.tourlina.Tourlina.staging E/AndroidRuntime: FATAL EXCEPTION: main
Process: de.tourlina.Tourlina.staging, PID: 10951
java.lang.RuntimeException: Unable to resume activity {de.tourlina.Tourlina.staging/de.tourlina.tourlina.MainActivity}: java.lang.RuntimeException: Failed to call observer method
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4205)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4237)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.RuntimeException: Failed to call observer method
at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:226)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185)
at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:36)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
at androidx.lifecycle.ProcessLifecycleOwner.activityResumed(ProcessLifecycleOwner.java:118)
at androidx.lifecycle.ProcessLifecycleOwner$2.onResume(ProcessLifecycleOwner.java:85)
at androidx.lifecycle.ReportFragment.dispatchResume(ReportFragment.java:68)
at androidx.lifecycle.ReportFragment.onResume(ReportFragment.java:89)
at android.app.Fragment.performResume(Fragment.java:2580)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1346)
at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1581)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1642)
at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3052)
at android.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:3014)
at android.app.FragmentController.dispatchResume(FragmentController.java:206)
at android.app.Activity.performResume(Activity.java:7961)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4195)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4237) 
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52) 
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:214) 
at android.app.ActivityThread.main(ActivityThread.java:7356) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.Handler.removeCallbacksAndMessages(java.lang.Object)' on a null object reference
at com.getstream.sdk.chat.rest.WebSocketService.disconnect(WebSocketService.java:168)
at com.getstream.sdk.chat.rest.core.Client.disconnect(Client.java:991)
at com.getstream.sdk.chat.rest.core.Client.reconnect(Client.java:1003)
at com.getstream.sdk.chat.StreamChat$2$1.resume(StreamChat.java:118)
at com.getstream.sdk.chat.StreamLifecycleObserver.onResume(StreamLifecycleObserver.java:18)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:216)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194) 
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185) 
at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:36) 
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361) 
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300) 
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339) 
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145) 
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131) 
at androidx.lifecycle.ProcessLifecycleOwner.activityResumed(ProcessLifecycleOwner.java:118) 
at androidx.lifecycle.ProcessLifecycleOwner$2.onResume(ProcessLifecycleOwner.java:85) 
at androidx.lifecycle.ReportFragment.dispatchResume(ReportFragment.java:68) 
at androidx.lifecycle.ReportFragment.onResume(ReportFragment.java:89) 
at android.app.Fragment.performResume(Fragment.java:2580) 
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1346) 
at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1581) 
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1642) 
at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3052) 
at android.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:3014) 
at android.app.FragmentController.dispatchResume(FragmentController.java:206) 
at android.app.Activity.performResume(Activity.java:7961) 
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4195) 
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4237) 
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52) 
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:214) 
at android.app.ActivityThread.main(ActivityThread.java:7356) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

App crashes when attachment is not sent correctly

 FATAL EXCEPTION: main
    Process: REDACTED, PID: 28038
    java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
        at com.getstream.sdk.chat.view.MessageListView$1.getDrawableForAttachment(MessageListView.java:182)
        at com.getstream.sdk.chat.adapter.AttachmentViewHolder.configImageThumbBackground(AttachmentViewHolder.java:107)
        at com.getstream.sdk.chat.adapter.AttachmentViewHolder.configMediaAttach(AttachmentViewHolder.java:179)
        at com.getstream.sdk.chat.adapter.AttachmentViewHolder.configAttachment(AttachmentViewHolder.java:76)
        at com.getstream.sdk.chat.adapter.AttachmentViewHolder.bind(AttachmentViewHolder.java:58)
        at com.getstream.sdk.chat.adapter.AttachmentListItemAdapter.onBindViewHolder(AttachmentListItemAdapter.java:68)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
        at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3336)
        at com.getstream.sdk.chat.view.AttachmentListView.onMeasure(Unknown Source:13)
        at android.view.View.measure(View.java:24938)
        at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:722)
        at androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:373)
        at androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure.measureChildren(BasicMeasure.java:112)
        at androidx.constraintlayout.solver.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:213)
        at androidx.constraintlayout.solver.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:113)
        at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1458)
        at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1537)
        at android.view.View.measure(View.java:24938)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.measureChildWithMargins(RecyclerView.java:9119)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1583)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:587)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4194)
        at android.view.View.layout(View.java:22397)
        at android.view.ViewGroup.layout(ViewGroup.java:6572)
        at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1654)
        at android.view.View.layout(View.java:22397)
        at android.view.ViewGroup.layout(ViewGroup.java:6572)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:22397)

Channels request return empty after switching user

What did you do?

1. Initialised client
2. Set user to user X
3. Sent query to fetch user X channels
4. Query successfully returned array of channels for user X
4.5 Disconnected client(first I didn't do that, then I tried with it)
5. Set user to user Y
6. Sent query to fetch user Y channels
7. Query successfully returned but with empty array of channels for user Y
8. Completely restarted the app(StreamChat got reinitialised)
9. Set user to user Y
10. Sent query to fetch user Y channels
11. Query successfully returned array of channels for user Y

What did you expect to happen?

To receive user Y channels after he got successfully set on the client.

What happened instead?

The array of channels returned empty, despite passing an exact cid in the request.

GetStream Environment

GetStream Chat version: 1.8.7 with later commits(master)
Android version: 9.0.0
Android Studio: 3.5
Device: OnePlus6

Additional context

1. Despite disconnecting the client or setting user Y, channels belonging to user X still hang around in activeChannels in client object.
2. Channels query is exactly the same every time with the exception of clientId(which changes after disconnecting client before setting new user) and cid(different for both users)

Autocomplete behaviour

If one were to type "@A", then click a name from the autocomplete list, it would fill the EditText as "@A[the name]". Using the user name from the tutorial, it would show "@aparanoid Android". I would expect it to replace all of the text in the EditText

(Livly reported this)

Feature request: Prevent messages from being auto read

In our app ChatFragment is only one of many fragments alive at the same time in the main screen. When user is not looking at the ChatFragment at the moment, we tend to display number of unread messages on the chat navigation icon.

1. Since ChatFragment doesn't go to sleep while browsing other fragment, nor it gets destroyed, the MessageListView is marking all messages read as soon as they arrive.

2. I'm not entirely sure about this one, but I think that ChannelViewModel is marking the messages as read too, even before MessageListView does.
https://github.com/GetStream/stream-chat-android/blob/master/library/src/main/java/com/getstream/sdk/chat/viewmodel/ChannelViewModel.java#L531

It would be great to have some kind of flag on (possibly) ChannelViewModel that would block markLastMessageRead() from executing.

Add possibility to close attachment drawer programmatically

The attachment drawer in com.getstream.sdk.chat.view.MessageInputView asks for permissions upon opening. But then if the permissions are denied it's not possible to close the drawer programatically. That way user can still click options inside the drawer, some of which will crash the app due to missing permissions.

Retry logic when querying channels needs improvement/refactor

The anonymous class that is handling the callback for querying channels has retry logic when an error occurs.

Specifically ChannelListViewModel line 311:

            public void onError(String errMsg, int errCode) {
                Log.e(TAG, "onError for loading the channels " + errMsg);
                if (attempt > 100) {
                    Log.e(TAG, "tried more than 100 times, give up now");
                    return;
                }
                if (!client().isConnected()) {
                    return;
                }
                int sleep = Math.min(500 * (attempt * attempt + 1), 30000);
                Log.d(TAG, "retrying in " + sleep);
                retryLooper.postDelayed(() -> {
                    queryChannelsInner(attempt + 1);
                }, sleep);
            }

The logic in this onError() method does not log an error occurs until 100 attempts are made. That's a significant amount of time before it's logged. What's the reason for such a high number of attempts?

This is related to #92 where it would be nice to inform the SDK client that an error occurs so we can present UI to the user that something went wrong.

Hardcoded channel type in ApiService.java

What did you do?

I tried to send messages to channel which type is commerce

What did you expect to happen?

That the messages will be sent and appear correctly on receiving end.

What happened instead?

Messages were sent successfully but with channel type messaging which is hardcoded for almost every endpoint in ApiService.java, hence the messages were never received by anyone else.

GetStream Environment

GetStream Chat version: 1.8.7
Android version: Any
Android studio version: Any
Device: Any

File upload 2.0

  • You should be able to send a message before the upload is completed
  • The upload should show the upload progress instead of the loading icon

Feature request: Allow for custom viewhlder view types in MessageViewHolderFactory

In MessageViewHolderFactory:

public MessageListItemType getEntityViewType(MessageListItem messageListItem, Boolean mine, List<Position> positions) 

requires that returned type is MessageListItemType, effectively making it impossible to provide custom viewhodlder in

 public BaseMessageListItemViewHolder createMessageViewHolder(MessageListItemAdapter adapter, ViewGroup parent, MessageListItemType viewType)

Would it be possible to make getEntityViewType return Int like in regular adapter, so that we could provide custom BaseMessageListItemViewHolder in createMessageViewHolder?

Empty photo/video selection if file doesn't exist

If there is files paths don't exist selection is just white. So it might be confusing for a user. Not sure exactly why file.exits() returns false, but it turns out it's a possible case.

Possible solutions:

  • some error icon instead of not loading preview at all
  • check file existence before filling MediaAttachment

screen

public void bind(Attachment attachment, final OnItemClickListener listener) {
    if (file.exists()) {
 	//load image       
    } else {
        Log.d(TAG, "There is no image from this path");
    }
}

CDN overwrite

Most of our customers use our CDN during development, but change to their own when going live.

At the moment it's not easy to overwrite the behaviour of how files are uploaded

image

I think we should expose this as a setting on the Client object... @tbarbugli what do you think?

User Presence/ Update users

User objects are not automatically updated by the SDK when the user updates or their online/offline presence changes

totalUnreadCount not updated for currently set user

Continuation of #100

The currently set user is not updated when new messages from other users arrive, leaving the totalUnreadCount stick to the value received when the user was initialised, up until the point when this user sends some message himself.

It checks out with this piece of code in Client.java

public void onAnyEvent(Event event) {
                    // if an event contains the current user update it
                    // this also captures notification.mutes_updated
                    if (event.getMe() != null) {
                        state.setCurrentUser(event.getMe());
                    }
                    if (event.getType() == EventType.NOTIFICATION_MUTES_UPDATED) {
                        Log.i(TAG, "Mutes updated");
                    }

                    // if an event contains a user update that user
                    // handles user updates, presence changes etc.
                    if (event.getUser() != null) {
                        state.updateUser(event.getUser());
                    }

                    // update the unread count if it is present on the event
                    if (event.getTotalUnreadCount() != null) {
                        state.setTotalUnreadCount(event.getTotalUnreadCount().intValue());
                    }
                    if (event.getUnreadChannels() != null) {
                        state.setUnreadChannels(event.getUnreadChannels().intValue());
                    }

                    // if an event contains an updated channel write the update
                    if (event.getChannel() != null) {
                        state.updateUsersForChannel(event.getChannel().getChannelState());
                    }
                }

Could you give me a hint how can I update the currently set user every time new message is received/deleted or read? Is the client.queryUsers() way to go here?

Token expiration

Provide an interface to handle token expiration on the client. That allows the client to do the work necessary to send an API request to authenticate, get/set a new token, and continue the work that was expected in the callback. In this way, you're able to contextually continue the work that was expected and provide the library client the ability to run their own code as needed.

Custom data is not parsed from JSON correctly

Messages, Channels and Attachment can have custom data; at the moment we store all custom fields in a HashMap field (extraData) but we don't serialize it correctly to JSON nor deserialize it correctly from API responses.

Example:

{"id": "the-message-id", "color": "blue"}

The message in this case should have "color": "blue" in the extra data (and it should produce the same data when marshaled to json)

Bug: NullPointerException when channelState.getLastMessage() is null

The tutorial provided in Stream's documentation instructs the reader to copy the sample code from the tutorial as-is.

When using the sample credentials provided, the lastMessage for the ChannelState object that is returned is null, and causes the line channelState.getLastMessage().setStatus(MessageStatus.RECEIVED); to throw an NPE.

Stacktrace:

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.getstream.sdk.chat.rest.Message.setStatus(com.getstream.sdk.chat.enums.MessageStatus)' on a null object reference
at com.getstream.sdk.chat.rest.core.Client$3$1.onResponse(Client.java:470)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:71)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Dependency: `com.github.getstream:stream-chat-android:1.9.1'

Steps to Reproduce:

  1. Copy setup from tutorial
  2. Copy ChannelList section from tutorial
  3. Run the application
  4. Observe NPE

Chat initializes after activity is put in background and then back in foreground

I implemented the Getstream chat into my Android app, but the chat only loads after I put the app in the background and come back to it. Before that, inside onCreate where I do all the logic like in the example here.

The log shows successful connect to the /connect endpoint and 201 response for device registration on /devices endpoint. After that the progress bar keeps spinning and this is shown in logcat every second:

2019-10-04 14:33:29.621 9284-9434/de.tourlina.Tourlina.staging D/WebSocketService: WebSocket Response : {"connection_id":"f06c52e2-6628-42b3-a485-796eca46e6ae","cid":"*","type":"health.check","created_at":"2019-10-04T12:33:27.10919249Z"} 2019-10-04 14:33:58.555 9284-9435/de.tourlina.Tourlina.staging W/ourlina.stagin: Accessing hidden method Ljava/lang/ThreadGroup;-><init>()V (greylist-max-o, reflection, denied) 2019-10-04 14:33:58.572 9284-9435/de.tourlina.Tourlina.staging W/ourlina.stagin: Accessing hidden method Ljava/util/concurrent/locks/ReentrantLock$Sync;-><init>()V (greylist-max-o, reflection, denied) 2019-10-04 14:33:58.590 9284-9435/de.tourlina.Tourlina.staging W/ourlina.stagin: Accessing hidden method Ljava/net/InetSocketAddress;-><init>()V (greylist-max-o,core-platform-api, reflection, denied) 2019-10-04 14:33:58.595 9284-9435/de.tourlina.Tourlina.staging W/ourlina.stagin: Accessing hidden method Ljava/net/InetSocketAddress;-><init>()V (greylist-max-o,core-platform-api, reflection, denied)

I tried putting all the code in onStart, onResume and so on, but nothing worked. What could the issue be?

Bug: Concurrent Modification Exception

Steps to Reproduce:

  1. Load channel list
  2. Wait an arbitrary amount of time (I waited around 20 seconds)
  3. Close out of app
  4. Open app again

Reproducibility: ~10%

Stacktrace:

2019-09-23 11:05:34.074 17365-17448/com.osh.streamchatpoc E/AndroidRuntime: FATAL EXCEPTION: WSS - event handler thread
Process: com.osh.streamchatpoc, PID: 17365
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at com.getstream.sdk.chat.rest.core.Client.connectionResolved(Client.java:379)
at com.getstream.sdk.chat.rest.WebSocketService$EchoWebSocketListener.lambda$onMessage$1$WebSocketService$EchoWebSocketListener(WebSocketService.java:272)
at com.getstream.sdk.chat.rest.-$$Lambda$WebSocketService$EchoWebSocketListener$f9N2ARRqFxybqCam0RKr38hIg2U.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at com.getstream.sdk.chat.rest.WebSocketService$EventHandlerThread.run(WebSocketService.java:323)

Version: 1.10.0

Attachment video files are duplicated

Utils.getAllShownImagesPath returns duplicates. Debugged it briefly and noticed that count and attachments.size are different, count is valid. So most probably the issue is in the method logic.

Reproducible on emulator.

screen-duplicates

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.