~singpolyma/cheogram-android

8952e69e9bd96113df005fe1a38beef6fb13456f — Stephen Paul Weber 1 year, 10 months ago 9684563
Allow editing tags on a contact
M build.gradle => build.gradle +1 -0
@@ 109,6 109,7 @@ dependencies {
    implementation 'io.github.nishkarsh:android-permissions:2.1.6'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'com.github.ipld:java-cid:v1.3.1'
    implementation 'com.splitwise:tokenautocomplete:3.0.2'
    implementation urlFile('https://gateway.pinata.cloud/ipfs/QmeqMiLxHi8AAjXobxr3QTfa1bSSLyAu86YviAqQnjxCjM/libwebrtc.aar', 'libwebrtc.aar')
    // INSERT
}

A src/cheogram/java/com/cheogram/android/TagEditorView.java => src/cheogram/java/com/cheogram/android/TagEditorView.java +57 -0
@@ 0,0 1,57 @@
package com.cheogram.android;

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

M src/main/java/eu/siacs/conversations/entities/Contact.java => src/main/java/eu/siacs/conversations/entities/Contact.java +12 -2
@@ 189,12 189,18 @@ public class Contact implements ListItem, Blockable {
        return jid;
    }

    @Override
    public List<Tag> getTags(Context context) {
    public List<Tag> getGroupTags() {
        final ArrayList<Tag> tags = new ArrayList<>();
        for (final String group : getGroups(true)) {
            tags.add(new Tag(group, UIHelper.getColorForName(group)));
        }
        return tags;
    }

    @Override
    public List<Tag> getTags(Context context) {
        final ArrayList<Tag> tags = new ArrayList<>();
        tags.addAll(getGroupTags());
        for (final String tag : getSystemTags(true)) {
            tags.add(new Tag(tag, UIHelper.getColorForName(tag)));
        }


@@ 344,6 350,10 @@ public class Contact implements ListItem, Blockable {
        this.systemAccount = lookupUri;
    }

    public void setGroups(List<String> groups) {
        this.groups = new JSONArray(groups);
    }

    private Collection<String> getGroups(final boolean unique) {
        final Collection<String> groups = unique ? new HashSet<>() : new ArrayList<>();
        for (int i = 0; i < this.groups.length(); ++i) {

M src/main/java/eu/siacs/conversations/entities/ListItem.java => src/main/java/eu/siacs/conversations/entities/ListItem.java +2 -1
@@ 2,6 2,7 @@ package eu.siacs.conversations.entities;

import android.content.Context;

import java.io.Serializable;
import java.util.List;
import java.util.Locale;



@@ 16,7 17,7 @@ public interface ListItem extends Comparable<ListItem>, AvatarService.Avatarable

	List<Tag> getTags(Context context);

	final class Tag {
	final class Tag implements Serializable {
		private final String name;
		private final int color;


M src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java => src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +36 -0
@@ 21,6 21,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;


@@ 33,9 34,13 @@ import androidx.databinding.DataBindingUtil;

import org.openintents.openpgp.util.OpenPgpUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;


@@ 44,6 49,7 @@ import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlSession;
import eu.siacs.conversations.databinding.ActivityContactDetailsBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Bookmark;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.ListItem;
import eu.siacs.conversations.services.AbstractQuickConversationsService;


@@ 266,9 272,11 @@ 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();


@@ 313,6 321,34 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
                    });
                    text.setText(contact.getServerName());
                    text.requestFocus();
                    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);
                    binding.editTags.setVisibility(View.VISIBLE);
                    if (save != null) save.setVisible(true);
                } else {
                    menuItem.collapseActionView();

M src/main/res/layout/activity_contact_details.xml => src/main/res/layout/activity_contact_details.xml +9 -0
@@ 67,6 67,15 @@
                                android:layout_marginTop="4dp"
                                android:orientation="horizontal"></com.wefika.flowlayout.FlowLayout>

                            <com.cheogram.android.TagEditorView
                                android:id="@+id/edit_tags"
                                android:visibility="gone"
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:layout_marginBottom="4dp"
                                android:layout_marginLeft="-4dp"
                                android:layout_marginTop="-4dp" />

                            <TextView
                                android:id="@+id/details_lastseen"
                                android:layout_width="wrap_content"