hanggrian / socialview

Android TextView and EditText with hashtag, mention, and hyperlink support
http://hanggrian.com/socialview/
Apache License 2.0
324 stars 81 forks source link

Crash when writing mention/tag #15

Closed CripyIce closed 7 years ago

CripyIce commented 7 years ago

Hi there friend, Been using a lot your awesome library, but i came across an issue that never occurred to me before. I made an custom adapter for the mentions and assigned it to the SocialAutoCompleteTextView. When i enter a mention or even a hashtag and check if there are mentions or hashtags i get a crash (after pressing a 'post' button that checks if there are mentions/hashtags).

My custom adapter:

public class MentionsCustomAdapter extends SocialAdapter<Mention> {
    private Filter filter = new SocialFilter() {
        @Override
        public CharSequence convertResultToString(Object resultValue) {
            return ((Mention) resultValue).getUsername();
        }
    };

    public MentionsCustomAdapter(@NonNull Context context) {
        super(context, R.layout.item_mentions, R.id.textview_mention_username);
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_mentions, parent, false);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        Mention item = getItem(position);
        if (item != null) {
            if (item.getAvatar() != null) {
                Glide.with(getContext()).load(item.getAvatar()).dontAnimate().into(holder.imageView);
            }

            holder.textViewUsername.setText(item.getUsername());
            if (ViewsKt.setVisibleBy(holder.textViewDisplayName, !TextUtils.isEmpty(item.getDisplayname())))
                holder.textViewDisplayName.setText(item.getDisplayname());
        }
        return convertView;
    }

    @NonNull
    @Override
    public Filter getFilter() {
        return filter;
    }

    private static class ViewHolder {
        @NonNull
        private final CircularImageView imageView;
        @NonNull
        private final TextView textViewUsername;
        @NonNull
        private final TextView textViewDisplayName;

        private ViewHolder(@NonNull View view) {
            imageView = view.findViewById(R.id.imageview_mention_username);
            textViewUsername = view.findViewById(R.id.textview_mention_username);
            textViewDisplayName = view.findViewById(R.id.textview_mention_displayname);
        }
    }
}

Adapter assignment:

        mentionArrayAdapter = new MentionsCustomAdapter(this);
        hashtagArrayAdapter = new HashtagAdapter(this);

        postContent.setMentionAdapter(mentionArrayAdapter);
        postContent.setHashtagAdapter(hashtagArrayAdapter);

My checks:

                String mentionsToString = "";
                if (postContent.getMentions().size() > 0) {
                    StringBuilder builder = new StringBuilder();
                    for (String s : postContent.getMentions()) {
                        for (TagsModel model : originalTagsModels) {
                            if (s.equals(model.getTagName().replace(" ", ""))) {
                                builder.append(model.getTagId()).append(",");
                                content = content.replace(s.replace(" ", ""), String.valueOf(model.getTagId()));
                            }
                        }
                    }
                    mentionsToString = builder.toString();
                }

                String tagsToString = "";
                if (postContent.getHashtags().size() > 0) {
                    StringBuilder builder2 = new StringBuilder();
                    for (String s : postContent.getHashtags()) {
                        builder2.append(s).append(",");
                    }
                    tagsToString = builder2.toString();
                }

This is the line where it crashes: if (postContent.getHashtags().size() > 0) { With the following error:

07-28 10:48:45.180 5694-5694/app.example.com E/AndroidRuntime: FATAL EXCEPTION: main
                                                                  Process: app.example.com, PID: 5694
                                                                  java.lang.ArrayIndexOutOfBoundsException: length=2; index=2
                                                                      at java.util.regex.Matcher.group(Matcher.java:370)
                                                                      at com.hendraanggrian.socialview.SocialView$DefaultImpls.newList(SocialView.kt:111)
                                                                      at com.hendraanggrian.socialview.SocialView$DefaultImpls.getHashtags(SocialView.kt:104)
                                                                      at com.hendraanggrian.widget.SocialAutoCompleteTextView.getHashtags(SocialAutoCompleteTextView.kt:15)
                                                                      at app.example.com.posts.NewPostActivity$9.onClick(NewPostActivity.java:408)
                                                                      at android.view.View.performClick(View.java:6256)
                                                                      at android.view.View$PerformClick.run(View.java:24697)
                                                                      at android.os.Handler.handleCallback(Handler.java:789)
                                                                      at android.os.Handler.dispatchMessage(Handler.java:98)
                                                                      at android.os.Looper.loop(Looper.java:164)
                                                                      at android.app.ActivityThread.main(ActivityThread.java:6541)
                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                      at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

BTW, i'm using the latest library version 0.15.2 Thanks!

CripyIce commented 7 years ago

Another thing i just noticed, it also happens when pressing a Mention in SocialTextView i get an exception that there a no HashTags..

hanggrian commented 7 years ago

Hi @CripyIce, your adapter and ViewHolder looks okay, so it looks like a legit bug. Do you mind sharing text content of your SocialAutoCompleteTextView when the error occurs so I can recreate them?

Anyway, completely unrelated, socialview-commons imports another library I wrote for extending Picasso usage. I see that you are using Glide in your custom adapter, so you really don't need that other library, you can exclude it with:

compile("com.hendraanggrian:socialview-commons:$version") {
    exclude group: 'com.hendraanggrian', module: 'picasso-utils'
}
CripyIce commented 7 years ago

Hi @HendraAnggrian , Thanks for the tip ;) This is the text i am writing down: Hi there @eitantest. image

hanggrian commented 7 years ago

@CripyIce I have identified the first issue, thank you for the input. Can you elaborate the second issue about mention click listener so I can fix it too in the next release?

CripyIce commented 7 years ago

@HendraAnggrian This is the code i'm using for the onclick listener:

        textView.setOnMentionClickListener(new Function2<SocialView, CharSequence, Unit>() {
            @Override
            public Unit invoke(SocialView socialView, CharSequence charSequence) {
                for (PostMentionModel s : model) {
                    if (s.getNickname().equals(charSequence.toString())) {
                        Intent intent = new Intent(context, ProfileActivity.class);
                        intent.putExtra("userId", s.getUserId());
                        context.startActivity(intent);
                    }
                }
                return null;
            }
        });

        textView.setOnHashtagClickListener(new Function2<SocialView, CharSequence, Unit>() {
            @Override
            public Unit invoke(SocialView socialView, CharSequence charSequence) {
                for (PostTagsModel s : model2) {
                    if (s.getTagName().equals(charSequence.toString())) {
                        Intent intent = new Intent(context, TagResultsActivity.class);
                        intent.putExtra("tagId", s.getTagId());
                        intent.putExtra("tagName", s.getTagName());
                        context.startActivity(intent);
                    }
                }
                return null;
            }
        });

it crashes on this line of code: for (PostTagsModel s : model2) { notice that now i'm using version 0.15.0 with the same code (except that i have to use "SociableView") and it's working great.

hanggrian commented 7 years ago

Okay I've uploaded version 0.16.0 that addresses these 2 separate issues. Would you kindly try test it again?

CripyIce commented 7 years ago

Hi @HendraAnggrian, works like a charm! But i detected another bug, should i write it here or open a new issue?

hanggrian commented 7 years ago

@CripyIce Whichever you are comfortable with :) I'm listening either way

CripyIce commented 7 years ago

@HendraAnggrian so i'll write it down here :) If i write down a mention and click the user name i get something like that (the mention i wanted and a space to start a new word): image After the space i got, i want to continue writing of course, so i begin to write down a letter and get something like that: image So far so good. Now if i'll erase that word it will delete the mention and i will get something like that: image A bit hard to explain, but i hope you understood :)

hanggrian commented 7 years ago

So far so good. Now if i'll erase that word it will delete the mention and i will get something like that:

@CripyIce Specifically, which character of @5HTP h did you backspace into @5hh? In my test case, you have to backspace two characters (last space and h) to achieve it. If it is true that you backspaced only once, it is most likely a bug I have to discover more. If instead you backspaced twice like I did, I think it is the default behavior of AppCompatMultiAutoCompleteTextView.Tokenizer.

CripyIce commented 7 years ago

@HendraAnggrian it happens to me with every word i type after a mention and even with different mention name.

hanggrian commented 7 years ago

@CripyIce I'm sorry now I don't much understand what you mean. I would need a detailed list of steps you have taken, along with expected and actual result of each step. Or quite simply a short video of it.

CripyIce commented 7 years ago

@HendraAnggrian sorry for the delay, but it seems it only happens on the Emulator.. strange. You can close this issue :)

hanggrian commented 7 years ago

@CripyIce strange indeed, but thank you for confirming!