Fix jank and decrease animation duration in share contact selection recycler.

This commit is contained in:
Alex Hart
2021-06-08 13:10:54 -03:00
committed by GitHub
parent c72dd86fed
commit cf361334c4
9 changed files with 54 additions and 28 deletions

View File

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

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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() {

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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;
}