tags editor
This commit is contained in:
parent
dca3e80bad
commit
fee1a67332
|
@ -87,6 +87,8 @@ dependencies {
|
||||||
implementation 'com.github.bumptech.glide:glide:4.15.1'
|
implementation 'com.github.bumptech.glide:glide:4.15.1'
|
||||||
implementation 'info.androidhive:imagefilters:1.0.7'
|
implementation 'info.androidhive:imagefilters:1.0.7'
|
||||||
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
||||||
|
|
||||||
|
implementation 'com.splitwise:tokenautocomplete:3.0.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
|
|
18
src/conversations/res/layout/actionview_edit.xml
Normal file
18
src/conversations/res/layout/actionview_edit.xml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?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:addStatesFromChildren="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/search_field"
|
||||||
|
style="@style/Widget.Conversations.SearchView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:focusable="true"
|
||||||
|
android:imeOptions="flagNoExtractUi|actionDone"
|
||||||
|
android:inputType="textPersonName"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -184,12 +184,19 @@ public class Contact implements ListItem, Blockable {
|
||||||
return jid;
|
return jid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public List<Tag> getGroupTags() {
|
||||||
public List<Tag> getTags(Context context) {
|
|
||||||
final ArrayList<Tag> tags = new ArrayList<>();
|
final ArrayList<Tag> tags = new ArrayList<>();
|
||||||
for (final String group : getGroups(true)) {
|
for (final String group : getGroups(true)) {
|
||||||
tags.add(new Tag(group, UIHelper.getColorForName(group)));
|
tags.add(new Tag(group, UIHelper.getColorForName(group)));
|
||||||
}
|
}
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tag> getTags(Context context) {
|
||||||
|
final HashSet<Tag> tags = new HashSet<>();
|
||||||
|
tags.addAll(getGroupTags());
|
||||||
|
|
||||||
Presence.Status status = getShownStatus();
|
Presence.Status status = getShownStatus();
|
||||||
if (status != Presence.Status.OFFLINE) {
|
if (status != Presence.Status.OFFLINE) {
|
||||||
tags.add(UIHelper.getTagForStatus(context, status));
|
tags.add(UIHelper.getTagForStatus(context, status));
|
||||||
|
@ -197,7 +204,10 @@ public class Contact implements ListItem, Blockable {
|
||||||
if (isBlocked()) {
|
if (isBlocked()) {
|
||||||
tags.add(new Tag(context.getString(R.string.blocked), 0xff2e2f3b));
|
tags.add(new Tag(context.getString(R.string.blocked), 0xff2e2f3b));
|
||||||
}
|
}
|
||||||
return tags;
|
if (!showInRoster() && getSystemAccount() != null) {
|
||||||
|
tags.add(new Tag("Android", UIHelper.getColorForName("Android")));
|
||||||
|
}
|
||||||
|
return new ArrayList<>(tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean match(Context context, String needle) {
|
public boolean match(Context context, String needle) {
|
||||||
|
@ -316,6 +326,10 @@ public class Contact implements ListItem, Blockable {
|
||||||
return systemAccount;
|
return systemAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGroups(List<String> groups) {
|
||||||
|
this.groups = new JSONArray(groups);
|
||||||
|
}
|
||||||
|
|
||||||
public void setSystemAccount(Uri lookupUri) {
|
public void setSystemAccount(Uri lookupUri) {
|
||||||
this.systemAccount = lookupUri;
|
this.systemAccount = lookupUri;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.siacs.conversations.entities;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@ -16,7 +17,7 @@ public interface ListItem extends Comparable<ListItem>, AvatarService.Avatarable
|
||||||
|
|
||||||
List<Tag> getTags(Context context);
|
List<Tag> getTags(Context context);
|
||||||
|
|
||||||
final class Tag {
|
final class Tag implements Serializable {
|
||||||
private final String name;
|
private final String name;
|
||||||
private final int color;
|
private final int color;
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,12 @@ package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -16,13 +18,18 @@ import android.provider.ContactsContract.Intents;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.style.RelativeSizeSpan;
|
import android.text.style.RelativeSizeSpan;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -32,9 +39,13 @@ import androidx.databinding.DataBindingUtil;
|
||||||
|
|
||||||
import org.openintents.openpgp.util.OpenPgpUtils;
|
import org.openintents.openpgp.util.OpenPgpUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
|
@ -43,6 +54,7 @@ import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
|
||||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
|
||||||
import eu.siacs.conversations.databinding.ActivityContactDetailsBinding;
|
import eu.siacs.conversations.databinding.ActivityContactDetailsBinding;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.entities.Bookmark;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
import eu.siacs.conversations.entities.Contact;
|
||||||
import eu.siacs.conversations.entities.ListItem;
|
import eu.siacs.conversations.entities.ListItem;
|
||||||
import eu.siacs.conversations.services.AbstractQuickConversationsService;
|
import eu.siacs.conversations.services.AbstractQuickConversationsService;
|
||||||
|
@ -55,6 +67,7 @@ import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
||||||
import eu.siacs.conversations.ui.util.GridManager;
|
import eu.siacs.conversations.ui.util.GridManager;
|
||||||
import eu.siacs.conversations.ui.util.JidDialog;
|
import eu.siacs.conversations.ui.util.JidDialog;
|
||||||
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
|
import eu.siacs.conversations.ui.util.MenuDoubleTabUtil;
|
||||||
|
import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
|
||||||
import eu.siacs.conversations.utils.AccountUtils;
|
import eu.siacs.conversations.utils.AccountUtils;
|
||||||
import eu.siacs.conversations.utils.Compatibility;
|
import eu.siacs.conversations.utils.Compatibility;
|
||||||
import eu.siacs.conversations.utils.Emoticons;
|
import eu.siacs.conversations.utils.Emoticons;
|
||||||
|
@ -62,6 +75,7 @@ import eu.siacs.conversations.utils.IrregularUnicodeDetector;
|
||||||
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.utils.XmppUri;
|
import eu.siacs.conversations.utils.XmppUri;
|
||||||
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
import eu.siacs.conversations.xml.Namespace;
|
||||||
import eu.siacs.conversations.xmpp.Jid;
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
|
||||||
|
@ -73,6 +87,8 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
private final int REQUEST_SYNC_CONTACTS = 0x28cf;
|
private final int REQUEST_SYNC_CONTACTS = 0x28cf;
|
||||||
ActivityContactDetailsBinding binding;
|
ActivityContactDetailsBinding binding;
|
||||||
private MediaAdapter mMediaAdapter;
|
private MediaAdapter mMediaAdapter;
|
||||||
|
protected MenuItem edit = null;
|
||||||
|
protected MenuItem save = null;
|
||||||
|
|
||||||
private Contact contact;
|
private Contact contact;
|
||||||
private final DialogInterface.OnClickListener removeFromRoster = new DialogInterface.OnClickListener() {
|
private final DialogInterface.OnClickListener removeFromRoster = new DialogInterface.OnClickListener() {
|
||||||
|
@ -185,7 +201,6 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void refreshUiReal() {
|
protected void refreshUiReal() {
|
||||||
invalidateOptionsMenu();
|
|
||||||
populateView();
|
populateView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +209,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
if (http) {
|
if (http) {
|
||||||
return "https://conversations.im/i/" + XmppUri.lameUrlEncode(contact.getJid().asBareJid().toEscapedString());
|
return "https://conversations.im/i/" + XmppUri.lameUrlEncode(contact.getJid().asBareJid().toEscapedString());
|
||||||
} else {
|
} else {
|
||||||
return "xmpp:" + contact.getJid().asBareJid().toEscapedString();
|
return "xmpp:" + Uri.encode(contact.getJid().asBareJid().toEscapedString(), "@/+");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +257,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
recreate();
|
recreate();
|
||||||
} else {
|
} else {
|
||||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
this.showDynamicTags = preferences.getBoolean(SettingsActivity.SHOW_DYNAMIC_TAGS, false);
|
this.showDynamicTags = preferences.getBoolean(SettingsActivity.SHOW_DYNAMIC_TAGS, getResources().getBoolean(R.bool.show_dynamic_tags));
|
||||||
this.showLastSeen = preferences.getBoolean("last_activity", false);
|
this.showLastSeen = preferences.getBoolean("last_activity", false);
|
||||||
}
|
}
|
||||||
binding.mediaWrapper.setVisibility(Compatibility.hasStoragePermission(this) ? View.VISIBLE : View.GONE);
|
binding.mediaWrapper.setVisibility(Compatibility.hasStoragePermission(this) ? View.VISIBLE : View.GONE);
|
||||||
|
@ -262,6 +277,19 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void saveEdits() {
|
||||||
|
binding.editTags.setVisibility(View.GONE);
|
||||||
|
if (edit != null) {
|
||||||
|
EditText text = edit.getActionView().findViewById(R.id.search_field);
|
||||||
|
contact.setServerName(text.getText().toString());
|
||||||
|
contact.setGroups(binding.editTags.getObjects().stream().map(tag -> tag.getName()).collect(Collectors.toList()));
|
||||||
|
ContactDetailsActivity.this.xmppConnectionService.pushContactToServer(contact);
|
||||||
|
populateView();
|
||||||
|
edit.collapseActionView();
|
||||||
|
}
|
||||||
|
if (save != null) save.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(final MenuItem menuItem) {
|
public boolean onOptionsItemSelected(final MenuItem menuItem) {
|
||||||
if (MenuDoubleTabUtil.shouldIgnoreTap()) {
|
if (MenuDoubleTabUtil.shouldIgnoreTap()) {
|
||||||
|
@ -285,16 +313,56 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
.setPositiveButton(getString(R.string.delete),
|
.setPositiveButton(getString(R.string.delete),
|
||||||
removeFromRoster).create().show();
|
removeFromRoster).create().show();
|
||||||
break;
|
break;
|
||||||
|
case R.id.action_save:
|
||||||
|
saveEdits();
|
||||||
|
break;
|
||||||
case R.id.action_edit_contact:
|
case R.id.action_edit_contact:
|
||||||
Uri systemAccount = contact.getSystemAccount();
|
Uri systemAccount = contact.getSystemAccount();
|
||||||
if (systemAccount == null) {
|
if (systemAccount == null) {
|
||||||
quickEdit(contact.getServerName(), R.string.contact_name, value -> {
|
menuItem.expandActionView();
|
||||||
contact.setServerName(value);
|
EditText text = menuItem.getActionView().findViewById(R.id.search_field);
|
||||||
ContactDetailsActivity.this.xmppConnectionService.pushContactToServer(contact);
|
text.setOnEditorActionListener((v, actionId, event) -> {
|
||||||
populateView();
|
saveEdits();
|
||||||
return null;
|
return true;
|
||||||
}, true);
|
});
|
||||||
|
text.setText(contact.getServerName());
|
||||||
|
text.requestFocus();
|
||||||
|
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
if (imm != null) {
|
||||||
|
imm.showSoftInput(text, InputMethodManager.SHOW_IMPLICIT);
|
||||||
|
}
|
||||||
|
binding.tags.setVisibility(View.GONE);
|
||||||
|
binding.editTags.clearSync();
|
||||||
|
for (final ListItem.Tag group : contact.getGroupTags()) {
|
||||||
|
binding.editTags.addObjectSync(group);
|
||||||
|
}
|
||||||
|
ArrayList<ListItem.Tag> tags = new ArrayList<>();
|
||||||
|
for (final Account account : xmppConnectionService.getAccounts()) {
|
||||||
|
for (Contact contact : account.getRoster().getContacts()) {
|
||||||
|
tags.addAll(contact.getTags(this));
|
||||||
|
}
|
||||||
|
for (Bookmark bookmark : account.getBookmarks()) {
|
||||||
|
tags.addAll(bookmark.getTags(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Comparator<Map.Entry<ListItem.Tag,Integer>> sortTagsBy = Map.Entry.comparingByValue(Comparator.reverseOrder());
|
||||||
|
sortTagsBy = sortTagsBy.thenComparing(entry -> entry.getKey().getName());
|
||||||
|
|
||||||
|
ArrayAdapter<ListItem.Tag> adapter = new ArrayAdapter<>(
|
||||||
|
this,
|
||||||
|
android.R.layout.simple_list_item_1,
|
||||||
|
tags.stream()
|
||||||
|
.collect(Collectors.toMap((x) -> x, (t) -> 1, (c1, c2) -> c1 + c2))
|
||||||
|
.entrySet().stream()
|
||||||
|
.sorted(sortTagsBy)
|
||||||
|
.map(e -> e.getKey()).collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
binding.editTags.setAdapter(adapter);
|
||||||
|
if (showDynamicTags) binding.editTags.setVisibility(View.VISIBLE);
|
||||||
|
if (save != null) save.setVisible(true);
|
||||||
} else {
|
} else {
|
||||||
|
menuItem.collapseActionView();
|
||||||
|
if (save != null) save.setVisible(false);
|
||||||
Intent intent = new Intent(Intent.ACTION_EDIT);
|
Intent intent = new Intent(Intent.ACTION_EDIT);
|
||||||
intent.setDataAndType(systemAccount, Contacts.CONTENT_ITEM_TYPE);
|
intent.setDataAndType(systemAccount, Contacts.CONTENT_ITEM_TYPE);
|
||||||
intent.putExtra("finishActivityOnSaveCompleted", true);
|
intent.putExtra("finishActivityOnSaveCompleted", true);
|
||||||
|
@ -320,6 +388,8 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.contact_details, menu);
|
getMenuInflater().inflate(R.menu.contact_details, menu);
|
||||||
AccountUtils.showHideMenuItems(menu);
|
AccountUtils.showHideMenuItems(menu);
|
||||||
|
edit = menu.findItem(R.id.action_edit_contact);
|
||||||
|
save = menu.findItem(R.id.action_save);
|
||||||
MenuItem block = menu.findItem(R.id.action_block);
|
MenuItem block = menu.findItem(R.id.action_block);
|
||||||
MenuItem unblock = menu.findItem(R.id.action_unblock);
|
MenuItem unblock = menu.findItem(R.id.action_unblock);
|
||||||
MenuItem edit = menu.findItem(R.id.action_edit_contact);
|
MenuItem edit = menu.findItem(R.id.action_edit_contact);
|
||||||
|
@ -342,6 +412,19 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
edit.setVisible(false);
|
edit.setVisible(false);
|
||||||
delete.setVisible(false);
|
delete.setVisible(false);
|
||||||
}
|
}
|
||||||
|
edit.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||||
|
SoftKeyboardUtils.hideSoftKeyboard(ContactDetailsActivity.this);
|
||||||
|
binding.editTags.setVisibility(View.GONE);
|
||||||
|
if (save != null) save.setVisible(false);
|
||||||
|
populateView();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemActionExpand(MenuItem item) { return true; }
|
||||||
|
});
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,6 +432,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
if (contact == null) {
|
if (contact == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (binding.editTags.getVisibility() != View.GONE) return;
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
setTitle(contact.getDisplayName());
|
setTitle(contact.getDisplayName());
|
||||||
if (contact.showInRoster()) {
|
if (contact.showInRoster()) {
|
||||||
|
@ -549,6 +633,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
|
||||||
xmppConnectionService.getAttachments(account, contact.getJid().asBareJid(), limit, this);
|
xmppConnectionService.getAttachments(account, contact.getJid().asBareJid(), limit, this);
|
||||||
this.binding.showMedia.setOnClickListener((v) -> MediaBrowserActivity.launch(this, contact));
|
this.binding.showMedia.setOnClickListener((v) -> MediaBrowserActivity.launch(this, contact));
|
||||||
}
|
}
|
||||||
|
|
||||||
populateView();
|
populateView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package eu.siacs.conversations.ui.widget;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.tokenautocomplete.TokenCompleteTextView;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.R;
|
||||||
|
import eu.siacs.conversations.entities.ListItem;
|
||||||
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
|
|
||||||
|
public class TagEditorView extends TokenCompleteTextView<ListItem.Tag> {
|
||||||
|
public TagEditorView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setTokenClickStyle(TokenCompleteTextView.TokenClickStyle.Delete);
|
||||||
|
setThreshold(1);
|
||||||
|
performBestGuess(false);
|
||||||
|
allowCollapse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearSync() {
|
||||||
|
for (ListItem.Tag tag : getObjects()) {
|
||||||
|
removeObjectSync(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View getViewForObject(ListItem.Tag tag) {
|
||||||
|
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
||||||
|
final TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag, (ViewGroup) getParent(), false);
|
||||||
|
tv.setText(tag.getName());
|
||||||
|
tv.setBackgroundColor(tag.getColor());
|
||||||
|
return tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ListItem.Tag defaultObject(String completionText) {
|
||||||
|
return new ListItem.Tag(completionText, UIHelper.getColorForName(completionText));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldIgnoreToken(ListItem.Tag tag) {
|
||||||
|
return getObjects().contains(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFocusChanged(boolean hasFocus, int direction, Rect previous) {
|
||||||
|
super.onFocusChanged(hasFocus, direction, previous);
|
||||||
|
performCompletion();
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,6 +68,16 @@
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:orientation="horizontal"></com.wefika.flowlayout.FlowLayout>
|
android:orientation="horizontal"></com.wefika.flowlayout.FlowLayout>
|
||||||
|
|
||||||
|
<eu.siacs.conversations.ui.widget.TagEditorView
|
||||||
|
android:id="@+id/edit_tags"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:hint="Tags"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:layout_marginLeft="-4dp"
|
||||||
|
android:layout_marginTop="-4dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/details_lastseen"
|
android:id="@+id/details_lastseen"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_edit_contact"
|
android:id="@+id/action_edit_contact"
|
||||||
android:icon="?attr/icon_edit"
|
android:icon="?attr/icon_edit"
|
||||||
android:orderInCategory="10"
|
android:orderInCategory="10"
|
||||||
app:showAsAction="always"
|
app:showAsAction="collapseActionView|always"
|
||||||
android:title="@string/action_edit_contact"/>
|
android:title="@string/action_edit_contact"
|
||||||
|
app:actionLayout="@layout/actionview_edit" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_save"
|
||||||
|
android:icon="@drawable/ic_save_white_24dp"
|
||||||
|
android:title="@string/save"
|
||||||
|
android:visible="false"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_share"
|
android:id="@+id/action_share"
|
||||||
|
|
|
@ -353,7 +353,7 @@
|
||||||
<string name="no_application_found_to_open_link">No app found to open link</string>
|
<string name="no_application_found_to_open_link">No app found to open link</string>
|
||||||
<string name="no_application_found_to_view_contact">No app found to view contact</string>
|
<string name="no_application_found_to_view_contact">No app found to view contact</string>
|
||||||
<string name="pref_show_dynamic_tags">Dynamic Tags</string>
|
<string name="pref_show_dynamic_tags">Dynamic Tags</string>
|
||||||
<string name="pref_show_dynamic_tags_summary">Display read-only tags underneath contacts</string>
|
<string name="pref_show_dynamic_tags_summary">Allow organizing with tags</string>
|
||||||
<string name="enable_notifications">Enable notifications</string>
|
<string name="enable_notifications">Enable notifications</string>
|
||||||
<string name="no_conference_server_found">No group chat server found</string>
|
<string name="no_conference_server_found">No group chat server found</string>
|
||||||
<string name="conference_creation_failed">Could not create group chat</string>
|
<string name="conference_creation_failed">Could not create group chat</string>
|
||||||
|
|
Loading…
Reference in a new issue