mirror of
https://codeberg.org/Mercury-IM/Mercury-IM
synced 2024-06-15 16:14:52 +02:00
Poc: Add/Remove roster groups
This commit is contained in:
parent
441cf7c902
commit
206fd1c8da
|
@ -8,6 +8,7 @@ import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -18,6 +19,7 @@ import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.lifecycle.ViewModelStoreOwner;
|
import androidx.lifecycle.ViewModelStoreOwner;
|
||||||
|
|
||||||
|
import com.google.android.material.chip.Chip;
|
||||||
import com.google.android.material.chip.ChipGroup;
|
import com.google.android.material.chip.ChipGroup;
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
||||||
|
|
||||||
|
@ -26,10 +28,11 @@ import org.mercury_im.messenger.R;
|
||||||
import org.mercury_im.messenger.ui.chat.ChatActivity;
|
import org.mercury_im.messenger.ui.chat.ChatActivity;
|
||||||
import org.mercury_im.messenger.util.ColorUtil;
|
import org.mercury_im.messenger.util.ColorUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import io.reactivex.Completable;
|
import io.reactivex.Completable;
|
||||||
import io.reactivex.Observable;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
|
@ -59,6 +62,9 @@ public class ContactDetailFragment extends Fragment {
|
||||||
@BindView(R.id.fab)
|
@BindView(R.id.fab)
|
||||||
ExtendedFloatingActionButton fab;
|
ExtendedFloatingActionButton fab;
|
||||||
|
|
||||||
|
@BindView(R.id.button_add_to_group)
|
||||||
|
Button button;
|
||||||
|
|
||||||
private ContactDetailViewModel viewModel;
|
private ContactDetailViewModel viewModel;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -98,6 +104,15 @@ public class ContactDetailFragment extends Fragment {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
button.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
viewModel.addContactToRosterGroup().subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,5 +147,24 @@ public class ContactDetailFragment extends Fragment {
|
||||||
viewModel.getContactAddress().observe(this, address -> contactAddress.setText(address));
|
viewModel.getContactAddress().observe(this, address -> contactAddress.setText(address));
|
||||||
viewModel.getContactPresenceStatus().observe(this, presenceText -> contactPresence.setText(presenceText));
|
viewModel.getContactPresenceStatus().observe(this, presenceText -> contactPresence.setText(presenceText));
|
||||||
viewModel.getContactAccountAddress().observe(this, address -> contactAccount.setText(address));
|
viewModel.getContactAccountAddress().observe(this, address -> contactAccount.setText(address));
|
||||||
|
viewModel.getContactGroups().observe(this, this::setRosterGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setRosterGroups(List<String> groups) {
|
||||||
|
contactGroups.removeAllViews();
|
||||||
|
for (String group : groups) {
|
||||||
|
Chip chip = new Chip(contactGroups.getContext());
|
||||||
|
chip.setText(group);
|
||||||
|
chip.setOnLongClickListener(new View.OnLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
viewModel.removeContactFromRosterGroup(group)
|
||||||
|
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
contactGroups.addView(chip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ import org.jivesoftware.smack.packet.Presence;
|
||||||
import org.jivesoftware.smack.roster.PresenceEventListener;
|
import org.jivesoftware.smack.roster.PresenceEventListener;
|
||||||
import org.jivesoftware.smack.roster.Roster;
|
import org.jivesoftware.smack.roster.Roster;
|
||||||
import org.jivesoftware.smack.roster.RosterEntry;
|
import org.jivesoftware.smack.roster.RosterEntry;
|
||||||
|
import org.jivesoftware.smack.roster.RosterGroup;
|
||||||
|
import org.jxmpp.jid.BareJid;
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.mercury_im.messenger.MercuryImApplication;
|
import org.mercury_im.messenger.MercuryImApplication;
|
||||||
|
@ -23,10 +25,15 @@ import org.mercury_im.messenger.entity.contact.Peer;
|
||||||
import org.mercury_im.messenger.ui.avatar.AvatarDrawable;
|
import org.mercury_im.messenger.ui.avatar.AvatarDrawable;
|
||||||
import org.mercury_im.messenger.util.CombinedPresenceListener;
|
import org.mercury_im.messenger.util.CombinedPresenceListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import io.reactivex.Completable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
@ -46,6 +53,7 @@ public class ContactDetailViewModel extends ViewModel {
|
||||||
private MutableLiveData<String> contactPresenceStatus = new MutableLiveData<>("Going down the rabbit hole.");
|
private MutableLiveData<String> contactPresenceStatus = new MutableLiveData<>("Going down the rabbit hole.");
|
||||||
private MutableLiveData<String> contactName = new MutableLiveData<>("Alice Wonderland");
|
private MutableLiveData<String> contactName = new MutableLiveData<>("Alice Wonderland");
|
||||||
private MutableLiveData<String> contactAccountAddress = new MutableLiveData<>("mad@hatter.lit");
|
private MutableLiveData<String> contactAccountAddress = new MutableLiveData<>("mad@hatter.lit");
|
||||||
|
private MutableLiveData<List<String>> contactGroups = new MutableLiveData<>(Collections.emptyList());
|
||||||
|
|
||||||
private Roster roster;
|
private Roster roster;
|
||||||
|
|
||||||
|
@ -58,6 +66,8 @@ public class ContactDetailViewModel extends ViewModel {
|
||||||
|
|
||||||
public void bind(UUID accountId, String peerAddress) {
|
public void bind(UUID accountId, String peerAddress) {
|
||||||
Log.d("MMMMMM", "Bind!");
|
Log.d("MMMMMM", "Bind!");
|
||||||
|
roster = Roster.getInstanceFor(messenger.getConnectionManager().getConnection(accountId).getConnection());
|
||||||
|
roster.addPresenceEventListener(presenceEventListener);
|
||||||
contactAddress.setValue(peerAddress);
|
contactAddress.setValue(peerAddress);
|
||||||
contactAccountId.setValue(accountId);
|
contactAccountId.setValue(accountId);
|
||||||
disposable.add(peerRepository.observePeerByAddress(accountId, peerAddress)
|
disposable.add(peerRepository.observePeerByAddress(accountId, peerAddress)
|
||||||
|
@ -71,12 +81,21 @@ public class ContactDetailViewModel extends ViewModel {
|
||||||
contactAccountAddress.setValue(peer.getAccount().getAddress());
|
contactAccountAddress.setValue(peer.getAccount().getAddress());
|
||||||
contactAvatar.setValue(new AvatarDrawable(peer.getDisplayName(), peer.getAddress()));
|
contactAvatar.setValue(new AvatarDrawable(peer.getDisplayName(), peer.getAddress()));
|
||||||
contactName.setValue(peer.getDisplayName());
|
contactName.setValue(peer.getDisplayName());
|
||||||
|
|
||||||
|
RosterEntry entry = roster.getEntry(JidCreate.entityBareFromOrThrowUnchecked(peerAddress));
|
||||||
|
if (entry != null) {
|
||||||
|
List<RosterGroup> groups = entry.getGroups();
|
||||||
|
List<String> groupNames = new ArrayList<>(groups.size());
|
||||||
|
for (RosterGroup g : groups) {
|
||||||
|
groupNames.add(g.getName());
|
||||||
|
}
|
||||||
|
contactGroups.postValue(groupNames);
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
roster = Roster.getInstanceFor(messenger.getConnectionManager().getConnection(accountId).getConnection());
|
BareJid jid = JidCreate.entityBareFromOrThrowUnchecked(peerAddress);
|
||||||
roster.addPresenceEventListener(presenceEventListener);
|
|
||||||
|
|
||||||
Presence presence = roster.getPresence(JidCreate.entityBareFromOrThrowUnchecked(peerAddress));
|
Presence presence = roster.getPresence(jid);
|
||||||
if (presence != null) {
|
if (presence != null) {
|
||||||
contactPresenceMode.postValue(presence.getMode());
|
contactPresenceMode.postValue(presence.getMode());
|
||||||
contactPresenceStatus.postValue(presence.getStatus());
|
contactPresenceStatus.postValue(presence.getStatus());
|
||||||
|
@ -120,6 +139,10 @@ public class ContactDetailViewModel extends ViewModel {
|
||||||
return contactAccountAddress;
|
return contactAccountAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<List<String>> getContactGroups() {
|
||||||
|
return contactGroups;
|
||||||
|
}
|
||||||
|
|
||||||
private final PresenceEventListener presenceEventListener = new CombinedPresenceListener() {
|
private final PresenceEventListener presenceEventListener = new CombinedPresenceListener() {
|
||||||
@Override
|
@Override
|
||||||
public void presenceReceived(Jid address, Presence presence) {
|
public void presenceReceived(Jid address, Presence presence) {
|
||||||
|
@ -138,4 +161,28 @@ public class ContactDetailViewModel extends ViewModel {
|
||||||
entry.setName(newName);
|
entry.setName(newName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Completable addContactToRosterGroup() {
|
||||||
|
return Completable.fromAction(() -> doAddContactToRosterGroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doAddContactToRosterGroup() throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
|
||||||
|
String groupName = "Mercury Seven";
|
||||||
|
RosterGroup group = roster.getGroup(groupName);
|
||||||
|
if (group == null) {
|
||||||
|
group = roster.createGroup(groupName);
|
||||||
|
}
|
||||||
|
BareJid jid = JidCreate.entityBareFromOrThrowUnchecked(getContactAddress().getValue());
|
||||||
|
if (group.contains(jid)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RosterEntry entry = roster.getEntry(jid);
|
||||||
|
group.addEntry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Completable removeContactFromRosterGroup(String group) {
|
||||||
|
return Completable.fromAction(() -> roster.getGroup(group).removeEntry(roster.getEntry(JidCreate.entityBareFromOrThrowUnchecked(getContactAddress().getValue()))));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,12 @@
|
||||||
android:text="Dungeons n' Dragons"/>
|
android:text="Dungeons n' Dragons"/>
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_add_to_group"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Mark Mercury Seven"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.mercury_im.messenger.data.model;
|
||||||
import org.mercury_im.messenger.data.converter.SubscriptionDirectionConverter;
|
import org.mercury_im.messenger.data.converter.SubscriptionDirectionConverter;
|
||||||
import org.mercury_im.messenger.entity.contact.SubscriptionDirection;
|
import org.mercury_im.messenger.entity.contact.SubscriptionDirection;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import io.requery.CascadeAction;
|
import io.requery.CascadeAction;
|
||||||
|
@ -42,6 +43,9 @@ public abstract class AbstractPeerModel implements Persistable {
|
||||||
@Convert(SubscriptionDirectionConverter.class)
|
@Convert(SubscriptionDirectionConverter.class)
|
||||||
SubscriptionDirection subscriptionDirection;
|
SubscriptionDirection subscriptionDirection;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
List<String> groupNames;
|
||||||
|
|
||||||
boolean subscriptionPending;
|
boolean subscriptionPending;
|
||||||
|
|
||||||
boolean subscriptionPreApproved;
|
boolean subscriptionPreApproved;
|
||||||
|
|
|
@ -198,6 +198,9 @@ public class MercuryRosterStore implements RosterStore {
|
||||||
}
|
}
|
||||||
item.setApproved(contactModel.isSubscriptionApproved());
|
item.setApproved(contactModel.isSubscriptionApproved());
|
||||||
item.setSubscriptionPending(contactModel.isSubscriptionPending());
|
item.setSubscriptionPending(contactModel.isSubscriptionPending());
|
||||||
|
for (String groupName : contactModel.getGroupNames()) {
|
||||||
|
item.addGroupName(groupName);
|
||||||
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +213,7 @@ public class MercuryRosterStore implements RosterStore {
|
||||||
}
|
}
|
||||||
peer.setSubscriptionApproved(item.isApproved());
|
peer.setSubscriptionApproved(item.isApproved());
|
||||||
peer.setSubscriptionPending(item.isSubscriptionPending());
|
peer.setSubscriptionPending(item.isSubscriptionPending());
|
||||||
|
peer.setGroupNames(new ArrayList<>(item.getGroupNames()));
|
||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class CsiManager implements ClientStateListener {
|
||||||
private void tryCsiActive(MercuryConnection connection) {
|
private void tryCsiActive(MercuryConnection connection) {
|
||||||
try {
|
try {
|
||||||
ClientStateIndicationManager.active(connection.getConnection());
|
ClientStateIndicationManager.active(connection.getConnection());
|
||||||
} catch (SmackException.NotConnectedException | InterruptedException e) {
|
} catch (SmackException.NotConnectedException | InterruptedException | IllegalArgumentException e) {
|
||||||
LOGGER.log(Level.WARNING, "Sending CSI state 'active' failed.", e);
|
LOGGER.log(Level.WARNING, "Sending CSI state 'active' failed.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ public class CsiManager implements ClientStateListener {
|
||||||
private void tryCsiInactive(MercuryConnection connection) {
|
private void tryCsiInactive(MercuryConnection connection) {
|
||||||
try {
|
try {
|
||||||
ClientStateIndicationManager.inactive(connection.getConnection());
|
ClientStateIndicationManager.inactive(connection.getConnection());
|
||||||
} catch (SmackException.NotConnectedException | InterruptedException e) {
|
} catch (SmackException.NotConnectedException | InterruptedException | IllegalArgumentException e) {
|
||||||
LOGGER.log(Level.WARNING, "Sending CSI state 'inactive' failed.", e);
|
LOGGER.log(Level.WARNING, "Sending CSI state 'inactive' failed.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.mercury_im.messenger.entity.contact;
|
||||||
|
|
||||||
import org.mercury_im.messenger.entity.Account;
|
import org.mercury_im.messenger.entity.Account;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
@ -19,6 +20,7 @@ public class Peer {
|
||||||
SubscriptionDirection subscriptionDirection;
|
SubscriptionDirection subscriptionDirection;
|
||||||
boolean subscriptionPending;
|
boolean subscriptionPending;
|
||||||
boolean subscriptionApproved;
|
boolean subscriptionApproved;
|
||||||
|
List<String> groupNames;
|
||||||
|
|
||||||
public Peer() {
|
public Peer() {
|
||||||
this.id = UUID.randomUUID();
|
this.id = UUID.randomUUID();
|
||||||
|
|
Loading…
Reference in a new issue