From 71f8e656db044a3b3e28cb82a954521699fe9602 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 27 Jan 2019 14:56:20 +0100 Subject: refactored group chat members into seperate screen --- src/main/AndroidManifest.xml | 5 +- .../de/pixart/messenger/entities/MucOptions.java | 31 ++- .../pixart/messenger/services/AvatarService.java | 5 +- .../messenger/ui/ConferenceDetailsActivity.java | 232 ++++----------------- .../pixart/messenger/ui/EditAccountActivity.java | 2 +- .../de/pixart/messenger/ui/MucUsersActivity.java | 71 +++++++ .../pixart/messenger/ui/adapter/UserAdapter.java | 146 +++++++++++++ .../messenger/ui/adapter/UserPreviewAdapter.java | 72 +++++++ .../de/pixart/messenger/ui/util/GridManager.java | 3 +- src/main/res/layout/account_row.xml | 2 +- src/main/res/layout/activity_muc_details.xml | 38 +++- src/main/res/layout/activity_muc_users.xml | 33 +++ src/main/res/layout/contact.xml | 2 +- src/main/res/layout/user_preview.xml | 17 ++ src/main/res/values/dimens.xml | 1 + src/main/res/values/strings.xml | 2 + 16 files changed, 452 insertions(+), 210 deletions(-) create mode 100644 src/main/java/de/pixart/messenger/ui/MucUsersActivity.java create mode 100644 src/main/java/de/pixart/messenger/ui/adapter/UserAdapter.java create mode 100644 src/main/java/de/pixart/messenger/ui/adapter/UserPreviewAdapter.java create mode 100644 src/main/res/layout/activity_muc_users.xml create mode 100644 src/main/res/layout/user_preview.xml diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 2edfdbf67..d5dcd8dd6 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -305,9 +305,12 @@ android:name=".ui.EnterNameActivity" android:label="@string/enter_your_name" android:launchMode="singleTask" /> + - + diff --git a/src/main/java/de/pixart/messenger/entities/MucOptions.java b/src/main/java/de/pixart/messenger/entities/MucOptions.java index 01daad1bf..c1b776b9a 100644 --- a/src/main/java/de/pixart/messenger/entities/MucOptions.java +++ b/src/main/java/de/pixart/messenger/entities/MucOptions.java @@ -14,6 +14,7 @@ import java.util.Set; import de.pixart.messenger.Config; import de.pixart.messenger.R; +import de.pixart.messenger.services.AvatarService; import de.pixart.messenger.services.MessageArchiveService; import de.pixart.messenger.utils.JidHelper; import de.pixart.messenger.utils.UIHelper; @@ -45,6 +46,7 @@ public class MucOptions { private User self; private String password = null; private boolean tookProposedNickFromBookmark = false; + public MucOptions(Conversation conversation) { this.account = conversation.getAccount(); this.conversation = conversation; @@ -102,7 +104,7 @@ public class MucOptions { } void notifyOfBookmarkNick(final String nick) { - final String normalized = normalize(account.getJid(),nick); + final String normalized = normalize(account.getJid(), nick); if (normalized != null && normalized.equals(getSelf().getFullJid().getResource())) { this.tookProposedNickFromBookmark = true; } @@ -381,6 +383,21 @@ public class MucOptions { return subset; } + public static List sub(List users, int max) { + ArrayList subset = new ArrayList<>(); + HashSet jids = new HashSet<>(); + for (User user : users) { + jids.add(user.getAccount().getJid().asBareJid()); + if (user.getRealJid() == null || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) { + subset.add(user); + } + if (subset.size() >= max) { + break; + } + } + return subset; + } + public int getUserCount() { synchronized (users) { return users.size(); @@ -602,6 +619,7 @@ public class MucOptions { private int resId; private int rank; + Affiliation(int rank, int resId) { this.resId = resId; this.rank = rank; @@ -644,6 +662,7 @@ public class MucOptions { private int resId; private int rank; + Role(int resId, int rank) { this.resId = resId; this.rank = rank; @@ -702,7 +721,7 @@ public class MucOptions { } - public static class User implements Comparable { + public static class User implements Comparable, AvatarService.Avatarable { private Role role = Role.NONE; private Affiliation affiliation = Affiliation.NONE; private Jid realJid; @@ -838,7 +857,7 @@ public class MucOptions { } } - private String getComparableName() { + public String getComparableName() { Contact contact = getContact(); if (contact != null) { return contact.getDisplayName(); @@ -863,5 +882,11 @@ public class MucOptions { this.chatState = chatState; return true; } + + @Override + public int getAvatarBackgroundColor() { + final String seed = realJid != null ? realJid.asBareJid().toString() : null; + return UIHelper.getColorForName(seed == null ? getName() : seed); + } } } diff --git a/src/main/java/de/pixart/messenger/services/AvatarService.java b/src/main/java/de/pixart/messenger/services/AvatarService.java index 4ed01c42a..da5c449f9 100644 --- a/src/main/java/de/pixart/messenger/services/AvatarService.java +++ b/src/main/java/de/pixart/messenger/services/AvatarService.java @@ -39,6 +39,7 @@ import de.pixart.messenger.entities.Conversational; import de.pixart.messenger.entities.ListItem; import de.pixart.messenger.entities.Message; import de.pixart.messenger.entities.MucOptions; +import de.pixart.messenger.ui.ConferenceDetailsActivity; import de.pixart.messenger.utils.UIHelper; import de.pixart.messenger.xmpp.OnAdvancedStreamFeaturesLoaded; import de.pixart.messenger.xmpp.XmppConnection; @@ -75,13 +76,15 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded { public Bitmap get(final Avatarable avatarable, final int size, final boolean cachedOnly) { if (avatarable instanceof Account) { - return get((Account) avatarable,size,cachedOnly); + return get((Account) avatarable, size, cachedOnly); } else if (avatarable instanceof Conversation) { return get((Conversation) avatarable, size, cachedOnly); } else if (avatarable instanceof Message) { return get((Message) avatarable, size, cachedOnly); } else if (avatarable instanceof ListItem) { return get((ListItem) avatarable, size, cachedOnly); + } else if (avatarable instanceof MucOptions.User) { + return get((MucOptions.User) avatarable, size, cachedOnly); } throw new AssertionError("AvatarService does not know how to generate avatar from "+avatarable.getClass().getName()); } diff --git a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java index 3508fef7c..92192de69 100644 --- a/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/ConferenceDetailsActivity.java @@ -54,6 +54,7 @@ import de.pixart.messenger.services.XmppConnectionService; import de.pixart.messenger.services.XmppConnectionService.OnConversationUpdate; import de.pixart.messenger.services.XmppConnectionService.OnMucRosterUpdate; import de.pixart.messenger.ui.adapter.MediaAdapter; +import de.pixart.messenger.ui.adapter.UserPreviewAdapter; import de.pixart.messenger.ui.interfaces.OnMediaLoaded; import de.pixart.messenger.ui.util.Attachment; import de.pixart.messenger.ui.util.AvatarWorkerTask; @@ -78,15 +79,7 @@ import static de.pixart.messenger.utils.StringUtils.changed; public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, XmppConnectionService.OnRoleChanged, XmppConnectionService.OnConfigurationPushed, TextWatcher, OnMediaLoaded { public static final String ACTION_VIEW_MUC = "view_muc"; - private static final float INACTIVE_ALPHA = 0.4684f; //compromise between dark and light theme private Conversation mConversation; - private OnClickListener inviteListener = new OnClickListener() { - - @Override - public void onClick(View v) { - inviteToConversation(mConversation); - } - }; private OnClickListener destroyListener = new OnClickListener() { @Override public void onClick(View v) { @@ -109,8 +102,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers }; private ActivityMucDetailsBinding binding; private MediaAdapter mMediaAdapter; + private UserPreviewAdapter mUserPreviewAdapter; private String uuid = null; - private User mSelectedUser = null; private boolean mAdvancedMode = false; @@ -247,31 +240,6 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } }; - public static boolean cancelPotentialWork(User user, ImageView imageView) { - final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); - - if (bitmapWorkerTask != null) { - final User old = bitmapWorkerTask.o; - if (old == null || user != old) { - bitmapWorkerTask.cancel(true); - } else { - return false; - } - } - return true; - } - - private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { - if (imageView != null) { - final Drawable drawable = imageView.getDrawable(); - if (drawable instanceof AsyncDrawable) { - final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; - return asyncDrawable.getBitmapWorkerTask(); - } - } - return null; - } - @Override public void onConversationUpdate() { refreshUi(); @@ -292,14 +260,10 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers super.onCreate(savedInstanceState); this.binding = DataBindingUtil.setContentView(this, R.layout.activity_muc_details); this.binding.changeConferenceButton.setOnClickListener(this.mChangeConferenceSettings); - this.binding.invite.setOnClickListener(inviteListener); - this.binding.invite.setVisibility(View.GONE); - this.binding.invite.setOnClickListener(inviteListener); this.binding.destroy.setVisibility(View.GONE); this.binding.destroy.setOnClickListener(destroyListener); this.binding.leaveMuc.setVisibility(View.GONE); this.binding.addContactButton.setVisibility(View.GONE); - this.binding.mucMoreDetails.setVisibility(View.GONE); setSupportActionBar((Toolbar) binding.toolbar); configureActionBar(getSupportActionBar()); this.binding.editNickButton.setOnClickListener(v -> quickEdit(mConversation.getMucOptions().getActualNick(), @@ -342,9 +306,18 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } } }); - mMediaAdapter = new MediaAdapter(this, R.dimen.media_size); + this.mMediaAdapter = new MediaAdapter(this, R.dimen.media_size); + this.mUserPreviewAdapter = new UserPreviewAdapter(); this.binding.media.setAdapter(mMediaAdapter); + this.binding.users.setAdapter(mUserPreviewAdapter); GridManager.setupLayoutManager(this, this.binding.media, R.dimen.media_size); + GridManager.setupLayoutManager(this, this.binding.users, R.dimen.media_size); + this.binding.invite.setOnClickListener(v -> inviteToConversation(mConversation)); + this.binding.showUsers.setOnClickListener(v -> { + Intent intent = new Intent(this, MucUsersActivity.class); + intent.putExtra("uuid", mConversation.getUuid()); + startActivity(intent); + }); } @Override @@ -469,36 +442,6 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers return super.onCreateOptionsMenu(menu); } - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - Object tag = v.getTag(); - if (tag instanceof User) { - getMenuInflater().inflate(R.menu.muc_details_context, menu); - final User user = (User) tag; - this.mSelectedUser = user; - String name; - final Contact contact = user.getContact(); - if (contact != null && contact.showInContactList()) { - name = contact.getDisplayName(); - } else if (user.getRealJid() != null) { - name = user.getRealJid().asBareJid().toString(); - } else { - name = user.getName(); - } - menu.setHeaderTitle(name); - MucDetailsContextMenuHelper.configureMucDetailsContextMenu(this, menu, mConversation, user); - } - super.onCreateContextMenu(menu, v, menuInfo); - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - if (!MucDetailsContextMenuHelper.onContextItemSelected(item, mSelectedUser, mConversation, this)) { - return super.onContextItemSelected(item); - } - return true; - } - @Override public void onMediaLoaded(List attachments) { runOnUiThread(() -> { @@ -578,8 +521,8 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } else { this.binding.detailsAccount.setVisibility(View.GONE); } - AvatarWorkerTask.loadAvatar(mConversation, binding.detailsMucAvatar, getPixel(Config.AVATAR_SIZE)); - AvatarWorkerTask.loadAvatar(mConversation, binding.yourPhoto, R.dimen.avatar_on_details_screen_size); + AvatarWorkerTask.loadAvatar(mConversation, binding.detailsMucAvatar, R.dimen.avatar_big); + AvatarWorkerTask.loadAvatar(mConversation.getAccount(), binding.yourPhoto, R.dimen.avatar_on_details_screen_size); String roomName = mucOptions.getName(); String subject = mucOptions.getSubject(); @@ -609,7 +552,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } this.binding.mucYourNick.setText(EmojiWrapper.transform(mucOptions.getActualNick())); if (mucOptions.online()) { - this.binding.mucMoreDetails.setVisibility(View.VISIBLE); + this.binding.usersWrapper.setVisibility(View.VISIBLE); this.binding.mucSettings.setVisibility(View.VISIBLE); this.binding.mucInfoMore.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE); this.binding.jid.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE); @@ -686,7 +629,7 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers }); } } else { - this.binding.mucMoreDetails.setVisibility(View.GONE); + this.binding.usersWrapper.setVisibility(View.GONE); this.binding.mucInfoMore.setVisibility(View.GONE); this.binding.mucSettings.setVisibility(View.GONE); } @@ -710,71 +653,36 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers this.binding.notificationStatusButton.setImageResource(ic_notifications_none); } - final LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); - this.binding.mucMembers.removeAllViews(); - if (inflater == null) { - return; - } - final ArrayList users = mucOptions.getUsers(); - Collections.sort(users); - for (final User user : users) { - ContactBinding binding = DataBindingUtil.inflate(inflater, R.layout.contact, this.binding.mucMembers, false); - this.setListItemBackgroundOnView(binding.getRoot()); - binding.getRoot().setOnClickListener(view1 -> highlightInMuc(mConversation, user.getName())); - registerForContextMenu(binding.getRoot()); - binding.getRoot().setTag(user); - if (mAdvancedMode && user.getPgpKeyId() != 0) { - binding.key.setVisibility(View.VISIBLE); - binding.key.setOnClickListener(v -> viewPgpKey(user)); - binding.key.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); - } - Contact contact = user.getContact(); - String name = user.getName(); - if (contact != null) { - binding.contactDisplayName.setText(EmojiWrapper.transform(contact.getDisplayName())); - binding.contactJid.setText((name != null ? EmojiWrapper.transform(name) + " \u2022 " : "") + getStatus(user)); + List users = mucOptions.getUsers(); + Collections.sort(users, (a, b) -> { + if (b.getAffiliation().outranks(a.getAffiliation())) { + return 1; + } else if (a.getAffiliation().outranks(b.getAffiliation())) { + return -1; } else { - binding.contactDisplayName.setText(name == null ? "" : EmojiWrapper.transform(name)); - binding.contactJid.setText(getStatus(user)); - - } - loadAvatar(user, binding.contactPhoto); - if (user.getRole() == MucOptions.Role.NONE) { - binding.contactJid.setAlpha(INACTIVE_ALPHA); - binding.key.setAlpha(INACTIVE_ALPHA); - binding.contactDisplayName.setAlpha(INACTIVE_ALPHA); - binding.contactPhoto.setAlpha(INACTIVE_ALPHA); + if (a.getAvatar() != null && b.getAvatar() == null) { + return -1; + } else if (a.getAvatar() == null && b.getAvatar() != null) { + return 1; + } else { + return a.getComparableName().compareToIgnoreCase(b.getComparableName()); + } } - this.binding.mucMembers.addView(binding.getRoot()); - } - if (mConversation.getMucOptions().canInvite()) { - this.binding.invite.setVisibility(View.VISIBLE); - } else { - this.binding.invite.setVisibility(View.GONE); - } + }); + this.mUserPreviewAdapter.setUserList(MucOptions.sub(users, GridManager.getCurrentColumnCount(binding.users))); + this.binding.invite.setVisibility(mucOptions.canInvite() ? View.VISIBLE : View.GONE); } - private String getStatus(User user) { - if (mAdvancedMode) { - return getString(user.getAffiliation().getResId()) + - " (" + getString(user.getRole().getResId()) + ')'; + public static String getStatus(Context context, User user, final boolean advanced) { + if (advanced) { + return String.format("%s (%s)", context.getString(user.getAffiliation().getResId()), context.getString(user.getRole().getResId())); } else { - return getString(user.getAffiliation().getResId()); + return context.getString(user.getAffiliation().getResId()); } } - private void viewPgpKey(User user) { - PgpEngine pgp = xmppConnectionService.getPgpEngine(); - if (pgp != null) { - PendingIntent intent = pgp.getIntentForKey(user.getPgpKeyId()); - if (intent != null) { - try { - startIntentSenderForResult(intent.getIntentSender(), 0, null, 0, 0, 0); - } catch (SendIntentException ignored) { - - } - } - } + private String getStatus(User user) { + return getStatus(this, user, mAdvancedMode); } @Override @@ -816,28 +724,6 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers }); } - public void loadAvatar(User user, ImageView imageView) { - if (cancelPotentialWork(user, imageView)) { - final Bitmap bm = avatarService().get(user, getPixel(48), true); - if (bm != null) { - cancelPotentialWork(user, imageView); - imageView.setImageBitmap(bm); - imageView.setBackgroundColor(0x00000000); - } else { - String seed = user.getRealJid() != null ? user.getRealJid().asBareJid().toString() : null; - imageView.setBackgroundColor(UIHelper.getColorForName(seed == null ? user.getName() : seed)); - imageView.setImageDrawable(null); - final BitmapWorkerTask task = new BitmapWorkerTask(imageView); - final AsyncDrawable asyncDrawable = new AsyncDrawable(getResources(), null, task); - imageView.setImageDrawable(asyncDrawable); - try { - task.execute(user); - } catch (final RejectedExecutionException ignored) { - } - } - } - } - @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -864,46 +750,4 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers } } } - - static class AsyncDrawable extends BitmapDrawable { - private final WeakReference bitmapWorkerTaskReference; - - AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { - super(res, bitmap); - bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); - } - - BitmapWorkerTask getBitmapWorkerTask() { - return bitmapWorkerTaskReference.get(); - } - } - - class BitmapWorkerTask extends AsyncTask { - private final WeakReference imageViewReference; - private User o = null; - - private BitmapWorkerTask(ImageView imageView) { - imageViewReference = new WeakReference<>(imageView); - } - - @Override - protected Bitmap doInBackground(User... params) { - this.o = params[0]; - if (imageViewReference.get() == null) { - return null; - } - return avatarService().get(this.o, getPixel(48), isCancelled()); - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null && !isCancelled()) { - final ImageView imageView = imageViewReference.get(); - if (imageView != null) { - imageView.setImageBitmap(bitmap); - imageView.setBackgroundColor(0x00000000); - } - } - } - } } diff --git a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java index 34330236f..47a7b2173 100644 --- a/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java +++ b/src/main/java/de/pixart/messenger/ui/EditAccountActivity.java @@ -1058,7 +1058,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat if (!mInitMode) { binding.avater.setVisibility(View.VISIBLE); - AvatarWorkerTask.loadAvatar(mAccount, binding.avater, getPixel(Config.AVATAR_SIZE)); + AvatarWorkerTask.loadAvatar(mAccount, binding.avater, R.dimen.avatar_big); this.binding.accountJid.setEnabled(false); } else { binding.avater.setVisibility(View.GONE); diff --git a/src/main/java/de/pixart/messenger/ui/MucUsersActivity.java b/src/main/java/de/pixart/messenger/ui/MucUsersActivity.java new file mode 100644 index 000000000..ffefedc80 --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/MucUsersActivity.java @@ -0,0 +1,71 @@ +package de.pixart.messenger.ui; + +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.os.Bundle; +import android.support.v7.widget.Toolbar; +import android.view.MenuItem; + +import java.util.ArrayList; +import java.util.Collections; + +import de.pixart.messenger.R; +import de.pixart.messenger.databinding.ActivityMucUsersBinding; +import de.pixart.messenger.entities.Conversation; +import de.pixart.messenger.entities.MucOptions; +import de.pixart.messenger.services.XmppConnectionService; +import de.pixart.messenger.ui.adapter.UserAdapter; +import de.pixart.messenger.ui.util.MucDetailsContextMenuHelper; + +public class MucUsersActivity extends XmppActivity implements XmppConnectionService.OnRosterUpdate { + + private UserAdapter userAdapter; + + private Conversation mConversation = null; + + @Override + protected void refreshUiReal() { + } + + @Override + void onBackendConnected() { + final Intent intent = getIntent(); + final String uuid = intent == null ? null : intent.getStringExtra("uuid"); + if (uuid != null) { + mConversation = xmppConnectionService.findConversationByUuid(uuid); + } + loadAndSubmitUsers(); + } + + private void loadAndSubmitUsers() { + if (mConversation != null) { + ArrayList users = mConversation.getMucOptions().getUsers(); + Collections.sort(users); + userAdapter.submitList(users); + } + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + if (!MucDetailsContextMenuHelper.onContextItemSelected(item, userAdapter.getSelectedUser(), mConversation, this)) { + return super.onContextItemSelected(item); + } + return true; + } + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ActivityMucUsersBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_muc_users); + setSupportActionBar((Toolbar) binding.toolbar); + configureActionBar(getSupportActionBar(), true); + this.userAdapter = new UserAdapter(true); + binding.list.setAdapter(this.userAdapter); + } + + + @Override + public void onRosterUpdate() { + loadAndSubmitUsers(); + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/adapter/UserAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/UserAdapter.java new file mode 100644 index 000000000..f6a15aff4 --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/adapter/UserAdapter.java @@ -0,0 +1,146 @@ +package de.pixart.messenger.ui.adapter; + +import android.app.PendingIntent; +import android.content.IntentSender; +import android.databinding.DataBindingUtil; +import android.support.annotation.NonNull; +import android.support.v7.recyclerview.extensions.ListAdapter; +import android.support.v7.util.DiffUtil; +import android.support.v7.widget.RecyclerView; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.View; +import android.view.ViewGroup; +import android.widget.PopupMenu; + +import org.openintents.openpgp.util.OpenPgpUtils; + +import java.util.List; + +import de.pixart.messenger.R; +import de.pixart.messenger.crypto.PgpEngine; +import de.pixart.messenger.databinding.ContactBinding; +import de.pixart.messenger.entities.Contact; +import de.pixart.messenger.entities.MucOptions; +import de.pixart.messenger.services.XmppConnectionService; +import de.pixart.messenger.ui.ConferenceDetailsActivity; +import de.pixart.messenger.ui.XmppActivity; +import de.pixart.messenger.ui.util.AvatarWorkerTask; +import de.pixart.messenger.ui.util.MucDetailsContextMenuHelper; + +public class UserAdapter extends ListAdapter implements View.OnCreateContextMenuListener { + + private MucOptions.User selectedUser = null; + + static final DiffUtil.ItemCallback DIFF = new DiffUtil.ItemCallback() { + @Override + public boolean areItemsTheSame(@NonNull MucOptions.User a, @NonNull MucOptions.User b) { + return a == b; + } + + @Override + public boolean areContentsTheSame(@NonNull MucOptions.User a, @NonNull MucOptions.User b) { + return a.equals(b); + } + }; + private final boolean advancedMode; + + public UserAdapter(final boolean advancedMode) { + super(DIFF); + this.advancedMode = advancedMode; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { + return new ViewHolder(DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()), R.layout.contact, viewGroup, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) { + final MucOptions.User user = getItem(position); + AvatarWorkerTask.loadAvatar(user, viewHolder.binding.contactPhoto, R.dimen.avatar); + viewHolder.binding.getRoot().setOnClickListener(v -> { + final XmppActivity activity = XmppActivity.find(v); + if (activity != null) { + activity.highlightInMuc(user.getConversation(), user.getName()); + } + }); + viewHolder.binding.getRoot().setTag(user); + viewHolder.binding.getRoot().setOnCreateContextMenuListener(this); + viewHolder.binding.getRoot().setOnLongClickListener(v -> { + selectedUser = user; + return false; + }); + final String name = user.getName(); + final Contact contact = user.getContact(); + if (contact != null) { + viewHolder.binding.contactDisplayName.setText(contact.getDisplayName()); + if (name != null) { + viewHolder.binding.contactJid.setText(String.format("%s \u2022 %s", name, ConferenceDetailsActivity.getStatus(viewHolder.binding.getRoot().getContext(), user, advancedMode))); + } else { + viewHolder.binding.contactJid.setText(ConferenceDetailsActivity.getStatus(viewHolder.binding.getRoot().getContext(), user, advancedMode)); + } + } else { + viewHolder.binding.contactDisplayName.setText(name == null ? "" : name); + viewHolder.binding.contactJid.setText(ConferenceDetailsActivity.getStatus(viewHolder.binding.getRoot().getContext(), user, advancedMode)); + } + if (advancedMode && user.getPgpKeyId() != 0) { + viewHolder.binding.key.setVisibility(View.VISIBLE); + viewHolder.binding.key.setOnClickListener(v -> { + final XmppActivity activity = XmppActivity.find(v); + final XmppConnectionService service = activity == null ? null : activity.xmppConnectionService; + final PgpEngine pgpEngine = service == null ? null : service.getPgpEngine(); + if (pgpEngine != null) { + PendingIntent intent = pgpEngine.getIntentForKey(user.getPgpKeyId()); + if (intent != null) { + try { + activity.startIntentSenderForResult(intent.getIntentSender(), 0, null, 0, 0, 0); + } catch (IntentSender.SendIntentException ignored) { + + } + } + } + }); + viewHolder.binding.key.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId())); + } + + + } + + public MucOptions.User getSelectedUser() { + return selectedUser; + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + final XmppActivity activity = XmppActivity.find(v); + final Object tag = v.getTag(); + if (tag instanceof MucOptions.User && activity != null) { + activity.getMenuInflater().inflate(R.menu.muc_details_context, menu); + final MucOptions.User user = (MucOptions.User) tag; + String name; + final Contact contact = user.getContact(); + if (contact != null && contact.showInContactList()) { + name = contact.getDisplayName(); + } else if (user.getRealJid() != null) { + name = user.getRealJid().asBareJid().toString(); + } else { + name = user.getName(); + } + menu.setHeaderTitle(name); + MucDetailsContextMenuHelper.configureMucDetailsContextMenu(activity, menu, user.getConversation(), user); + } + } + + class ViewHolder extends RecyclerView.ViewHolder { + + private final ContactBinding binding; + + private ViewHolder(ContactBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/adapter/UserPreviewAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/UserPreviewAdapter.java new file mode 100644 index 000000000..5104ef86c --- /dev/null +++ b/src/main/java/de/pixart/messenger/ui/adapter/UserPreviewAdapter.java @@ -0,0 +1,72 @@ +package de.pixart.messenger.ui.adapter; + +import android.databinding.DataBindingUtil; +import android.support.annotation.NonNull; +import android.support.v7.recyclerview.extensions.ListAdapter; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.ViewGroup; +import android.widget.PopupMenu; + +import java.util.List; + +import de.pixart.messenger.R; +import de.pixart.messenger.databinding.UserPreviewBinding; +import de.pixart.messenger.entities.MucOptions; +import de.pixart.messenger.ui.XmppActivity; +import de.pixart.messenger.ui.util.AvatarWorkerTask; +import de.pixart.messenger.ui.util.MucDetailsContextMenuHelper; + +public class UserPreviewAdapter extends ListAdapter { + + public UserPreviewAdapter() { + super(UserAdapter.DIFF); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { + return new ViewHolder(DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()), R.layout.user_preview, viewGroup, false)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) { + final MucOptions.User user = getItem(position); + AvatarWorkerTask.loadAvatar(user, viewHolder.binding.avatar, R.dimen.media_size); + viewHolder.binding.getRoot().setOnClickListener(v -> { + final XmppActivity activity = XmppActivity.find(v); + if (activity != null) { + activity.highlightInMuc(user.getConversation(), user.getName()); + } + }); + viewHolder.binding.getRoot().setOnLongClickListener(v -> { + final XmppActivity activity = XmppActivity.find(v); + if (activity == null) { + return true; + } + final PopupMenu popupMenu = new PopupMenu(activity, v); + popupMenu.inflate(R.menu.muc_details_context); + final Menu menu = popupMenu.getMenu(); + MucDetailsContextMenuHelper.configureMucDetailsContextMenu(activity, menu, user.getConversation(), user); + popupMenu.setOnMenuItemClickListener(menuItem -> MucDetailsContextMenuHelper.onContextItemSelected(menuItem, user, user.getConversation(), activity)); + popupMenu.show(); + return true; + }); + } + + public void setUserList(List users) { + submitList(users); + } + + + class ViewHolder extends RecyclerView.ViewHolder { + + private final UserPreviewBinding binding; + + private ViewHolder(UserPreviewBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/ui/util/GridManager.java b/src/main/java/de/pixart/messenger/ui/util/GridManager.java index 0b445f3ec..9cad626ff 100644 --- a/src/main/java/de/pixart/messenger/ui/util/GridManager.java +++ b/src/main/java/de/pixart/messenger/ui/util/GridManager.java @@ -29,7 +29,8 @@ public class GridManager { } final ColumnInfo columnInfo = calculateColumnCount(context, recyclerView.getMeasuredWidth(), desiredSize); Log.d(Config.LOGTAG, "final count " + columnInfo.count); - if (recyclerView.getAdapter().getItemCount() != 0) { + final RecyclerView.Adapter adapter = recyclerView.getAdapter(); + if (adapter != null && adapter.getItemCount() != 0) { Log.e(Config.LOGTAG, "adapter already has items; just go with it now"); return; } diff --git a/src/main/res/layout/account_row.xml b/src/main/res/layout/account_row.xml index f99f6c0dd..e3f3d99e1 100644 --- a/src/main/res/layout/account_row.xml +++ b/src/main/res/layout/account_row.xml @@ -5,7 +5,7 @@ - - + android:orientation="horizontal" + android:paddingStart="@dimen/card_padding_regular" + android:paddingTop="@dimen/card_padding_regular" + android:paddingEnd="@dimen/card_padding_regular" + android:paddingBottom="@dimen/card_padding_list" /> + + +