mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-22 10:21:29 +00:00
Make contact photos optional when sharing contacts.
Previously, if you had a contact photo for a user, we'd always send it Now you can choose whether or not it is sent.
This commit is contained in:
parent
7237e919be
commit
6ce8516b93
@ -12,16 +12,12 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.AvatarImageView
|
|
||||||
android:id="@+id/editable_contact_avatar"
|
|
||||||
android:layout_width="50dp"
|
|
||||||
android:layout_height="50dp"
|
|
||||||
android:layout_margin="12dp"/>
|
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||||
android:id="@+id/editable_contact_name"
|
android:id="@+id/editable_contact_name"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
|
@ -9,6 +9,15 @@
|
|||||||
android:paddingBottom="5dp"
|
android:paddingBottom="5dp"
|
||||||
android:gravity="center_vertical">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/contact_field_avatar"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:src="@drawable/ic_contact_picture" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/contact_field_icon"
|
android:id="@+id/contact_field_icon"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
|
@ -582,7 +582,7 @@ public class Contact implements Parcelable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Avatar implements Parcelable {
|
public static class Avatar implements Selectable, Parcelable {
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private final AttachmentId attachmentId;
|
private final AttachmentId attachmentId;
|
||||||
@ -593,10 +593,14 @@ public class Contact implements Parcelable {
|
|||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private final Attachment attachment;
|
private final Attachment attachment;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private boolean selected;
|
||||||
|
|
||||||
public Avatar(@Nullable AttachmentId attachmentId, @Nullable Attachment attachment, boolean isProfile) {
|
public Avatar(@Nullable AttachmentId attachmentId, @Nullable Attachment attachment, boolean isProfile) {
|
||||||
this.attachmentId = attachmentId;
|
this.attachmentId = attachmentId;
|
||||||
this.attachment = attachment;
|
this.attachment = attachment;
|
||||||
this.isProfile = isProfile;
|
this.isProfile = isProfile;
|
||||||
|
this.selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Avatar(@Nullable Uri attachmentUri, boolean isProfile) {
|
Avatar(@Nullable Uri attachmentUri, boolean isProfile) {
|
||||||
@ -624,6 +628,16 @@ public class Contact implements Parcelable {
|
|||||||
return isProfile;
|
return isProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelected(boolean selected) {
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelected() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package org.thoughtcrime.securesms.contactshare;
|
package org.thoughtcrime.securesms.contactshare;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -14,6 +16,7 @@ import com.annimon.stream.Stream;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.contactshare.Contact.Phone;
|
import org.thoughtcrime.securesms.contactshare.Contact.Phone;
|
||||||
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -23,14 +26,16 @@ import static org.thoughtcrime.securesms.contactshare.Contact.*;
|
|||||||
|
|
||||||
class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.ContactFieldViewHolder> {
|
class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.ContactFieldViewHolder> {
|
||||||
|
|
||||||
private final Locale locale;
|
private final Locale locale;
|
||||||
private final boolean selectable;
|
private final boolean selectable;
|
||||||
private final List<Field> fields;
|
private final List<Field> fields;
|
||||||
|
private final GlideRequests glideRequests;
|
||||||
|
|
||||||
public ContactFieldAdapter(@NonNull Locale locale, boolean selectable) {
|
public ContactFieldAdapter(@NonNull Locale locale, @NonNull GlideRequests glideRequests, boolean selectable) {
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
this.selectable = selectable;
|
this.glideRequests = glideRequests;
|
||||||
this.fields = new ArrayList<>();
|
this.selectable = selectable;
|
||||||
|
this.fields = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -40,7 +45,7 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ContactFieldViewHolder holder, int position) {
|
public void onBindViewHolder(ContactFieldViewHolder holder, int position) {
|
||||||
holder.bind(fields.get(position), selectable);
|
holder.bind(fields.get(position), glideRequests, selectable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,13 +58,18 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
|||||||
return fields.size();
|
return fields.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFields(@NonNull Context context,
|
void setFields(@NonNull Context context,
|
||||||
@NonNull List<Phone> phoneNumbers,
|
@Nullable Avatar avatar,
|
||||||
@NonNull List<Email> emails,
|
@NonNull List<Phone> phoneNumbers,
|
||||||
@NonNull List<PostalAddress> postalAddresses)
|
@NonNull List<Email> emails,
|
||||||
|
@NonNull List<PostalAddress> postalAddresses)
|
||||||
{
|
{
|
||||||
fields.clear();
|
fields.clear();
|
||||||
|
|
||||||
|
if (avatar != null) {
|
||||||
|
fields.add(new Field(avatar));
|
||||||
|
}
|
||||||
|
|
||||||
fields.addAll(Stream.of(phoneNumbers).map(phone -> new Field(context, phone, locale)).toList());
|
fields.addAll(Stream.of(phoneNumbers).map(phone -> new Field(context, phone, locale)).toList());
|
||||||
fields.addAll(Stream.of(emails).map(email -> new Field(context, email)).toList());
|
fields.addAll(Stream.of(emails).map(email -> new Field(context, email)).toList());
|
||||||
fields.addAll(Stream.of(postalAddresses).map(address -> new Field(context, address)).toList());
|
fields.addAll(Stream.of(postalAddresses).map(address -> new Field(context, address)).toList());
|
||||||
@ -72,6 +82,7 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
|||||||
private final TextView value;
|
private final TextView value;
|
||||||
private final TextView label;
|
private final TextView label;
|
||||||
private final ImageView icon;
|
private final ImageView icon;
|
||||||
|
private final ImageView avatar;
|
||||||
private final CheckBox checkBox;
|
private final CheckBox checkBox;
|
||||||
|
|
||||||
ContactFieldViewHolder(View itemView) {
|
ContactFieldViewHolder(View itemView) {
|
||||||
@ -80,14 +91,24 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
|||||||
value = itemView.findViewById(R.id.contact_field_value);
|
value = itemView.findViewById(R.id.contact_field_value);
|
||||||
label = itemView.findViewById(R.id.contact_field_label);
|
label = itemView.findViewById(R.id.contact_field_label);
|
||||||
icon = itemView.findViewById(R.id.contact_field_icon);
|
icon = itemView.findViewById(R.id.contact_field_icon);
|
||||||
|
avatar = itemView.findViewById(R.id.contact_field_avatar);
|
||||||
checkBox = itemView.findViewById(R.id.contact_field_checkbox);
|
checkBox = itemView.findViewById(R.id.contact_field_checkbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(@NonNull Field field, boolean selectable) {
|
void bind(@NonNull Field field, @NonNull GlideRequests glideRequests, boolean selectable) {
|
||||||
value.setMaxLines(field.maxLines);
|
value.setMaxLines(field.maxLines);
|
||||||
value.setText(field.value);
|
value.setText(field.value);
|
||||||
label.setText(field.label);
|
label.setText(field.label);
|
||||||
icon.setImageResource(field.iconResId);
|
|
||||||
|
if (field.iconUri != null) {
|
||||||
|
avatar.setVisibility(View.VISIBLE);
|
||||||
|
icon.setVisibility(View.GONE);
|
||||||
|
glideRequests.load(field.iconUri).circleCrop().into(avatar);
|
||||||
|
} else {
|
||||||
|
icon.setVisibility(View.VISIBLE);
|
||||||
|
avatar.setVisibility(View.GONE);
|
||||||
|
icon.setImageResource(field.iconResId);
|
||||||
|
}
|
||||||
|
|
||||||
if (selectable) {
|
if (selectable) {
|
||||||
checkBox.setVisibility(View.VISIBLE);
|
checkBox.setVisibility(View.VISIBLE);
|
||||||
@ -113,9 +134,13 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
|||||||
final int maxLines;
|
final int maxLines;
|
||||||
final Selectable selectable;
|
final Selectable selectable;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
final Uri iconUri;
|
||||||
|
|
||||||
Field(@NonNull Context context, @NonNull Phone phoneNumber, @NonNull Locale locale) {
|
Field(@NonNull Context context, @NonNull Phone phoneNumber, @NonNull Locale locale) {
|
||||||
this.value = ContactUtil.getPrettyPhoneNumber(phoneNumber, locale);
|
this.value = ContactUtil.getPrettyPhoneNumber(phoneNumber, locale);
|
||||||
this.iconResId = R.drawable.ic_call_white_24dp;
|
this.iconResId = R.drawable.ic_call_white_24dp;
|
||||||
|
this.iconUri = null;
|
||||||
this.maxLines = 1;
|
this.maxLines = 1;
|
||||||
this.selectable = phoneNumber;
|
this.selectable = phoneNumber;
|
||||||
|
|
||||||
@ -140,6 +165,7 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
|||||||
Field(@NonNull Context context, @NonNull Email email) {
|
Field(@NonNull Context context, @NonNull Email email) {
|
||||||
this.value = email.getEmail();
|
this.value = email.getEmail();
|
||||||
this.iconResId = R.drawable.baseline_email_white_24;
|
this.iconResId = R.drawable.baseline_email_white_24;
|
||||||
|
this.iconUri = null;
|
||||||
this.maxLines = 1;
|
this.maxLines = 1;
|
||||||
this.selectable = email;
|
this.selectable = email;
|
||||||
|
|
||||||
@ -164,6 +190,7 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
|||||||
Field(@NonNull Context context, @NonNull PostalAddress postalAddress) {
|
Field(@NonNull Context context, @NonNull PostalAddress postalAddress) {
|
||||||
this.value = postalAddress.toString();
|
this.value = postalAddress.toString();
|
||||||
this.iconResId = R.drawable.ic_location_on_white_24dp;
|
this.iconResId = R.drawable.ic_location_on_white_24dp;
|
||||||
|
this.iconUri = null;
|
||||||
this.maxLines = 3;
|
this.maxLines = 3;
|
||||||
this.selectable = postalAddress;
|
this.selectable = postalAddress;
|
||||||
|
|
||||||
@ -182,6 +209,15 @@ class ContactFieldAdapter extends RecyclerView.Adapter<ContactFieldAdapter.Conta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Field(@NonNull Avatar avatar) {
|
||||||
|
this.value = "";
|
||||||
|
this.iconResId = 0;
|
||||||
|
this.iconUri = avatar.getAttachment() != null ? avatar.getAttachment().getDataUri() : null;
|
||||||
|
this.maxLines = 1;
|
||||||
|
this.selectable = avatar;
|
||||||
|
this.label = "";
|
||||||
|
}
|
||||||
|
|
||||||
void setSelected(boolean selected) {
|
void setSelected(boolean selected) {
|
||||||
selectable.setSelected(selected);
|
selectable.setSelected(selected);
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,14 @@ public class ContactShareEditAdapter extends RecyclerView.Adapter<ContactShareEd
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ContactEditViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ContactEditViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
return new ContactEditViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_editable_contact, parent, false), locale);
|
return new ContactEditViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_editable_contact, parent, false),
|
||||||
|
locale,
|
||||||
|
glideRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ContactEditViewHolder holder, int position) {
|
public void onBindViewHolder(ContactEditViewHolder holder, int position) {
|
||||||
holder.bind(position, contacts.get(position), glideRequests, eventListener);
|
holder.bind(position, contacts.get(position), eventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -63,18 +65,16 @@ public class ContactShareEditAdapter extends RecyclerView.Adapter<ContactShareEd
|
|||||||
|
|
||||||
static class ContactEditViewHolder extends RecyclerView.ViewHolder {
|
static class ContactEditViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
private final AvatarImageView avatar;
|
|
||||||
private final TextView name;
|
private final TextView name;
|
||||||
private final View nameEditButton;
|
private final View nameEditButton;
|
||||||
private final ContactFieldAdapter fieldAdapter;
|
private final ContactFieldAdapter fieldAdapter;
|
||||||
|
|
||||||
ContactEditViewHolder(View itemView, @NonNull Locale locale) {
|
ContactEditViewHolder(View itemView, @NonNull Locale locale, @NonNull GlideRequests glideRequests) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
|
|
||||||
this.avatar = itemView.findViewById(R.id.editable_contact_avatar);
|
|
||||||
this.name = itemView.findViewById(R.id.editable_contact_name);
|
this.name = itemView.findViewById(R.id.editable_contact_name);
|
||||||
this.nameEditButton = itemView.findViewById(R.id.editable_contact_name_edit_button);
|
this.nameEditButton = itemView.findViewById(R.id.editable_contact_name_edit_button);
|
||||||
this.fieldAdapter = new ContactFieldAdapter(locale, true);
|
this.fieldAdapter = new ContactFieldAdapter(locale, glideRequests, true);
|
||||||
|
|
||||||
RecyclerView fields = itemView.findViewById(R.id.editable_contact_fields);
|
RecyclerView fields = itemView.findViewById(R.id.editable_contact_fields);
|
||||||
fields.setLayoutManager(new LinearLayoutManager(itemView.getContext()));
|
fields.setLayoutManager(new LinearLayoutManager(itemView.getContext()));
|
||||||
@ -82,25 +82,12 @@ public class ContactShareEditAdapter extends RecyclerView.Adapter<ContactShareEd
|
|||||||
fields.setAdapter(fieldAdapter);
|
fields.setAdapter(fieldAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(int position, @NonNull Contact contact, @NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) {
|
void bind(int position, @NonNull Contact contact, @NonNull EventListener eventListener) {
|
||||||
Context context = itemView.getContext();
|
Context context = itemView.getContext();
|
||||||
|
|
||||||
if (contact.getAvatarAttachment() != null && contact.getAvatarAttachment().getDataUri() != null) {
|
|
||||||
glideRequests.load(contact.getAvatarAttachment().getDataUri())
|
|
||||||
.fallback(R.drawable.ic_contact_picture)
|
|
||||||
.circleCrop()
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
|
||||||
.into(avatar);
|
|
||||||
} else {
|
|
||||||
glideRequests.load(R.drawable.ic_contact_picture)
|
|
||||||
.circleCrop()
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
|
||||||
.into(avatar);
|
|
||||||
}
|
|
||||||
|
|
||||||
name.setText(ContactUtil.getDisplayName(contact));
|
name.setText(ContactUtil.getDisplayName(contact));
|
||||||
nameEditButton.setOnClickListener(v -> eventListener.onNameEditClicked(position, contact.getName()));
|
nameEditButton.setOnClickListener(v -> eventListener.onNameEditClicked(position, contact.getName()));
|
||||||
fieldAdapter.setFields(context, contact.getPhoneNumbers(), contact.getEmails(), contact.getPostalAddresses());
|
fieldAdapter.setFields(context, contact.getAvatar(), contact.getPhoneNumbers(), contact.getEmails(), contact.getPostalAddresses());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class ContactShareEditViewModel extends ViewModel {
|
|||||||
trimSelectables(contact.getPhoneNumbers()),
|
trimSelectables(contact.getPhoneNumbers()),
|
||||||
trimSelectables(contact.getEmails()),
|
trimSelectables(contact.getEmails()),
|
||||||
trimSelectables(contact.getPostalAddresses()),
|
trimSelectables(contact.getPostalAddresses()),
|
||||||
contact.getAvatar());
|
contact.getAvatar() != null && contact.getAvatar().isSelected() ? contact.getAvatar() : null);
|
||||||
trimmedContacts.add(trimmed);
|
trimmedContacts.add(trimmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ public class SharedContactDetailsActivity extends PassphraseRequiredActionBarAct
|
|||||||
messageButtonView = findViewById(R.id.contact_details_message_button);
|
messageButtonView = findViewById(R.id.contact_details_message_button);
|
||||||
callButtonView = findViewById(R.id.contact_details_call_button);
|
callButtonView = findViewById(R.id.contact_details_call_button);
|
||||||
|
|
||||||
contactFieldAdapter = new ContactFieldAdapter(dynamicLanguage.getCurrentLocale(), false);
|
contactFieldAdapter = new ContactFieldAdapter(dynamicLanguage.getCurrentLocale(), glideRequests, false);
|
||||||
|
|
||||||
RecyclerView list = findViewById(R.id.contact_details_fields);
|
RecyclerView list = findViewById(R.id.contact_details_fields);
|
||||||
list.setLayoutManager(new LinearLayoutManager(this));
|
list.setLayoutManager(new LinearLayoutManager(this));
|
||||||
@ -171,7 +171,7 @@ public class SharedContactDetailsActivity extends PassphraseRequiredActionBarAct
|
|||||||
}.execute();
|
}.execute();
|
||||||
});
|
});
|
||||||
|
|
||||||
contactFieldAdapter.setFields(this, contact.getPhoneNumbers(), contact.getEmails(), contact.getPostalAddresses());
|
contactFieldAdapter.setFields(this, null, contact.getPhoneNumbers(), contact.getEmails(), contact.getPostalAddresses());
|
||||||
} else {
|
} else {
|
||||||
nameView.setText("");
|
nameView.setText("");
|
||||||
numberView.setText("");
|
numberView.setText("");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user