NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/PhonebookSelectShareAlert.java

1013 lines
46 KiB
Java
Raw Normal View History

2019-12-31 14:08:08 +01:00
/*
* This is the source code of Telegram for Android v. 5.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2018.
*/
package org.telegram.ui.Components;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.SparseBooleanArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChatActivity;
import java.util.ArrayList;
import java.util.HashMap;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class PhonebookSelectShareAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate {
private FrameLayout frameLayout;
private RecyclerListView listView;
private LinearLayoutManager layoutManager;
private ShareAdapter listAdapter;
private ShareSearchAdapter searchAdapter;
private EmptyTextProgressView searchEmptyView;
private Drawable shadowDrawable;
private View shadow;
private AnimatorSet shadowAnimation;
private ChatActivity chatActivity;
private int scrollOffsetY;
private int topBeforeSwitch;
private PhonebookShareAlertDelegate delegate;
public interface PhonebookShareAlertDelegate {
void didSelectContact(TLRPC.User user, boolean notify, int scheduleDate);
}
public class UserCell extends FrameLayout {
private BackupImageView avatarImageView;
private SimpleTextView nameTextView;
private SimpleTextView statusTextView;
private AvatarDrawable avatarDrawable;
private TLRPC.User currentUser;
private int currentId;
private CharSequence currentName;
private CharSequence currentStatus;
private String lastName;
private int lastStatus;
private TLRPC.FileLocation lastAvatar;
private int currentAccount = UserConfig.selectedAccount;
private boolean needDivider;
public UserCell(Context context) {
super(context);
avatarDrawable = new AvatarDrawable();
avatarImageView = new BackupImageView(context);
avatarImageView.setRoundRadius(AndroidUtilities.dp(23));
addView(avatarImageView, LayoutHelper.createFrame(46, 46, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 14, 9, LocaleController.isRTL ? 14 : 0, 0));
nameTextView = new SimpleTextView(context);
nameTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
nameTextView.setTextSize(16);
nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 28 : 72, 12, LocaleController.isRTL ? 72 : 28, 0));
statusTextView = new SimpleTextView(context);
statusTextView.setTextSize(13);
statusTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2));
statusTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
addView(statusTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 28 : 72, 36, LocaleController.isRTL ? 72 : 28, 0));
}
public void setCurrentId(int id) {
currentId = id;
}
public void setData(TLRPC.User user, CharSequence name, CharSequence status, boolean divider) {
if (user == null && name == null && status == null) {
currentStatus = null;
currentName = null;
nameTextView.setText("");
statusTextView.setText("");
avatarImageView.setImageDrawable(null);
return;
}
currentStatus = status;
currentName = name;
currentUser = user;
needDivider = divider;
setWillNotDraw(!needDivider);
update(0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
}
public void update(int mask) {
TLRPC.FileLocation photo = null;
String newName = null;
if (currentUser != null && currentUser.photo != null) {
photo = currentUser.photo.photo_small;
}
if (mask != 0) {
boolean continueUpdate = false;
if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0) {
if (lastAvatar != null && photo == null || lastAvatar == null && photo != null || lastAvatar != null && photo != null && (lastAvatar.volume_id != photo.volume_id || lastAvatar.local_id != photo.local_id)) {
continueUpdate = true;
}
}
if (currentUser != null && !continueUpdate && (mask & MessagesController.UPDATE_MASK_STATUS) != 0) {
int newStatus = 0;
if (currentUser.status != null) {
newStatus = currentUser.status.expires;
}
if (newStatus != lastStatus) {
continueUpdate = true;
}
}
if (!continueUpdate && currentName == null && lastName != null && (mask & MessagesController.UPDATE_MASK_NAME) != 0) {
if (currentUser != null) {
newName = UserObject.getUserName(currentUser);
}
if (!newName.equals(lastName)) {
continueUpdate = true;
}
}
if (!continueUpdate) {
return;
}
}
if (currentUser != null) {
avatarDrawable.setInfo(currentUser);
if (currentUser.status != null) {
lastStatus = currentUser.status.expires;
} else {
lastStatus = 0;
}
} else if (currentName != null) {
avatarDrawable.setInfo(currentId, currentName.toString(), null);
} else {
avatarDrawable.setInfo(currentId, "#", null);
}
if (currentName != null) {
lastName = null;
nameTextView.setText(currentName);
} else {
if (currentUser != null) {
lastName = newName == null ? UserObject.getUserName(currentUser) : newName;
} else {
lastName = "";
}
nameTextView.setText(lastName);
}
if (currentStatus != null) {
statusTextView.setText(currentStatus);
} else if (currentUser != null) {
if (TextUtils.isEmpty(currentUser.phone)) {
statusTextView.setText(LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
} else {
statusTextView.setText(PhoneFormat.getInstance().format("+" + currentUser.phone));
}
}
lastAvatar = photo;
if (currentUser != null) {
avatarImageView.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser);
} else {
avatarImageView.setImageDrawable(avatarDrawable);
}
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
@Override
protected void onDraw(Canvas canvas) {
if (needDivider) {
canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(70), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(70) : 0), getMeasuredHeight() - 1, Theme.dividerPaint);
}
}
}
@SuppressWarnings("FieldCanBeLocal")
private class SearchField extends FrameLayout {
private View searchBackground;
private ImageView searchIconImageView;
private ImageView clearSearchImageView;
private CloseProgressDrawable2 progressDrawable;
private EditTextBoldCursor searchEditText;
private View backgroundView;
public SearchField(Context context) {
super(context);
searchBackground = new View(context);
searchBackground.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(18), Theme.getColor(Theme.key_dialogSearchBackground)));
addView(searchBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 14, 11, 14, 0));
searchIconImageView = new ImageView(context);
searchIconImageView.setScaleType(ImageView.ScaleType.CENTER);
searchIconImageView.setImageResource(R.drawable.smiles_inputsearch);
searchIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogSearchIcon), PorterDuff.Mode.MULTIPLY));
addView(searchIconImageView, LayoutHelper.createFrame(36, 36, Gravity.LEFT | Gravity.TOP, 16, 11, 0, 0));
clearSearchImageView = new ImageView(context);
clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER);
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
progressDrawable.setSide(AndroidUtilities.dp(7));
clearSearchImageView.setScaleX(0.1f);
clearSearchImageView.setScaleY(0.1f);
clearSearchImageView.setAlpha(0.0f);
clearSearchImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogSearchIcon), PorterDuff.Mode.MULTIPLY));
addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 11, 14, 0));
clearSearchImageView.setOnClickListener(v -> {
searchEditText.setText("");
AndroidUtilities.showKeyboard(searchEditText);
});
searchEditText = new EditTextBoldCursor(context) {
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
MotionEvent e = MotionEvent.obtain(event);
e.setLocation(e.getRawX(), e.getRawY() - containerView.getTranslationY());
listView.dispatchTouchEvent(e);
e.recycle();
return super.dispatchTouchEvent(event);
}
};
searchEditText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
searchEditText.setHintTextColor(Theme.getColor(Theme.key_dialogSearchHint));
searchEditText.setTextColor(Theme.getColor(Theme.key_dialogSearchText));
searchEditText.setBackgroundDrawable(null);
searchEditText.setPadding(0, 0, 0, 0);
searchEditText.setMaxLines(1);
searchEditText.setLines(1);
searchEditText.setSingleLine(true);
searchEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH | EditorInfo.IME_FLAG_NO_EXTRACT_UI);
searchEditText.setHint(LocaleController.getString("SearchFriends", R.string.SearchFriends));
searchEditText.setCursorColor(Theme.getColor(Theme.key_featuredStickers_addedIcon));
searchEditText.setCursorSize(AndroidUtilities.dp(20));
searchEditText.setCursorWidth(1.5f);
addView(searchEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.LEFT | Gravity.TOP, 16 + 38, 9, 16 + 30, 0));
searchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
boolean show = searchEditText.length() > 0;
boolean showed = clearSearchImageView.getAlpha() != 0;
if (show != showed) {
clearSearchImageView.animate()
.alpha(show ? 1.0f : 0.0f)
.setDuration(150)
.scaleX(show ? 1.0f : 0.1f)
.scaleY(show ? 1.0f : 0.1f)
.start();
}
String text = searchEditText.getText().toString();
if (text.length() != 0) {
if (searchEmptyView != null) {
searchEmptyView.setText(LocaleController.getString("NoResult", R.string.NoResult));
}
} else {
if (listView.getAdapter() != listAdapter) {
int top = getCurrentTop();
searchEmptyView.setText(LocaleController.getString("NoContacts", R.string.NoContacts));
searchEmptyView.showTextView();
listView.setAdapter(listAdapter);
listAdapter.notifyDataSetChanged();
if (top > 0) {
layoutManager.scrollToPositionWithOffset(0, -top);
}
}
}
if (searchAdapter != null) {
searchAdapter.search(text);
}
}
});
searchEditText.setOnEditorActionListener((v, actionId, event) -> {
if (event != null && (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_SEARCH || event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
AndroidUtilities.hideKeyboard(searchEditText);
}
return false;
});
}
public void hideKeyboard() {
AndroidUtilities.hideKeyboard(searchEditText);
}
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
public PhonebookSelectShareAlert(ChatActivity parentFragment) {
super(parentFragment.getParentActivity(), true);
chatActivity = parentFragment;
Context context = parentFragment.getParentActivity();
shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate();
shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY));
searchAdapter = new ShareSearchAdapter(context);
containerView = new FrameLayout(context) {
private boolean ignoreLayout = false;
private RectF rect1 = new RectF();
private boolean fullHeight;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int totalHeight = MeasureSpec.getSize(heightMeasureSpec);
if (Build.VERSION.SDK_INT >= 21 && !isFullscreen) {
ignoreLayout = true;
setPadding(backgroundPaddingLeft, AndroidUtilities.statusBarHeight, backgroundPaddingLeft, 0);
ignoreLayout = false;
}
int availableHeight = totalHeight - getPaddingTop();
int size = Math.max(searchAdapter.getItemCount(), listAdapter.getItemCount());
if (size > 0) {
size--;
}
int contentSize = AndroidUtilities.dp(56 + 35) + size * AndroidUtilities.dp(64) + size - 1 + backgroundPaddingTop;
int padding = (contentSize < availableHeight ? 0 : availableHeight - (availableHeight / 5 * 3)) + AndroidUtilities.dp(8);
if (listView.getPaddingTop() != padding) {
ignoreLayout = true;
listView.setPadding(0, padding, 0, 0);
ignoreLayout = false;
}
fullHeight = contentSize >= totalHeight;
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Math.min(contentSize, totalHeight), MeasureSpec.EXACTLY));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
updateLayout();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY - AndroidUtilities.dp(30)) {
dismiss();
return true;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
return !isDismissed() && super.onTouchEvent(e);
}
@Override
public void requestLayout() {
if (ignoreLayout) {
return;
}
super.requestLayout();
}
@Override
protected void onDraw(Canvas canvas) {
int y = scrollOffsetY - backgroundPaddingTop + AndroidUtilities.dp(6);
int top = scrollOffsetY - backgroundPaddingTop - AndroidUtilities.dp(13);
int height = getMeasuredHeight() + AndroidUtilities.dp(30) + backgroundPaddingTop;
int statusBarHeight = 0;
float radProgress = 1.0f;
if (!isFullscreen && Build.VERSION.SDK_INT >= 21) {
top += AndroidUtilities.statusBarHeight;
y += AndroidUtilities.statusBarHeight;
height -= AndroidUtilities.statusBarHeight;
if (fullHeight) {
if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight * 2) {
int diff = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight * 2 - top - backgroundPaddingTop);
top -= diff;
height += diff;
radProgress = 1.0f - Math.min(1.0f, (diff * 2) / (float) AndroidUtilities.statusBarHeight);
}
if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight) {
statusBarHeight = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight - top - backgroundPaddingTop);
}
}
}
shadowDrawable.setBounds(0, top, getMeasuredWidth(), height);
shadowDrawable.draw(canvas);
if (radProgress != 1.0f) {
Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_dialogBackground));
rect1.set(backgroundPaddingLeft, backgroundPaddingTop + top, getMeasuredWidth() - backgroundPaddingLeft, backgroundPaddingTop + top + AndroidUtilities.dp(24));
canvas.drawRoundRect(rect1, AndroidUtilities.dp(12) * radProgress, AndroidUtilities.dp(12) * radProgress, Theme.dialogs_onlineCirclePaint);
}
int w = AndroidUtilities.dp(36);
rect1.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + AndroidUtilities.dp(4));
Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_sheet_scrollUp));
canvas.drawRoundRect(rect1, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint);
if (statusBarHeight > 0) {
int color1 = Theme.getColor(Theme.key_dialogBackground);
int finalColor = Color.argb(0xff, (int) (Color.red(color1) * 0.8f), (int) (Color.green(color1) * 0.8f), (int) (Color.blue(color1) * 0.8f));
Theme.dialogs_onlineCirclePaint.setColor(finalColor);
canvas.drawRect(backgroundPaddingLeft, AndroidUtilities.statusBarHeight - statusBarHeight, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight, Theme.dialogs_onlineCirclePaint);
}
}
};
containerView.setWillNotDraw(false);
containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);
frameLayout = new FrameLayout(context);
frameLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground));
SearchField searchView = new SearchField(context);
frameLayout.addView(searchView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
listView = new RecyclerListView(context) {
@Override
protected boolean allowSelectChildAtPosition(float x, float y) {
return y >= scrollOffsetY + AndroidUtilities.dp(48) + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
}
};
listView.setClipToPadding(false);
listView.setLayoutManager(layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
listView.setHorizontalScrollBarEnabled(false);
listView.setVerticalScrollBarEnabled(false);
containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0));
listView.setAdapter(listAdapter = new ShareAdapter(context));
listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow));
listView.setOnItemClickListener((view, position) -> {
Object object;
if (listView.getAdapter() == searchAdapter) {
object = searchAdapter.getItem(position);
} else {
int section = listAdapter.getSectionForPosition(position);
int row = listAdapter.getPositionInSectionForPosition(position);
if (row < 0 || section < 0) {
return;
}
object = listAdapter.getItem(section, row);
}
if (object != null) {
String name;
ContactsController.Contact contact;
if (object instanceof ContactsController.Contact) {
contact = (ContactsController.Contact) object;
if (contact.user != null) {
name = ContactsController.formatName(contact.user.first_name, contact.user.last_name);
} else {
name = "";
}
} else {
TLRPC.User user = (TLRPC.User) object;
contact = new ContactsController.Contact();
contact.first_name = user.first_name;
contact.last_name = user.last_name;
contact.phones.add(user.phone);
contact.user = user;
name = ContactsController.formatName(contact.first_name, contact.last_name);
}
PhonebookShareAlert alert = new PhonebookShareAlert(chatActivity, contact, null, null, null, name);
alert.setDelegate((user, notify, scheduleDate) -> {
dismiss();
delegate.didSelectContact(user, notify, scheduleDate);
});
alert.show();
}
});
listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
updateLayout();
}
});
searchEmptyView = new EmptyTextProgressView(context);
searchEmptyView.setShowAtCenter(true);
searchEmptyView.showTextView();
searchEmptyView.setText(LocaleController.getString("NoContacts", R.string.NoContacts));
listView.setEmptyView(searchEmptyView);
containerView.addView(searchEmptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 52, 0, 0));
FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.TOP | Gravity.LEFT);
frameLayoutParams.topMargin = AndroidUtilities.dp(58);
shadow = new View(context);
shadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine));
shadow.setAlpha(0.0f);
shadow.setTag(1);
containerView.addView(shadow, frameLayoutParams);
containerView.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 58, Gravity.LEFT | Gravity.TOP));
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.contactsDidLoad);
}
private int getCurrentTop() {
if (listView.getChildCount() != 0) {
View child = listView.getChildAt(0);
RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child);
if (holder != null) {
return listView.getPaddingTop() - (holder.getAdapterPosition() == 0 && child.getTop() >= 0 ? child.getTop() : 0);
}
}
return -1000;
}
public void setDelegate(PhonebookShareAlertDelegate phonebookShareAlertDelegate) {
delegate = phonebookShareAlertDelegate;
}
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.contactsDidLoad) {
if (listAdapter != null) {
listAdapter.notifyDataSetChanged();
}
}
}
@Override
protected boolean canDismissWithSwipe() {
return false;
}
@SuppressLint("NewApi")
private void updateLayout() {
if (listView.getChildCount() <= 0) {
return;
}
View child = listView.getChildAt(0);
RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child);
int top = child.getTop() - AndroidUtilities.dp(8);
int newOffset = top > 0 && holder != null && holder.getAdapterPosition() == 0 ? top : 0;
if (top >= 0 && holder != null && holder.getAdapterPosition() == 0) {
newOffset = top;
runShadowAnimation(false);
} else {
runShadowAnimation(true);
}
if (scrollOffsetY != newOffset) {
listView.setTopGlowOffset(scrollOffsetY = newOffset);
frameLayout.setTranslationY(scrollOffsetY);
searchEmptyView.setTranslationY(scrollOffsetY);
containerView.invalidate();
}
}
private void runShadowAnimation(final boolean show) {
if (show && shadow.getTag() != null || !show && shadow.getTag() == null) {
shadow.setTag(show ? null : 1);
if (show) {
shadow.setVisibility(View.VISIBLE);
}
if (shadowAnimation != null) {
shadowAnimation.cancel();
}
shadowAnimation = new AnimatorSet();
shadowAnimation.playTogether(ObjectAnimator.ofFloat(shadow, View.ALPHA, show ? 1.0f : 0.0f));
shadowAnimation.setDuration(150);
shadowAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (shadowAnimation != null && shadowAnimation.equals(animation)) {
if (!show) {
shadow.setVisibility(View.INVISIBLE);
}
shadowAnimation = null;
}
}
@Override
public void onAnimationCancel(Animator animation) {
if (shadowAnimation != null && shadowAnimation.equals(animation)) {
shadowAnimation = null;
}
}
});
shadowAnimation.start();
}
}
@Override
public void dismiss() {
super.dismiss();
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.contactsDidLoad);
}
public class ShareAdapter extends RecyclerListView.SectionsAdapter {
private int currentAccount = UserConfig.selectedAccount;
private Context mContext;
public ShareAdapter(Context context) {
mContext = context;
}
public Object getItem(int section, int position) {
if (section == 0) {
return null;
}
section--;
HashMap<String, ArrayList<Object>> usersSectionsDict = ContactsController.getInstance(currentAccount).phoneBookSectionsDict;
ArrayList<String> sortedUsersSectionsArray = ContactsController.getInstance(currentAccount).phoneBookSectionsArray;
if (section < sortedUsersSectionsArray.size()) {
ArrayList<Object> arr = usersSectionsDict.get(sortedUsersSectionsArray.get(section));
if (position < arr.size()) {
return arr.get(position);
}
}
return null;
}
@Override
public boolean isEnabled(int section, int row) {
if (section == 0) {
return false;
}
section--;
HashMap<String, ArrayList<Object>> usersSectionsDict = ContactsController.getInstance(currentAccount).phoneBookSectionsDict;
ArrayList<String> sortedUsersSectionsArray = ContactsController.getInstance(currentAccount).phoneBookSectionsArray;
return row < usersSectionsDict.get(sortedUsersSectionsArray.get(section)).size();
}
@Override
public int getSectionCount() {
ArrayList<String> sortedUsersSectionsArray = ContactsController.getInstance(currentAccount).phoneBookSectionsArray;
return sortedUsersSectionsArray.size() + 1;
}
@Override
public int getCountForSection(int section) {
if (section == 0) {
return 1;
}
section--;
HashMap<String, ArrayList<Object>> usersSectionsDict = ContactsController.getInstance(currentAccount).phoneBookSectionsDict;
ArrayList<String> sortedUsersSectionsArray = ContactsController.getInstance(currentAccount).phoneBookSectionsArray;
if (section < sortedUsersSectionsArray.size()) {
return usersSectionsDict.get(sortedUsersSectionsArray.get(section)).size();
}
return 0;
}
@Override
public View getSectionHeaderView(int section, View view) {
return null;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case 0: {
view = new UserCell(mContext);
break;
}
case 1:
default: {
view = new View(mContext);
view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(56)));
break;
}
}
return new RecyclerListView.Holder(view);
}
@Override
public void onBindViewHolder(int section, int position, RecyclerView.ViewHolder holder) {
if (holder.getItemViewType() == 0) {
UserCell userCell = (UserCell) holder.itemView;
Object object = getItem(section, position);
TLRPC.User user = null;
boolean divider = section != getSectionCount() -1 || position != getCountForSection(section) - 1;
if (object instanceof ContactsController.Contact) {
ContactsController.Contact contact = (ContactsController.Contact) object;
if (contact.user != null) {
user = contact.user;
} else {
userCell.setCurrentId(contact.contact_id);
userCell.setData(null, ContactsController.formatName(contact.first_name, contact.last_name), contact.phones.isEmpty() ? "" : PhoneFormat.getInstance().format(contact.phones.get(0)), divider);
}
} else {
user = (TLRPC.User) object;
}
if (user != null) {
userCell.setData(user, null, PhoneFormat.getInstance().format("+" + user.phone), divider);
}
}
}
@Override
public int getItemViewType(int section, int position) {
if (section == 0) {
return 1;
}
return 0;
}
@Override
public String getLetter(int position) {
return null;
}
@Override
public int getPositionForScrollProgress(float progress) {
return 0;
}
}
public class ShareSearchAdapter extends RecyclerListView.SelectionAdapter {
private Context mContext;
private ArrayList<Object> searchResult = new ArrayList<>();
private ArrayList<CharSequence> searchResultNames = new ArrayList<>();
private Runnable searchRunnable;
private int lastSearchId;
public ShareSearchAdapter(Context context) {
mContext = context;
}
public void search(final String query) {
if (searchRunnable != null) {
Utilities.searchQueue.cancelRunnable(searchRunnable);
searchRunnable = null;
}
if (query == null) {
searchResult.clear();
searchResultNames.clear();
notifyDataSetChanged();
} else {
int searchId = ++lastSearchId;
Utilities.searchQueue.postRunnable(searchRunnable = () -> processSearch(query, searchId), 300);
}
}
private void processSearch(final String query, final int searchId) {
AndroidUtilities.runOnUIThread(() -> {
final int currentAccount = UserConfig.selectedAccount;
final ArrayList<ContactsController.Contact> contactsCopy = new ArrayList<>(ContactsController.getInstance(currentAccount).contactsBook.values());
final ArrayList<TLRPC.TL_contact> contactsCopy2 = new ArrayList<>(ContactsController.getInstance(currentAccount).contacts);
Utilities.searchQueue.postRunnable(() -> {
String search1 = query.trim().toLowerCase();
if (search1.length() == 0) {
lastSearchId = -1;
updateSearchResults(query, new ArrayList<>(), new ArrayList<>(), lastSearchId);
return;
}
String search2 = LocaleController.getInstance().getTranslitString(search1);
if (search1.equals(search2) || search2.length() == 0) {
search2 = null;
}
String[] search = new String[1 + (search2 != null ? 1 : 0)];
search[0] = search1;
if (search2 != null) {
search[1] = search2;
}
ArrayList<Object> resultArray = new ArrayList<>();
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
SparseBooleanArray foundUids = new SparseBooleanArray();
for (int a = 0; a < contactsCopy.size(); a++) {
ContactsController.Contact contact = contactsCopy.get(a);
String name = ContactsController.formatName(contact.first_name, contact.last_name).toLowerCase();
String tName = LocaleController.getInstance().getTranslitString(name);
String name2;
String tName2;
if (contact.user != null) {
name2 = ContactsController.formatName(contact.user.first_name, contact.user.last_name).toLowerCase();
tName2 = LocaleController.getInstance().getTranslitString(name);
} else {
name2 = null;
tName2 = null;
}
if (name.equals(tName)) {
tName = null;
}
int found = 0;
for (String q : search) {
if (name2 != null && (name2.startsWith(q) || name2.contains(" " + q)) || tName2 != null && (tName2.startsWith(q) || tName2.contains(" " + q))) {
found = 1;
} else if (contact.user != null && contact.user.username != null && contact.user.username.startsWith(q)) {
found = 2;
} else if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) {
found = 3;
}
if (found != 0) {
if (found == 3) {
resultArrayNames.add(AndroidUtilities.generateSearchName(contact.first_name, contact.last_name, q));
} else if (found == 1) {
resultArrayNames.add(AndroidUtilities.generateSearchName(contact.user.first_name, contact.user.last_name, q));
} else {
resultArrayNames.add(AndroidUtilities.generateSearchName("@" + contact.user.username, null, "@" + q));
}
if (contact.user != null) {
foundUids.put(contact.user.id, true);
}
resultArray.add(contact);
break;
}
}
}
for (int a = 0; a < contactsCopy2.size(); a++) {
TLRPC.TL_contact contact = contactsCopy2.get(a);
if (foundUids.indexOfKey(contact.user_id) >= 0) {
continue;
}
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(contact.user_id);
String name = ContactsController.formatName(user.first_name, user.last_name).toLowerCase();
String tName = LocaleController.getInstance().getTranslitString(name);
if (name.equals(tName)) {
tName = null;
}
int found = 0;
for (String q : search) {
if (name.startsWith(q) || name.contains(" " + q) || tName != null && (tName.startsWith(q) || tName.contains(" " + q))) {
found = 1;
} else if (user.username != null && user.username.startsWith(q)) {
found = 2;
}
if (found != 0) {
if (found == 1) {
resultArrayNames.add(AndroidUtilities.generateSearchName(user.first_name, user.last_name, q));
} else {
resultArrayNames.add(AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q));
}
resultArray.add(user);
break;
}
}
}
updateSearchResults(query, resultArray, resultArrayNames, searchId);
});
});
}
private void updateSearchResults(final String query, final ArrayList<Object> users, final ArrayList<CharSequence> names, final int searchId) {
AndroidUtilities.runOnUIThread(() -> {
if (searchId != lastSearchId) {
return;
}
if (searchId != -1 && listView.getAdapter() != searchAdapter) {
topBeforeSwitch = getCurrentTop();
listView.setAdapter(searchAdapter);
}
boolean becomeEmpty = !searchResult.isEmpty() && users.isEmpty();
boolean isEmpty = searchResult.isEmpty() && users.isEmpty();
if (becomeEmpty) {
topBeforeSwitch = getCurrentTop();
}
searchResult = users;
searchResultNames = names;
notifyDataSetChanged();
if (!isEmpty && !becomeEmpty && topBeforeSwitch > 0) {
layoutManager.scrollToPositionWithOffset(0, -topBeforeSwitch);
topBeforeSwitch = -1000;
}
});
}
@Override
public int getItemCount() {
return searchResult.isEmpty() ? 0 : (searchResult.size() + 1);
}
public Object getItem(int position) {
if (position == 0) {
return null;
}
return searchResult.get(position - 1);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case 0:
view = new UserCell(mContext);
break;
case 1:
default:
view = new View(mContext);
view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(56)));
break;
}
return new RecyclerListView.Holder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == 0) {
UserCell userCell = (UserCell) holder.itemView;
boolean divider = position != getItemCount() - 1;
Object object = getItem(position);
TLRPC.User user = null;
if (object instanceof ContactsController.Contact) {
ContactsController.Contact contact = (ContactsController.Contact) object;
if (contact.user != null) {
user = contact.user;
} else {
userCell.setCurrentId(contact.contact_id);
userCell.setData(null, searchResultNames.get(position - 1), contact.phones.isEmpty() ? "" : PhoneFormat.getInstance().format(contact.phones.get(0)), divider);
}
} else {
user = (TLRPC.User) object;
}
if (user != null) {
userCell.setData(user, searchResultNames.get(position - 1), PhoneFormat.getInstance().format("+" + user.phone), divider);
}
}
}
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
return true;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return 1;
}
return 0;
}
}
}