mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-24 11:45:28 +00:00
Fix jank and decrease animation duration in share contact selection recycler.
This commit is contained in:
@@ -49,7 +49,6 @@ import org.thoughtcrime.securesms.components.SearchToolbar;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.mediasend.Media;
|
||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@@ -67,6 +66,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -254,6 +254,9 @@ public class ShareActivity extends PassphraseRequiredActivity
|
||||
RecyclerView contactsRecycler = findViewById(R.id.selected_list);
|
||||
contactsRecycler.setAdapter(adapter);
|
||||
|
||||
RecyclerView.ItemAnimator itemAnimator = Objects.requireNonNull(contactsRecycler.getItemAnimator());
|
||||
ShareFlowConstants.applySelectedContactsRecyclerAnimationSpeeds(itemAnimator);
|
||||
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.contact_selection_list_fragment, contactsFragment)
|
||||
.commit();
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.thoughtcrime.securesms.sharing
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
internal object ShareFlowConstants {
|
||||
|
||||
private const val ADD_DURATION = 60L
|
||||
private const val REMOVE_DURATION = 60L
|
||||
private const val MOVE_DURATION = 125L
|
||||
private const val CHANGE_DURATION = 125L
|
||||
|
||||
@JvmStatic
|
||||
fun applySelectedContactsRecyclerAnimationSpeeds(
|
||||
itemAnimator: RecyclerView.ItemAnimator
|
||||
) {
|
||||
itemAnimator.addDuration = ADD_DURATION
|
||||
itemAnimator.removeDuration = REMOVE_DURATION
|
||||
itemAnimator.moveDuration = MOVE_DURATION
|
||||
itemAnimator.changeDuration = CHANGE_DURATION
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,11 @@ import org.thoughtcrime.securesms.util.MappingModel;
|
||||
class ShareSelectionMappingModel implements MappingModel<ShareSelectionMappingModel> {
|
||||
|
||||
private final ShareContact shareContact;
|
||||
private final boolean isLast;
|
||||
private final boolean isFirst;
|
||||
|
||||
ShareSelectionMappingModel(@NonNull ShareContact shareContact, boolean isLast) {
|
||||
ShareSelectionMappingModel(@NonNull ShareContact shareContact, boolean isFirst) {
|
||||
this.shareContact = shareContact;
|
||||
this.isLast = isLast;
|
||||
this.isFirst = isFirst;
|
||||
}
|
||||
|
||||
@NonNull String getName(@NonNull Context context) {
|
||||
@@ -25,7 +25,7 @@ class ShareSelectionMappingModel implements MappingModel<ShareSelectionMappingMo
|
||||
: recipient.getShortDisplayNameIncludingUsername(context))
|
||||
.or(shareContact.getNumber());
|
||||
|
||||
return isLast ? name : context.getString(R.string.ShareActivity__s_comma, name);
|
||||
return isFirst ? name : context.getString(R.string.ShareActivity__comma_s, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -35,6 +35,6 @@ class ShareSelectionMappingModel implements MappingModel<ShareSelectionMappingMo
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull ShareSelectionMappingModel newItem) {
|
||||
return areItemsTheSame(newItem) && newItem.isLast == isLast;
|
||||
return areItemsTheSame(newItem) && newItem.isFirst == isFirst;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.Transformations;
|
||||
@@ -19,8 +18,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.DefaultValueLiveData;
|
||||
import org.thoughtcrime.securesms.util.MappingModel;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||
import org.thoughtcrime.securesms.util.MappingModelList;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -89,10 +87,10 @@ public class ShareViewModel extends ViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull LiveData<List<MappingModel<?>>> getSelectedContactModels() {
|
||||
@NonNull LiveData<MappingModelList> getSelectedContactModels() {
|
||||
return Transformations.map(selectedContacts, set -> Stream.of(set)
|
||||
.<MappingModel<?>>mapIndexed((i, c) -> new ShareSelectionMappingModel(c, i == set.size() - 1))
|
||||
.toList());
|
||||
.mapIndexed((i, c) -> new ShareSelectionMappingModel(c, i == 0))
|
||||
.collect(MappingModelList.toMappingModelList()));
|
||||
}
|
||||
|
||||
@NonNull LiveData<SmsShareRestriction> getSmsShareRestriction() {
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.view.View;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
@@ -23,11 +24,14 @@ import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.sharing.MultiShareArgs;
|
||||
import org.thoughtcrime.securesms.sharing.MultiShareDialogs;
|
||||
import org.thoughtcrime.securesms.sharing.ShareFlowConstants;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Handles display and editing of a text message (with possible link preview) before it is forwarded
|
||||
* to multiple users.
|
||||
@@ -126,6 +130,9 @@ public class ShareInterstitialActivity extends PassphraseRequiredActivity {
|
||||
contactsRecycler = findViewById(R.id.selected_list);
|
||||
contactsRecycler.setAdapter(adapter);
|
||||
|
||||
RecyclerView.ItemAnimator itemAnimator = Objects.requireNonNull(contactsRecycler.getItemAnimator());
|
||||
ShareFlowConstants.applySelectedContactsRecyclerAnimationSpeeds(itemAnimator);
|
||||
|
||||
confirm.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
|
||||
int pad = Math.abs(v.getWidth() + ViewUtil.dpToPx(16));
|
||||
ViewUtil.setPaddingEnd(contactsRecycler, pad);
|
||||
|
||||
@@ -11,11 +11,11 @@ import org.thoughtcrime.securesms.util.viewholders.RecipientMappingModel;
|
||||
class ShareInterstitialMappingModel extends RecipientMappingModel<ShareInterstitialMappingModel> {
|
||||
|
||||
private final Recipient recipient;
|
||||
private final boolean isLast;
|
||||
private final boolean isFirst;
|
||||
|
||||
ShareInterstitialMappingModel(@NonNull Recipient recipient, boolean isLast) {
|
||||
ShareInterstitialMappingModel(@NonNull Recipient recipient, boolean isFirst) {
|
||||
this.recipient = recipient;
|
||||
this.isLast = isLast;
|
||||
this.isFirst = isFirst;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,7 +23,7 @@ class ShareInterstitialMappingModel extends RecipientMappingModel<ShareInterstit
|
||||
String name = recipient.isSelf() ? context.getString(R.string.note_to_self)
|
||||
: recipient.getShortDisplayNameIncludingUsername(context);
|
||||
|
||||
return isLast ? name : context.getString(R.string.ShareActivity__s_comma, name);
|
||||
return isFirst ? name : context.getString(R.string.ShareActivity__comma_s, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -33,6 +33,6 @@ class ShareInterstitialMappingModel extends RecipientMappingModel<ShareInterstit
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull ShareInterstitialMappingModel newItem) {
|
||||
return super.areContentsTheSame(newItem) && isLast == newItem.isLast;
|
||||
return super.areContentsTheSame(newItem) && isFirst == newItem.isFirst;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,14 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.sharing.MultiShareArgs;
|
||||
import org.thoughtcrime.securesms.sharing.MultiShareSender;
|
||||
import org.thoughtcrime.securesms.util.DefaultValueLiveData;
|
||||
import org.thoughtcrime.securesms.util.MappingModel;
|
||||
import org.thoughtcrime.securesms.util.MappingModelList;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class ShareInterstitialViewModel extends ViewModel {
|
||||
|
||||
private final MultiShareArgs args;
|
||||
private final MutableLiveData<List<MappingModel<?>>> recipients;
|
||||
private final MutableLiveData<String> draftText;
|
||||
private final MultiShareArgs args;
|
||||
private final MutableLiveData<MappingModelList> recipients;
|
||||
private final MutableLiveData<String> draftText;
|
||||
|
||||
private LinkPreview linkPreview;
|
||||
|
||||
@@ -37,12 +35,12 @@ private final MultiShareArgs args;
|
||||
|
||||
repository.loadRecipients(args.getShareContactAndThreads(),
|
||||
list -> recipients.postValue(Stream.of(list)
|
||||
.<MappingModel<?>>mapIndexed((i, r) -> new ShareInterstitialMappingModel(r, i == list.size() - 1))
|
||||
.toList()));
|
||||
.mapIndexed((i, r) -> new ShareInterstitialMappingModel(r, i == 0))
|
||||
.collect(MappingModelList.toMappingModelList())));
|
||||
|
||||
}
|
||||
|
||||
LiveData<List<MappingModel<?>>> getRecipients() {
|
||||
LiveData<MappingModelList> getRecipients() {
|
||||
return recipients;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user