Changes the autocomplete list to show the username, display name, and avatar of each suggestion for @ mentions.
This commit is contained in:
parent
74aa866647
commit
fcdb507ef0
2 changed files with 106 additions and 15 deletions
|
@ -42,6 +42,7 @@ import android.provider.MediaStore;
|
||||||
import android.support.annotation.AttrRes;
|
import android.support.annotation.AttrRes;
|
||||||
import android.support.annotation.LayoutRes;
|
import android.support.annotation.LayoutRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v13.view.inputmethod.InputConnectionCompat;
|
import android.support.v13.view.inputmethod.InputConnectionCompat;
|
||||||
|
@ -59,8 +60,10 @@ import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.text.style.URLSpan;
|
import android.text.style.URLSpan;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
@ -86,6 +89,7 @@ import com.keylesspalace.tusky.util.ParserUtils;
|
||||||
import com.keylesspalace.tusky.util.SpanUtils;
|
import com.keylesspalace.tusky.util.SpanUtils;
|
||||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||||
import com.keylesspalace.tusky.view.EditTextTyped;
|
import com.keylesspalace.tusky.view.EditTextTyped;
|
||||||
|
import com.keylesspalace.tusky.view.RoundedTransformation;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
import com.squareup.picasso.Target;
|
import com.squareup.picasso.Target;
|
||||||
|
|
||||||
|
@ -320,8 +324,7 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
textEditor.setAdapter(new MentionAutoCompleteAdapter(this,
|
textEditor.setAdapter(new MentionAutoCompleteAdapter(this, R.layout.item_autocomplete));
|
||||||
android.R.layout.simple_dropdown_item_1line));
|
|
||||||
textEditor.setTokenizer(new MentionTokenizer());
|
textEditor.setTokenizer(new MentionTokenizer());
|
||||||
|
|
||||||
// Add any mentions to the text field when a reply is first composed.
|
// Add any mentions to the text field when a reply is first composed.
|
||||||
|
@ -1247,20 +1250,16 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does a synchronous search request for usernames fulfilling the given partial mention text.
|
* Does a synchronous search request for accounts fulfilling the given partial mention text.
|
||||||
*/
|
*/
|
||||||
private ArrayList<String> autocompleteMention(String mention) {
|
private ArrayList<Account> autocompleteMention(String mention) {
|
||||||
ArrayList<String> resultList = new ArrayList<>();
|
ArrayList<Account> resultList = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
List<Account> accountList = mastodonAPI.searchAccounts(mention, false, 5)
|
List<Account> accountList = mastodonAPI.searchAccounts(mention, false, 40)
|
||||||
.execute()
|
.execute()
|
||||||
.body();
|
.body();
|
||||||
/* Match only accounts whose username contains the partial mention text, because
|
if (accountList != null) {
|
||||||
searches also return matches for display names, which aren't relevant here. */
|
resultList.addAll(accountList);
|
||||||
for (Account account : accountList) {
|
|
||||||
if (account.username.toLowerCase().contains(mention.toLowerCase())) {
|
|
||||||
resultList.add(account.username);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, String.format("Autocomplete search for %s failed.", mention));
|
Log.e(TAG, String.format("Autocomplete search for %s failed.", mention));
|
||||||
|
@ -1344,11 +1343,13 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MentionAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
|
private class MentionAutoCompleteAdapter extends ArrayAdapter<Account> implements Filterable {
|
||||||
private ArrayList<String> resultList;
|
private ArrayList<Account> resultList;
|
||||||
|
private @LayoutRes int layoutId;
|
||||||
|
|
||||||
MentionAutoCompleteAdapter(Context context, @LayoutRes int resource) {
|
MentionAutoCompleteAdapter(Context context, @LayoutRes int resource) {
|
||||||
super(context, resource);
|
super(context, resource);
|
||||||
|
layoutId = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1357,13 +1358,18 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getItem(int index) {
|
public Account getItem(int index) {
|
||||||
return resultList.get(index);
|
return resultList.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override @NonNull
|
@Override @NonNull
|
||||||
public Filter getFilter() {
|
public Filter getFilter() {
|
||||||
return new Filter() {
|
return new Filter() {
|
||||||
|
@Override
|
||||||
|
public CharSequence convertResultToString(Object resultValue) {
|
||||||
|
return ((Account) resultValue).username;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FilterResults performFiltering(CharSequence constraint) {
|
protected FilterResults performFiltering(CharSequence constraint) {
|
||||||
FilterResults filterResults = new FilterResults();
|
FilterResults filterResults = new FilterResults();
|
||||||
|
@ -1385,5 +1391,40 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override @NonNull
|
||||||
|
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||||
|
View view = convertView;
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
|
||||||
|
if (convertView == null) {
|
||||||
|
LayoutInflater layoutInflater =
|
||||||
|
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
view = layoutInflater.inflate(layoutId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Account account = getItem(position);
|
||||||
|
if (account != null) {
|
||||||
|
TextView username = (TextView) view.findViewById(R.id.username);
|
||||||
|
TextView displayName = (TextView) view.findViewById(R.id.display_name);
|
||||||
|
ImageView avatar = (ImageView) view.findViewById(R.id.avatar);
|
||||||
|
String format = getContext().getString(R.string.status_username_format);
|
||||||
|
String formattedUsername = String.format(format, account.username);
|
||||||
|
username.setText(formattedUsername);
|
||||||
|
displayName.setText(account.getDisplayName());
|
||||||
|
if (!account.avatar.isEmpty()) {
|
||||||
|
Picasso.with(context)
|
||||||
|
.load(account.avatar)
|
||||||
|
.placeholder(R.drawable.avatar_default)
|
||||||
|
.error(R.drawable.avatar_error)
|
||||||
|
.transform(new RoundedTransformation(7, 0))
|
||||||
|
.into(avatar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
50
app/src/main/res/layout/item_autocomplete.xml
Normal file
50
app/src/main/res/layout/item_autocomplete.xml
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="42dp"
|
||||||
|
android:layout_height="42dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:id="@+id/avatar"
|
||||||
|
android:src="@drawable/avatar_default"
|
||||||
|
android:contentDescription="@null" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_toRightOf="@id/avatar"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/display_name"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textStyle="normal|bold" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="4dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/username"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="?android:textColorSecondary" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
Loading…
Reference in a new issue