Coder Social home page Coder Social logo

getstream / stream-chat-android Goto Github PK

View Code? Open in Web Editor NEW
1.4K 52.0 269.0 185.73 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.52% Kotlin 77.49% Shell 0.05% JavaScript 0.06% MDX 19.87%
chat-sdk java android chat chat-api messaging chatview hacktoberfest kotlin android-chat

stream-chat-android's Issues

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

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

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.

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) 

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:

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: 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

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)

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

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?

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

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

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

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?

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?

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

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.

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

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)

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.

User Presence/ Update users

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

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.)

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)

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?

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.

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.

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.

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");
    }
}

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

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)

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;
    }
}

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

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.