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
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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;
}

View file

@ -6,5 +6,4 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:paddingEnd="5sp"
tools:text="@tools:sample/first_names" />

View file

@ -3251,7 +3251,7 @@
<!-- ShareActivity -->
<string name="ShareActivity__share">Share</string>
<string name="ShareActivity__send">Send</string>
<string name="ShareActivity__s_comma">%1$s,</string>
<string name="ShareActivity__comma_s">, %1$s</string>
<string name="ShareActivity__sharing_to_multiple_chats_is">Sharing to multiple chats is only supported for Signal messages</string>
<!-- MultiShareDialogs -->