NekoX/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java

1768 lines
85 KiB
Java

package org.telegram.ui;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.DocumentObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.HeaderCell;
import org.telegram.ui.Cells.ManageChatTextCell;
import org.telegram.ui.Cells.ManageChatUserCell;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Cells.TextSettingsCell;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.DotDividerSpan;
import org.telegram.ui.Components.FlickerLoadingView;
import org.telegram.ui.Components.InviteLinkBottomSheet;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkActionView;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.TimerParticles;
import org.telegram.ui.Components.RecyclerItemsEnterAnimator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
public class ManageLinksActivity extends BaseFragment {
private ListAdapter listViewAdapter;
private RecyclerListView listView;
private TLRPC.Chat currentChat;
private TLRPC.ChatFull info;
private TLRPC.TL_chatInviteExported invite;
private long adminId;
private boolean isChannel;
private long currentChatId;
private int helpRow;
private int permanentLinkHeaderRow;
private int permanentLinkRow;
private int dividerRow;
private int createNewLinkRow;
private int linksStartRow;
private int linksEndRow;
private int linksLoadingRow;
private int revokedLinksStartRow;
private int revokedLinksEndRow;
private int revokedDivider;
private int lastDivider;
private int revokedHeader;
private int revokeAllDivider;
private int revokeAllRow;
private int createLinkHelpRow;
private int linksHeaderRow;
private int creatorRow;
private int creatorDividerRow;
private int adminsHeaderRow;
private int adminsDividerRow;
private int adminsStartRow;
private int adminsEndRow;
boolean linksLoading;
private int rowCount;
Drawable linkIcon;
Drawable linkIconRevoked;
boolean hasMore;
boolean deletingRevokedLinks;
boolean loadAdmins;
boolean adminsLoaded;
private int invitesCount;
private boolean isOpened;
private boolean transitionFinished;
private RecyclerItemsEnterAnimator recyclerItemsEnterAnimator;
private ArrayList<TLRPC.TL_chatInviteExported> invites = new ArrayList<>();
private ArrayList<TLRPC.TL_chatInviteExported> revokedInvites = new ArrayList<>();
private HashMap<Long, TLRPC.User> users = new HashMap<>();
private InviteLinkBottomSheet inviteLinkBottomSheet;
private ArrayList<TLRPC.TL_chatAdminWithInvites> admins = new ArrayList<>();
long timeDif;
private boolean isPublic;
private boolean canEdit;
Runnable updateTimerRunnable = new Runnable() {
@Override
public void run() {
if (listView == null) {
return;
}
for (int i = 0; i < listView.getChildCount(); i++) {
View child = listView.getChildAt(i);
if (child instanceof LinkCell) {
LinkCell linkCell = (LinkCell) child;
if (linkCell.timerRunning) {
linkCell.setLink(linkCell.invite, linkCell.position);
}
}
}
AndroidUtilities.runOnUIThread(this, 500);
}
};
private static class EmptyView extends LinearLayout implements NotificationCenter.NotificationCenterDelegate {
private BackupImageView stickerView;
private final int currentAccount = UserConfig.selectedAccount;
private static final String stickerSetName = AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME;
public EmptyView(Context context) {
super(context);
setPadding(0, AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12));
setOrientation(LinearLayout.VERTICAL);
stickerView = new BackupImageView(context);
addView(stickerView, LayoutHelper.createLinear(104, 104, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 2, 0, 0));
}
private void setSticker() {
TLRPC.TL_messages_stickerSet set = MediaDataController.getInstance(currentAccount).getStickerSetByName(stickerSetName);
if (set == null) {
set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(stickerSetName);
}
if (set != null && set.documents.size() >= 4) {
TLRPC.Document document = set.documents.get(3);
ImageLocation imageLocation = ImageLocation.getForDocument(document);
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundGray, 1.0f);
stickerView.setImage(imageLocation, "104_104", "tgs", svgThumb, set);
} else {
MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(stickerSetName, false, set == null);
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setSticker();
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.diceStickersDidLoad);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.diceStickersDidLoad);
}
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.diceStickersDidLoad) {
String name = (String) args[0];
if (stickerSetName.equals(name)) {
setSticker();
}
}
}
}
public ManageLinksActivity(long chatId, long adminId, int invitesCount) {
super();
currentChatId = chatId;
this.invitesCount = invitesCount;
currentChat = MessagesController.getInstance(currentAccount).getChat(chatId);
isChannel = ChatObject.isChannel(currentChat) && !currentChat.megagroup;
if (adminId == 0) {
this.adminId = getAccountInstance().getUserConfig().clientUserId;
} else {
this.adminId = adminId;
}
TLRPC.User user = getMessagesController().getUser(this.adminId);
canEdit = (this.adminId == getAccountInstance().getUserConfig().clientUserId) || (user != null && !user.bot);
}
boolean loadRevoked = false;
private void loadLinks(boolean notify) {
if (loadAdmins && !adminsLoaded) {
linksLoading = true;
TLRPC.TL_messages_getAdminsWithInvites req = new TLRPC.TL_messages_getAdminsWithInvites();
req.peer = getMessagesController().getInputPeer(-currentChatId);
int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> getNotificationCenter().doOnIdle(() -> {
linksLoading = false;
if (error == null) {
TLRPC.TL_messages_chatAdminsWithInvites adminsWithInvites = (TLRPC.TL_messages_chatAdminsWithInvites) response;
for (int i = 0; i < adminsWithInvites.admins.size(); i++) {
TLRPC.TL_chatAdminWithInvites admin = adminsWithInvites.admins.get(i);
if (admin.admin_id != getAccountInstance().getUserConfig().clientUserId) {
admins.add(admin);
}
}
for (int i = 0; i < adminsWithInvites.users.size(); i++) {
TLRPC.User user = adminsWithInvites.users.get(i);
users.put(user.id, user);
}
}
int oldRowsCount = rowCount;
adminsLoaded = true;
hasMore = false;
if (admins.size() > 0) {
if (recyclerItemsEnterAnimator != null && !isPaused && isOpened) {
recyclerItemsEnterAnimator.showItemsAnimated(oldRowsCount + 1);
}
}
if (!hasMore || (invites.size() + revokedInvites.size() + admins.size()) >= 5) {
resumeDelayedFragmentAnimation();
}
if (!hasMore && !loadRevoked) {
hasMore = true;
loadRevoked = true;
loadLinks(false);
}
updateRows(true);
})));
getConnectionsManager().bindRequestToGuid(reqId, getClassGuid());
} else {
TLRPC.TL_messages_getExportedChatInvites req = new TLRPC.TL_messages_getExportedChatInvites();
req.peer = getMessagesController().getInputPeer(-currentChatId);
if (adminId == getUserConfig().getClientUserId()) {
req.admin_id = getMessagesController().getInputUser(getUserConfig().getCurrentUser());
} else {
req.admin_id = getMessagesController().getInputUser(adminId);
}
boolean revoked = loadRevoked;
if (loadRevoked) {
req.revoked = true;
if (!revokedInvites.isEmpty()) {
req.flags |= 4;
req.offset_link = revokedInvites.get(revokedInvites.size() - 1).link;
req.offset_date = revokedInvites.get(revokedInvites.size() - 1).date;
}
} else {
if (!invites.isEmpty()) {
req.flags |= 4;
req.offset_link = invites.get(invites.size() - 1).link;
req.offset_date = invites.get(invites.size() - 1).date;
}
}
linksLoading = true;
TLRPC.TL_chatInviteExported inviteFinal = isPublic ? null : invite;
int reqId = getConnectionsManager().sendRequest(req, (response, error) -> {
TLRPC.TL_chatInviteExported permanentLink = null;
if (error == null) {
TLRPC.TL_messages_exportedChatInvites invites = (TLRPC.TL_messages_exportedChatInvites) response;
if (invites.invites.size() > 0 && inviteFinal != null) {
for (int i = 0; i < invites.invites.size(); i++) {
if (((TLRPC.TL_chatInviteExported) invites.invites.get(i)).link.equals(inviteFinal.link)) {
permanentLink = (TLRPC.TL_chatInviteExported) invites.invites.remove(i);
break;
}
}
}
}
TLRPC.TL_chatInviteExported finalPermanentLink = permanentLink;
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().doOnIdle(() -> {
DiffCallback callback = saveListState();
linksLoading = false;
hasMore = false;
if (finalPermanentLink != null) {
invite = finalPermanentLink;
if (info != null) {
info.exported_invite = finalPermanentLink;
}
}
boolean updateByDiffUtils = false;
if (error == null) {
TLRPC.TL_messages_exportedChatInvites invites = (TLRPC.TL_messages_exportedChatInvites) response;
if (revoked) {
for (int i = 0; i < invites.invites.size(); i++) {
TLRPC.TL_chatInviteExported in = (TLRPC.TL_chatInviteExported) invites.invites.get(i);
fixDate(in);
this.revokedInvites.add(in);
}
} else {
if (adminId != getAccountInstance().getUserConfig().clientUserId && this.invites.size() == 0 && invites.invites.size() > 0) {
invite = (TLRPC.TL_chatInviteExported) invites.invites.get(0);
invites.invites.remove(0);
}
for (int i = 0; i < invites.invites.size(); i++) {
TLRPC.TL_chatInviteExported in = (TLRPC.TL_chatInviteExported) invites.invites.get(i);
fixDate(in);
this.invites.add(in);
}
}
for (int i = 0; i < invites.users.size(); i++) {
users.put(invites.users.get(i).id, invites.users.get(i));
}
int oldRowsCount = rowCount;
if (invites.invites.size() == 0) {
hasMore = false;
} else if (revoked) {
hasMore = this.revokedInvites.size() + 1 < invites.count;
} else {
hasMore = this.invites.size() + 1 < invites.count;
}
if (invites.invites.size() > 0 && isOpened) {
if (recyclerItemsEnterAnimator != null && !isPaused) {
recyclerItemsEnterAnimator.showItemsAnimated(oldRowsCount + 1);
}
} else {
updateByDiffUtils = true;
}
if (info != null && !revoked) {
info.invitesCount = invites.count;
getMessagesStorage().saveChatLinksCount(currentChatId, info.invitesCount);
}
} else {
hasMore = false;
}
boolean loadNext = false;
if (!hasMore && !loadRevoked && adminId == getAccountInstance().getUserConfig().clientUserId) {
hasMore = true;
loadAdmins = true;
loadNext = true;
} else if (!hasMore && !loadRevoked) {
hasMore = true;
loadRevoked = true;
loadNext = true;
}
if (!hasMore || (invites.size() + revokedInvites.size() + admins.size()) >= 5) {
resumeDelayedFragmentAnimation();
}
if (loadNext) {
loadLinks(false);
}
if (updateByDiffUtils && listViewAdapter != null && listView.getChildCount() > 0) {
updateRecyclerViewAnimated(callback);
} else {
updateRows(true);
}
}));
});
getConnectionsManager().bindRequestToGuid(reqId, getClassGuid());
}
if (notify) {
updateRows(true);
}
}
private void updateRows(boolean notify) {
currentChat = MessagesController.getInstance(currentAccount).getChat(currentChatId);
if (currentChat == null) {
return;
}
creatorRow = -1;
creatorDividerRow = -1;
linksStartRow = -1;
linksEndRow = -1;
linksLoadingRow = -1;
revokedLinksStartRow = -1;
revokedLinksEndRow = -1;
revokedHeader = -1;
revokedDivider = -1;
lastDivider = -1;
revokeAllRow = -1;
revokeAllDivider = -1;
createLinkHelpRow = -1;
helpRow = -1;
createNewLinkRow = -1;
adminsEndRow = -1;
adminsStartRow = -1;
adminsDividerRow = -1;
adminsHeaderRow = -1;
linksHeaderRow = -1;
dividerRow = -1;
rowCount = 0;
boolean otherAdmin = adminId != getAccountInstance().getUserConfig().clientUserId;
if (otherAdmin) {
creatorRow = rowCount++;
creatorDividerRow = rowCount++;
} else {
helpRow = rowCount++;
}
permanentLinkHeaderRow = rowCount++;
permanentLinkRow = rowCount++;
if (!otherAdmin) {
dividerRow = rowCount++;
createNewLinkRow = rowCount++;
} else if (!invites.isEmpty()) {
dividerRow = rowCount++;
linksHeaderRow = rowCount++;
}
if (!invites.isEmpty()) {
linksStartRow = rowCount;
rowCount += invites.size();
linksEndRow = rowCount;
}
if (!otherAdmin && invites.isEmpty() && createNewLinkRow >= 0 && (!linksLoading || loadAdmins || loadRevoked)) {
createLinkHelpRow = rowCount++;
}
if (!otherAdmin && admins.size() > 0) {
if ((!invites.isEmpty() || createNewLinkRow >= 0) && createLinkHelpRow == -1) {
adminsDividerRow = rowCount++;
}
adminsHeaderRow = rowCount++;
adminsStartRow = rowCount;
rowCount += admins.size();
adminsEndRow = rowCount;
}
if (!revokedInvites.isEmpty()) {
if (adminsStartRow >= 0) {
revokedDivider = rowCount++;
} else if ((!invites.isEmpty() || createNewLinkRow >= 0) && createLinkHelpRow == -1) {
revokedDivider = rowCount++;
} else if (otherAdmin && linksStartRow == -1) {
revokedDivider = rowCount++;
}
revokedHeader = rowCount++;
revokedLinksStartRow = rowCount;
rowCount += revokedInvites.size();
revokedLinksEndRow = rowCount;
revokeAllDivider = rowCount++;
revokeAllRow = rowCount++;
}
if (!loadAdmins && !loadRevoked && (linksLoading || hasMore) && !otherAdmin) {
linksLoadingRow = rowCount++;
}
if (!invites.isEmpty() || !revokedInvites.isEmpty()) {
lastDivider = rowCount++;
}
if (listViewAdapter != null && notify) {
listViewAdapter.notifyDataSetChanged();
}
}
@Override
public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("InviteLinks", R.string.InviteLinks));
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
@Override
public void onItemClick(int id) {
if (id == -1) {
finishFragment();
}
}
});
fragmentView = new FrameLayout(context) {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
AndroidUtilities.runOnUIThread(updateTimerRunnable, 500);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
AndroidUtilities.cancelRunOnUIThread(updateTimerRunnable);
}
};
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
fragmentView.setTag(Theme.key_windowBackgroundGray);
FrameLayout frameLayout = (FrameLayout) fragmentView;
listView = new RecyclerListView(context);
LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) {
@Override
public boolean supportsPredictiveItemAnimations() {
return false;
}
};
listView.setLayoutManager(layoutManager);
listView.setAdapter(listViewAdapter = new ListAdapter(context));
listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (hasMore && !linksLoading) {
int lastPosition = layoutManager.findLastVisibleItemPosition();
if (rowCount - lastPosition < 10) {
loadLinks(true);
}
}
}
});
recyclerItemsEnterAnimator = new RecyclerItemsEnterAnimator(listView, false);
DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator();
defaultItemAnimator.setDelayAnimations(false);
defaultItemAnimator.setSupportsChangeAnimations(false);
listView.setItemAnimator(defaultItemAnimator);
listView.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT);
frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
listView.setOnItemClickListener((view, position) -> {
if (position == creatorRow) {
TLRPC.User user = users.get(invite.admin_id);
if (user != null) {
Bundle bundle = new Bundle();
bundle.putLong("user_id", user.id);
MessagesController.getInstance(UserConfig.selectedAccount).putUser(user, false);
ProfileActivity profileActivity = new ProfileActivity(bundle);
presentFragment(profileActivity);
}
} else if (position == createNewLinkRow) {
LinkEditActivity linkEditActivity = new LinkEditActivity(LinkEditActivity.CREATE_TYPE, currentChatId);
linkEditActivity.setCallback(linkEditActivityCallback);
presentFragment(linkEditActivity);
} else if (position >= linksStartRow && position < linksEndRow) {
TLRPC.TL_chatInviteExported invite = invites.get(position - linksStartRow);
inviteLinkBottomSheet = new InviteLinkBottomSheet(context, invite, info, users, this, currentChatId, false, isChannel);
inviteLinkBottomSheet.setCanEdit(canEdit);
inviteLinkBottomSheet.show();
} else if (position >= revokedLinksStartRow && position < revokedLinksEndRow) {
TLRPC.TL_chatInviteExported invite = revokedInvites.get(position - revokedLinksStartRow);
inviteLinkBottomSheet = new InviteLinkBottomSheet(context, invite, info, users, this, currentChatId, false, isChannel);
inviteLinkBottomSheet.show();
} else if (position == revokeAllRow) {
if (deletingRevokedLinks) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("DeleteAllRevokedLinks", R.string.DeleteAllRevokedLinks));
builder.setMessage(LocaleController.getString("DeleteAllRevokedLinkHelp", R.string.DeleteAllRevokedLinkHelp));
builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface2, i2) -> {
TLRPC.TL_messages_deleteRevokedExportedChatInvites req = new TLRPC.TL_messages_deleteRevokedExportedChatInvites();
req.peer = getMessagesController().getInputPeer(-currentChatId);
if (adminId == getUserConfig().getClientUserId()) {
req.admin_id = getMessagesController().getInputUser(getUserConfig().getCurrentUser());
} else {
req.admin_id = getMessagesController().getInputUser(adminId);
}
deletingRevokedLinks = true;
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
deletingRevokedLinks = false;
if (error == null) {
DiffCallback callback = saveListState();
revokedInvites.clear();
updateRecyclerViewAnimated(callback);
}
}));
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
showDialog(builder.create());
} else if (position >= adminsStartRow && position < adminsEndRow) {
int p = position - adminsStartRow;
TLRPC.TL_chatAdminWithInvites admin = admins.get(p);
if (users.containsKey(admin.admin_id)) {
getMessagesController().putUser(users.get(admin.admin_id), false);
}
ManageLinksActivity fragment = new ManageLinksActivity(currentChatId, admin.admin_id, admin.invites_count);
fragment.setInfo(info, null);
presentFragment(fragment);
}
});
listView.setOnItemLongClickListener((view, position) -> {
if ((position >= linksStartRow && position < linksEndRow) || (position >= revokedLinksStartRow && position < revokedLinksEndRow)) {
LinkCell cell = (LinkCell) view;
cell.optionsView.callOnClick();
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
return true;
}
return false;
});
linkIcon = ContextCompat.getDrawable(context, R.drawable.msg_link_1);
linkIconRevoked = ContextCompat.getDrawable(context, R.drawable.msg_link_2);
linkIcon.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY));
updateRows(true);
timeDif = getConnectionsManager().getCurrentTime() - (System.currentTimeMillis() / 1000L);
return fragmentView;
}
public void setInfo(TLRPC.ChatFull chatFull, TLRPC.ExportedChatInvite invite) {
info = chatFull;
this.invite = (TLRPC.TL_chatInviteExported) invite;
isPublic = !TextUtils.isEmpty(currentChat.username);
loadLinks(true);
}
@Override
public void onResume() {
super.onResume();
if (listViewAdapter != null) {
listViewAdapter.notifyDataSetChanged();
}
}
@SuppressWarnings("FieldCanBeLocal")
public class HintInnerCell extends FrameLayout {
private EmptyView emptyView;
private TextView messageTextView;
public HintInnerCell(Context context) {
super(context);
emptyView = new EmptyView(context);
addView(emptyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 10, 0, 0));
messageTextView = new TextView(context);
messageTextView.setTextColor(Theme.getColor(Theme.key_chats_message));
messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
messageTextView.setGravity(Gravity.CENTER);
messageTextView.setText(isChannel ? LocaleController.getString("PrimaryLinkHelpChannel", R.string.PrimaryLinkHelpChannel) : LocaleController.getString("PrimaryLinkHelp", R.string.PrimaryLinkHelp));
addView(messageTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 52, 143, 52, 18));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), heightMeasureSpec);
}
}
private class ListAdapter extends RecyclerListView.SelectionAdapter {
private Context mContext;
public ListAdapter(Context context) {
mContext = context;
}
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
int position = holder.getAdapterPosition();
if (creatorRow == position) {
return true;
} else if (createNewLinkRow == position) {
return true;
} else if (position >= linksStartRow && position < linksEndRow) {
return true;
} else if (position >= revokedLinksStartRow && position < revokedLinksEndRow) {
return true;
} else if (position == revokeAllRow) {
return true;
} else if (position >= adminsStartRow && position < adminsEndRow) {
return true;
}
return false;
}
@Override
public int getItemCount() {
return rowCount;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case 0:
default:
view = new HintInnerCell(mContext);
view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundWhite));
break;
case 1:
view = new HeaderCell(mContext, 23);
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
break;
case 2:
LinkActionView linkActionView = new LinkActionView(mContext, ManageLinksActivity.this, null, currentChatId, true, isChannel);
linkActionView.setPermanent(true);
linkActionView.setDelegate(new LinkActionView.Delegate() {
@Override
public void revokeLink() {
revokePermanent();
}
@Override
public void showUsersForPermanentLink() {
inviteLinkBottomSheet = new InviteLinkBottomSheet(linkActionView.getContext(), invite, info, users, ManageLinksActivity.this, currentChatId, true, isChannel);
inviteLinkBottomSheet.show();
}
});
view = linkActionView;
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
break;
case 3:
view = new TextCell(mContext);
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
break;
case 4:
view = new ShadowSectionCell(mContext);
break;
case 5:
view = new LinkCell(mContext);
break;
case 6:
FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext);
flickerLoadingView.setIsSingleCell(true);
flickerLoadingView.setViewType(FlickerLoadingView.INVITE_LINKS_TYPE);
flickerLoadingView.showDate(false);
view = flickerLoadingView;
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
break;
case 7:
view = new ShadowSectionCell(mContext);
view.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
break;
case 8:
TextSettingsCell revokeAll = new TextSettingsCell(mContext);
revokeAll.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
revokeAll.setText(LocaleController.getString("DeleteAllRevokedLinks", R.string.DeleteAllRevokedLinks), false);
revokeAll.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText5));
view = revokeAll;
break;
case 9:
TextInfoPrivacyCell cell = new TextInfoPrivacyCell(mContext);
cell.setText(LocaleController.getString("CreateNewLinkHelp", R.string.CreateNewLinkHelp));
cell.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
view = cell;
break;
case 10:
ManageChatUserCell userCell = new ManageChatUserCell(mContext, 8, 6, false);
userCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
view = userCell;
break;
}
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new RecyclerListView.Holder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 2:
LinkActionView linkActionView = (LinkActionView) holder.itemView;
linkActionView.setCanEdit(adminId == getAccountInstance().getUserConfig().clientUserId);
if (isPublic && adminId == getAccountInstance().getUserConfig().clientUserId) {
if (info != null) {
linkActionView.setLink("https://t.me/" + currentChat.username);
linkActionView.setUsers(0, null);
linkActionView.hideRevokeOption(true);
}
} else {
linkActionView.hideRevokeOption(!canEdit);
if (invite != null) {
TLRPC.TL_chatInviteExported inviteExported = invite;
linkActionView.setLink(inviteExported.link);
linkActionView.loadUsers(inviteExported, currentChatId);
} else {
linkActionView.setLink(null);
linkActionView.loadUsers(null, currentChatId);
}
}
break;
case 1:
HeaderCell headerCell = (HeaderCell) holder.itemView;
if (position == permanentLinkHeaderRow) {
if (isPublic && adminId == getAccountInstance().getUserConfig().clientUserId) {
headerCell.setText(LocaleController.getString("PublicLink", R.string.PublicLink));
} else if (adminId == getAccountInstance().getUserConfig().clientUserId) {
headerCell.setText(LocaleController.getString("ChannelInviteLinkTitle", R.string.ChannelInviteLinkTitle));
} else {
headerCell.setText(LocaleController.getString("PermanentLinkForThisAdmin", R.string.PermanentLinkForThisAdmin));
}
} else if (position == revokedHeader) {
headerCell.setText(LocaleController.getString("RevokedLinks", R.string.RevokedLinks));
} else if (position == linksHeaderRow) {
headerCell.setText(LocaleController.getString("LinksCreatedByThisAdmin", R.string.LinksCreatedByThisAdmin));
} else if (position == adminsHeaderRow) {
headerCell.setText(LocaleController.getString("LinksCreatedByOtherAdmins", R.string.LinksCreatedByOtherAdmins));
}
break;
case 3:
TextCell textCell = (TextCell) holder.itemView;
Drawable drawable1 = mContext.getResources().getDrawable(R.drawable.poll_add_circle);
Drawable drawable2 = mContext.getResources().getDrawable(R.drawable.poll_add_plus);
drawable1.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_switchTrackChecked), PorterDuff.Mode.MULTIPLY));
drawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_checkboxCheck), PorterDuff.Mode.MULTIPLY));
CombinedDrawable combinedDrawable = new CombinedDrawable(drawable1, drawable2);
textCell.setTextAndIcon(LocaleController.getString("CreateNewLink", R.string.CreateNewLink), combinedDrawable, !invites.isEmpty());
break;
case 5:
TLRPC.TL_chatInviteExported invite;
boolean drawDivider = true;
if (position >= linksStartRow && position < linksEndRow) {
invite = invites.get(position - linksStartRow);
if (position == linksEndRow - 1) {
drawDivider = false;
}
} else {
invite = revokedInvites.get(position - revokedLinksStartRow);
if (position == revokedLinksEndRow - 1) {
drawDivider = false;
}
}
LinkCell cell = (LinkCell) holder.itemView;
cell.setLink(invite, position - linksStartRow);
cell.drawDivider = drawDivider;
break;
case 10:
ManageChatUserCell userCell = (ManageChatUserCell) holder.itemView;
TLRPC.User user;
int count;
drawDivider = true;
if (position == creatorRow) {
user = getMessagesController().getUser(adminId);
count = invitesCount;
drawDivider = false;
} else {
int p = position - adminsStartRow;
TLRPC.TL_chatAdminWithInvites admin = admins.get(p);
user = users.get(admin.admin_id);
count = admin.invites_count;
if (position == adminsEndRow - 1) {
drawDivider = false;
}
}
if (user != null) {
userCell.setData(user, ContactsController.formatName(user.first_name, user.last_name), LocaleController.formatPluralString("InviteLinkCount", count), drawDivider);
}
}
}
@Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
if (holder.itemView instanceof ManageChatUserCell) {
((ManageChatUserCell) holder.itemView).recycle();
}
}
@Override
public int getItemViewType(int position) {
if (position == helpRow) {
return 0;
} else if (position == permanentLinkHeaderRow || position == revokedHeader || position == adminsHeaderRow || position == linksHeaderRow) {
return 1;
} else if (position == permanentLinkRow) {
return 2;
} else if (position == createNewLinkRow) {
return 3;
} else if (position == dividerRow || position == revokedDivider || position == revokeAllDivider || position == creatorDividerRow || position == adminsDividerRow) {
return 4;
} else if ((position >= linksStartRow && position < linksEndRow) || (position >= revokedLinksStartRow && position < revokedLinksEndRow)) {
return 5;
} else if (position == linksLoadingRow) {
return 6;
} else if (position == lastDivider) {
return 7;
} else if (position == revokeAllRow) {
return 8;
} else if (position == createLinkHelpRow) {
return 9;
} else if (position == creatorRow || (position >= adminsStartRow && position < adminsEndRow)) {
return 10;
}
return 1;
}
}
private void revokePermanent() {
if (adminId == getAccountInstance().getUserConfig().clientUserId) {
TLRPC.TL_messages_exportChatInvite req = new TLRPC.TL_messages_exportChatInvite();
req.peer = getMessagesController().getInputPeer(-currentChatId);
req.legacy_revoke_permanent = true;
TLRPC.TL_chatInviteExported oldInvite = invite;
invite = null;
info.exported_invite = null;
final int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (error == null) {
invite = (TLRPC.TL_chatInviteExported) response;
if (info != null) {
info.exported_invite = invite;
}
if (getParentActivity() == null) {
return;
}
oldInvite.revoked = true;
DiffCallback callback = saveListState();
revokedInvites.add(0, oldInvite);
updateRecyclerViewAnimated(callback);
BulletinFactory.of(this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString("InviteRevokedHint", R.string.InviteRevokedHint)).show();
}
}));
AndroidUtilities.updateVisibleRows(listView);
getConnectionsManager().bindRequestToGuid(reqId, classGuid);
} else {
revokeLink(invite);
}
}
public static class TextCell extends FrameLayout {
private SimpleTextView textView;
private ImageView imageView;
boolean divider;
public TextCell(Context context) {
super(context);
textView = new SimpleTextView(context);
textView.setTextSize(16);
textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2));
textView.setTag(Theme.key_windowBackgroundWhiteBlueText2);
addView(textView);
imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER);
addView(imageView);
setWillNotDraw(false);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = AndroidUtilities.dp(48);
textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + 23), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY));
imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY));
setMeasuredDimension(width, AndroidUtilities.dp(50));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int height = bottom - top;
int width = right - left;
int viewLeft;
int viewTop = (height - textView.getTextHeight()) / 2;
if (LocaleController.isRTL) {
viewLeft = getMeasuredWidth() - textView.getMeasuredWidth() - AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? 70 : 25);
} else {
viewLeft = AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? 70 : 25);
}
textView.layout(viewLeft, viewTop, viewLeft + textView.getMeasuredWidth(), viewTop + textView.getMeasuredHeight());
viewLeft = !LocaleController.isRTL ? (AndroidUtilities.dp(70) - imageView.getMeasuredWidth()) / 2 : width - imageView.getMeasuredWidth() - AndroidUtilities.dp(25);
imageView.layout(viewLeft, 0, viewLeft + imageView.getMeasuredWidth(), imageView.getMeasuredHeight());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (divider) {
canvas.drawLine(AndroidUtilities.dp(70), getMeasuredHeight() - 1, getMeasuredWidth() + AndroidUtilities.dp(23), getMeasuredHeight(), Theme.dividerPaint);
}
}
public void setTextAndIcon(String text, Drawable icon, boolean divider) {
textView.setText(text);
imageView.setImageDrawable(icon);
this.divider = divider;
}
}
private class LinkCell extends FrameLayout {
private final static int LINK_STATE_BLUE = 0;
private final static int LINK_STATE_GREEN = 1;
private final static int LINK_STATE_YELLOW = 2;
private final static int LINK_STATE_RED = 3;
private final static int LINK_STATE_GRAY = 4;
int lastDrawingState;
TextView titleView;
TextView subtitleView;
TLRPC.TL_chatInviteExported invite;
int position;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
RectF rectF = new RectF();
ImageView optionsView;
int animateFromState;
float animateToStateProgress = 1f;
float lastDrawExpringProgress;
boolean animateHideExpiring;
boolean drawDivider;
public LinkCell(@NonNull Context context) {
super(context);
paint2.setStyle(Paint.Style.STROKE);
paint2.setStrokeCap(Paint.Cap.ROUND);
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 70, 0, 30, 0));
titleView = new TextView(context);
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
titleView.setLines(1);
titleView.setEllipsize(TextUtils.TruncateAt.END);
subtitleView = new TextView(context);
subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
subtitleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText));
linearLayout.addView(titleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
linearLayout.addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 6, 0, 0));
optionsView = new ImageView(context);
optionsView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_ab_other));
optionsView.setScaleType(ImageView.ScaleType.CENTER);
optionsView.setColorFilter(Theme.getColor(Theme.key_stickers_menu));
optionsView.setOnClickListener(view -> {
if (invite == null) {
return;
}
ArrayList<String> items = new ArrayList<>();
ArrayList<Integer> icons = new ArrayList<>();
final ArrayList<Integer> actions = new ArrayList<>();
boolean redLastItem = false;
if (invite.revoked) {
items.add(LocaleController.getString("Delete", R.string.Delete));
icons.add(R.drawable.msg_delete);
actions.add(4);
redLastItem = true;
} else {
items.add(LocaleController.getString("CopyLink", R.string.CopyLink));
icons.add(R.drawable.msg_copy);
actions.add(0);
items.add(LocaleController.getString("ShareLink", R.string.ShareLink));
icons.add(R.drawable.msg_share);
actions.add(1);
if (!invite.permanent && canEdit) {
items.add(LocaleController.getString("EditLink", R.string.EditLink));
icons.add(R.drawable.msg_edit);
actions.add(2);
}
if (canEdit) {
items.add(LocaleController.getString("RevokeLink", R.string.RevokeLink));
icons.add(R.drawable.msg_delete);
actions.add(3);
redLastItem = true;
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setItems(items.toArray(new CharSequence[0]), AndroidUtilities.toIntArray(icons), (dialogInterface, i) -> {
switch (actions.get(i)) {
case 0:
try {
if (invite.link == null) {
return;
}
android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE);
android.content.ClipData clip = android.content.ClipData.newPlainText("label", invite.link);
clipboard.setPrimaryClip(clip);
BulletinFactory.createCopyLinkBulletin(ManageLinksActivity.this).show();
} catch (Exception e) {
FileLog.e(e);
}
break;
case 1:
try {
if (invite.link == null) {
return;
}
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, invite.link);
startActivityForResult(Intent.createChooser(intent, LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink)), 500);
} catch (Exception e) {
FileLog.e(e);
}
break;
case 2:
editLink(invite);
break;
case 3:
TLRPC.TL_chatInviteExported inviteFinal = invite;
AlertDialog.Builder builder2 = new AlertDialog.Builder(getParentActivity());
builder2.setMessage(LocaleController.getString("RevokeAlert", R.string.RevokeAlert));
builder2.setTitle(LocaleController.getString("RevokeLink", R.string.RevokeLink));
builder2.setPositiveButton(LocaleController.getString("RevokeButton", R.string.RevokeButton), (dialogInterface2, i2) -> revokeLink(inviteFinal));
builder2.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
showDialog(builder2.create());
break;
case 4:
inviteFinal = invite;
builder2 = new AlertDialog.Builder(getParentActivity());
builder2.setTitle(LocaleController.getString("DeleteLink", R.string.DeleteLink));
builder2.setMessage(LocaleController.getString("DeleteLinkHelp", R.string.DeleteLinkHelp));
builder2.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface2, i2) -> deleteLink(inviteFinal));
builder2.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
showDialog(builder2.create());
break;
}
});
builder.setTitle(LocaleController.getString("InviteLink", R.string.InviteLink));
AlertDialog alert = builder.create();
builder.show();
if (redLastItem) {
alert.setItemColor(items.size() - 1, Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogRedIcon));
}
});
optionsView.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 1));
addView(optionsView, LayoutHelper.createFrame(40, 48, Gravity.RIGHT | Gravity.CENTER_VERTICAL));
setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
setWillNotDraw(false);
}
boolean timerRunning;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64), MeasureSpec.EXACTLY));
paint2.setStrokeWidth(AndroidUtilities.dp(2));
}
private TimerParticles timerParticles = new TimerParticles();
@Override
protected void onDraw(Canvas canvas) {
if (invite == null) {
return;
}
int cX = AndroidUtilities.dp(36);
int cY = getMeasuredHeight() / 2;
int drawState;
float progress = 0;
float timeProgress = 1f;
if (invite.expired || invite.revoked) {
drawState = invite.revoked ? LINK_STATE_GRAY : LINK_STATE_RED;
} else if (invite.expire_date > 0 || invite.usage_limit > 0) {
float usageProgress = 1f;
if (invite.expire_date > 0) {
long currentTime = System.currentTimeMillis() + timeDif * 1000L;
long expireTime = invite.expire_date * 1000L;
long date = (invite.start_date <= 0 ? invite.date : invite.start_date) * 1000L;
long from = currentTime - date;
long to = expireTime - date;
timeProgress = (1f - from / (float) to);
}
if (invite.usage_limit > 0) {
usageProgress = (invite.usage_limit - invite.usage) / (float) invite.usage_limit;
}
progress = Math.min(timeProgress, usageProgress);
if (progress <= 0) {
invite.expired = true;
drawState = LINK_STATE_RED;
AndroidUtilities.updateVisibleRows(listView);
} else {
drawState = LINK_STATE_GREEN;
}
} else {
drawState = LINK_STATE_BLUE;
}
if (drawState != lastDrawingState && lastDrawingState >= 0) {
animateFromState = lastDrawingState;
animateToStateProgress = 0f;
if (hasProgress(animateFromState) && !hasProgress(drawState)) {
animateHideExpiring = true;
} else {
animateHideExpiring = false;
}
}
lastDrawingState = drawState;
if (animateToStateProgress != 1f) {
animateToStateProgress += 16f / 250f;
if (animateToStateProgress >= 1f) {
animateToStateProgress = 1f;
animateHideExpiring = false;
} else {
invalidate();
}
}
int color;
if (animateToStateProgress != 1f) {
color = ColorUtils.blendARGB(getColor(animateFromState, progress), getColor(drawState, progress), animateToStateProgress);
} else {
color = getColor(drawState, progress);
}
paint.setColor(color);
canvas.drawCircle(cX, cY, AndroidUtilities.dp(32) / 2f, paint);
if (animateHideExpiring || (!invite.expired && invite.expire_date > 0 && !invite.revoked)) {
if (animateHideExpiring) {
timeProgress = lastDrawExpringProgress;
}
paint2.setColor(color);
rectF.set(cX - AndroidUtilities.dp(20), cY - AndroidUtilities.dp(20), cX + AndroidUtilities.dp(20), cY + AndroidUtilities.dp(20));
if (animateToStateProgress != 1f && (!hasProgress(animateFromState) || animateHideExpiring)) {
canvas.save();
float a = (animateHideExpiring ? (1f - animateToStateProgress) : animateToStateProgress);
float s = (float) (0.7 + 0.3f * a);
canvas.scale(s, s, rectF.centerX(), rectF.centerY());
canvas.drawArc(rectF, -90, -timeProgress * 360, false, paint2);
timerParticles.draw(canvas, paint2, rectF, -timeProgress * 360, a);
canvas.restore();
} else {
canvas.drawArc(rectF, -90, -timeProgress * 360, false, paint2);
timerParticles.draw(canvas, paint2, rectF, -timeProgress * 360, 1f);
}
if (!isPaused) {
invalidate();
}
lastDrawExpringProgress = timeProgress;
}
if (invite.revoked) {
linkIconRevoked.setBounds(cX - AndroidUtilities.dp(12), cY - AndroidUtilities.dp(12), cX + AndroidUtilities.dp(12), cY + AndroidUtilities.dp(12));
linkIconRevoked.draw(canvas);
} else {
linkIcon.setBounds(cX - AndroidUtilities.dp(12), cY - AndroidUtilities.dp(12), cX + AndroidUtilities.dp(12), cY + AndroidUtilities.dp(12));
linkIcon.draw(canvas);
}
if (drawDivider) {
canvas.drawLine(AndroidUtilities.dp(70), getMeasuredHeight() - 1, getMeasuredWidth() + AndroidUtilities.dp(23), getMeasuredHeight(), Theme.dividerPaint);
}
}
private boolean hasProgress(int state) {
return state == LINK_STATE_YELLOW || state == LINK_STATE_GREEN;
}
private int getColor(int state, float progress) {
if (state == LINK_STATE_RED) {
return Theme.getColor(Theme.key_chat_attachAudioBackground);
} else if (state == LINK_STATE_GREEN) {
if (progress > 0.5f) {
float p = (progress - 0.5f) / 0.5f;
return ColorUtils.blendARGB(Theme.getColor(Theme.key_chat_attachLocationBackground), Theme.getColor(Theme.key_chat_attachPollBackground), (1f - p));
} else {
float p = progress / 0.5f;
return ColorUtils.blendARGB(Theme.getColor(Theme.key_chat_attachPollBackground), Theme.getColor(Theme.key_chat_attachAudioBackground), (1f - p));
}
} else if (state == LINK_STATE_YELLOW) {
return Theme.getColor(Theme.key_chat_attachPollBackground);
} else if (state == LINK_STATE_GRAY) {
return Theme.getColor(Theme.key_chats_unreadCounterMuted);
} else {
return Theme.getColor(Theme.key_featuredStickers_addButton);
}
}
public void setLink(TLRPC.TL_chatInviteExported invite, int position) {
timerRunning = false;
if (this.invite == null || invite == null || !this.invite.link.equals(invite.link)) {
lastDrawingState = -1;
animateToStateProgress = 1f;
}
this.invite = invite;
this.position = position;
if (invite == null) {
return;
}
if (!TextUtils.isEmpty(invite.title)) {
SpannableStringBuilder builder = new SpannableStringBuilder(invite.title);
Emoji.replaceEmoji(builder, titleView.getPaint().getFontMetricsInt(), (int) titleView.getPaint().getTextSize(), false);
titleView.setText(builder);
} else if (invite.link.startsWith("https://t.me/+")) {
titleView.setText(invite.link.substring("https://t.me/+".length()));
} else if (invite.link.startsWith("https://t.me/joinchat/")) {
titleView.setText(invite.link.substring("https://t.me/joinchat/".length()));
} else if (invite.link.startsWith("https://")) {
titleView.setText(invite.link.substring("https://".length()));
} else {
titleView.setText(invite.link);
}
String joinedString = "";
if (invite.usage == 0 && invite.usage_limit == 0 && invite.requested == 0) {
joinedString = LocaleController.getString("NoOneJoinedYet", R.string.NoOneJoinedYet);
} else {
if (invite.usage_limit > 0 && invite.usage == 0 && !invite.expired && !invite.revoked) {
joinedString = LocaleController.formatPluralString("CanJoin", invite.usage_limit);
} else if (invite.usage_limit > 0 && invite.expired && invite.revoked) {
joinedString = LocaleController.formatPluralString("PeopleJoined", invite.usage) + ", " + LocaleController.formatPluralString("PeopleJoinedRemaining", (invite.usage_limit - invite.usage));
} else {
if (invite.usage > 0) {
joinedString = LocaleController.formatPluralString("PeopleJoined", invite.usage);
}
if (invite.requested > 0) {
if (invite.usage > 0) {
joinedString = joinedString + ", ";
}
joinedString = joinedString + LocaleController.formatPluralString("JoinRequests", invite.requested);
}
}
}
if (invite.permanent && !invite.revoked) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(joinedString);
DotDividerSpan dotDividerSpan = new DotDividerSpan();
dotDividerSpan.setTopPadding(AndroidUtilities.dp(1.5f));
spannableStringBuilder.append(" . ").setSpan(dotDividerSpan, spannableStringBuilder.length() - 3, spannableStringBuilder.length() - 2, 0);
spannableStringBuilder.append(LocaleController.getString("Permanent", R.string.Permanent));
subtitleView.setText(spannableStringBuilder);
} else if (invite.expired || invite.revoked) {
if (invite.revoked && invite.usage == 0) {
joinedString = LocaleController.getString("NoOneJoined", R.string.NoOneJoined);
}
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(joinedString);
DotDividerSpan dotDividerSpan = new DotDividerSpan();
dotDividerSpan.setTopPadding(AndroidUtilities.dp(1.5f));
spannableStringBuilder.append(" . ").setSpan(dotDividerSpan, spannableStringBuilder.length() - 3, spannableStringBuilder.length() - 2, 0);
if (!invite.revoked && invite.usage_limit > 0 && invite.usage >= invite.usage_limit) {
spannableStringBuilder.append(LocaleController.getString("LinkLimitReached", R.string.LinkLimitReached));
} else {
spannableStringBuilder.append(invite.revoked ? LocaleController.getString("Revoked", R.string.Revoked) : LocaleController.getString("Expired", R.string.Expired));
}
subtitleView.setText(spannableStringBuilder);
} else if (invite.expire_date > 0) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(joinedString);
DotDividerSpan dotDividerSpan = new DotDividerSpan();
dotDividerSpan.setTopPadding(AndroidUtilities.dp(1.5f));
spannableStringBuilder.append(" . ").setSpan(dotDividerSpan, spannableStringBuilder.length() - 3, spannableStringBuilder.length() - 2, 0);
long currentTime = System.currentTimeMillis() + timeDif * 1000L;
long expireTime = invite.expire_date * 1000L;
long timeLeft = expireTime - currentTime;
if (timeLeft < 0) {
timeLeft = 0;
}
if (timeLeft > 86400000L) {
spannableStringBuilder.append(LocaleController.formatPluralString("DaysLeft", (int) (timeLeft / 86400000L)));
} else {
int s = (int) ((timeLeft / 1000) % 60);
int m = (int) ((timeLeft / 1000 / 60) % 60);
int h = (int) ((timeLeft / 1000 / 60 / 60));
spannableStringBuilder.append(String.format(Locale.ENGLISH, "%02d", h)).append(String.format(Locale.ENGLISH, ":%02d", m)).append(String.format(Locale.ENGLISH, ":%02d", s));
timerRunning = true;
}
subtitleView.setText(spannableStringBuilder);
} else {
subtitleView.setText(joinedString);
}
}
}
public void deleteLink(TLRPC.TL_chatInviteExported invite) {
TLRPC.TL_messages_deleteExportedChatInvite req = new TLRPC.TL_messages_deleteExportedChatInvite();
req.link = invite.link;
req.peer = getMessagesController().getInputPeer(-currentChatId);
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (error == null) {
linkEditActivityCallback.onLinkRemoved(invite);
}
}));
}
public void editLink(TLRPC.TL_chatInviteExported invite) {
LinkEditActivity activity = new LinkEditActivity(LinkEditActivity.EDIT_TYPE, currentChatId);
activity.setCallback(linkEditActivityCallback);
activity.setInviteToEdit(invite);
presentFragment(activity);
}
public void revokeLink(TLRPC.TL_chatInviteExported invite) {
TLRPC.TL_messages_editExportedChatInvite req = new TLRPC.TL_messages_editExportedChatInvite();
req.link = invite.link;
req.revoked = true;
req.peer = getMessagesController().getInputPeer(-currentChatId);
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (error == null) {
if (response instanceof TLRPC.TL_messages_exportedChatInviteReplaced) {
TLRPC.TL_messages_exportedChatInviteReplaced replaced = (TLRPC.TL_messages_exportedChatInviteReplaced) response;
if (!isPublic) {
ManageLinksActivity.this.invite = (TLRPC.TL_chatInviteExported) replaced.new_invite;
}
invite.revoked = true;
DiffCallback callback = saveListState();
if (isPublic && adminId == getAccountInstance().getUserConfig().getClientUserId()) {
invites.remove(invite);
invites.add(0, (TLRPC.TL_chatInviteExported) replaced.new_invite);
} else if (this.invite != null) {
this.invite = (TLRPC.TL_chatInviteExported) replaced.new_invite;
}
revokedInvites.add(0, invite);
updateRecyclerViewAnimated(callback);
} else {
linkEditActivityCallback.onLinkEdited(invite, response);
if (info != null) {
info.invitesCount--;
if (info.invitesCount < 0) {
info.invitesCount = 0;
}
getMessagesStorage().saveChatLinksCount(currentChatId, info.invitesCount);
}
}
if (getParentActivity() != null) {
BulletinFactory.of(this).createSimpleBulletin(R.raw.linkbroken, LocaleController.getString("InviteRevokedHint", R.string.InviteRevokedHint)).show();
}
}
}));
}
private final LinkEditActivity.Callback linkEditActivityCallback = new LinkEditActivity.Callback() {
@Override
public void onLinkCreated(TLObject response) {
if (response instanceof TLRPC.TL_chatInviteExported) {
AndroidUtilities.runOnUIThread(() -> {
DiffCallback callback = saveListState();
invites.add(0, (TLRPC.TL_chatInviteExported) response);
if (info != null) {
info.invitesCount++;
getMessagesStorage().saveChatLinksCount(currentChatId, info.invitesCount);
}
updateRecyclerViewAnimated(callback);
}, 200);
}
}
@Override
public void onLinkEdited(TLRPC.TL_chatInviteExported inviteToEdit, TLObject response) {
if (response instanceof TLRPC.TL_messages_exportedChatInvite) {
TLRPC.TL_chatInviteExported edited = (TLRPC.TL_chatInviteExported) ((TLRPC.TL_messages_exportedChatInvite) response).invite;
fixDate(edited);
for (int i = 0; i < invites.size(); i++) {
if (invites.get(i).link.equals(inviteToEdit.link)) {
if (edited.revoked) {
DiffCallback callback = saveListState();
invites.remove(i);
revokedInvites.add(0, edited);
updateRecyclerViewAnimated(callback);
} else {
invites.set(i, edited);
updateRows(true);
}
return;
}
}
}
}
@Override
public void onLinkRemoved(TLRPC.TL_chatInviteExported removedInvite) {
for (int i = 0; i < revokedInvites.size(); i++) {
if (revokedInvites.get(i).link.equals(removedInvite.link)) {
DiffCallback callback = saveListState();
revokedInvites.remove(i);
updateRecyclerViewAnimated(callback);
return;
}
}
}
@Override
public void revokeLink(TLRPC.TL_chatInviteExported inviteFinal) {
ManageLinksActivity.this.revokeLink(inviteFinal);
}
};
private void updateRecyclerViewAnimated(DiffCallback callback) {
if (isPaused || listViewAdapter == null || listView == null) {
updateRows(true);
return;
}
updateRows(false);
callback.fillPositions(callback.newPositionToItem);
DiffUtil.calculateDiff(callback).dispatchUpdatesTo(listViewAdapter);
AndroidUtilities.updateVisibleRows(listView);
}
private class DiffCallback extends DiffUtil.Callback {
int oldRowCount;
int oldLinksStartRow;
int oldLinksEndRow;
int oldRevokedLinksStartRow;
int oldRevokedLinksEndRow;
int oldAdminsStartRow;
int oldAdminsEndRow;
SparseIntArray oldPositionToItem = new SparseIntArray();
SparseIntArray newPositionToItem = new SparseIntArray();
ArrayList<TLRPC.TL_chatInviteExported> oldLinks = new ArrayList<>();
ArrayList<TLRPC.TL_chatInviteExported> oldRevokedLinks = new ArrayList<>();
@Override
public int getOldListSize() {
return oldRowCount;
}
@Override
public int getNewListSize() {
return rowCount;
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
if (oldItemPosition >= oldLinksStartRow && oldItemPosition < oldLinksEndRow || oldItemPosition >= oldRevokedLinksStartRow && oldItemPosition < oldRevokedLinksEndRow) {
if (newItemPosition >= linksStartRow && newItemPosition < linksEndRow || newItemPosition >= revokedLinksStartRow && newItemPosition < revokedLinksEndRow) {
TLRPC.TL_chatInviteExported newItem;
TLRPC.TL_chatInviteExported oldItem;
if (newItemPosition >= linksStartRow && newItemPosition < linksEndRow) {
newItem = invites.get(newItemPosition - linksStartRow);
} else {
newItem = revokedInvites.get(newItemPosition - revokedLinksStartRow);
}
if (oldItemPosition >= oldLinksStartRow && oldItemPosition < oldLinksEndRow) {
oldItem = oldLinks.get(oldItemPosition - oldLinksStartRow);
} else {
oldItem = oldRevokedLinks.get(oldItemPosition - oldRevokedLinksStartRow);
}
return oldItem.link.equals(newItem.link);
}
}
if (oldItemPosition >= oldAdminsStartRow && oldItemPosition < oldAdminsEndRow && newItemPosition >= adminsStartRow && newItemPosition < adminsEndRow) {
return (oldItemPosition - oldAdminsStartRow) == (newItemPosition - adminsStartRow);
}
int oldItem = oldPositionToItem.get(oldItemPosition, -1);
int newItem = newPositionToItem.get(newItemPosition, -1);
return oldItem >= 0 && oldItem == newItem;
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return areItemsTheSame(oldItemPosition, newItemPosition);
}
public void fillPositions(SparseIntArray sparseIntArray) {
sparseIntArray.clear();
int pointer = 0;
put(++pointer, helpRow, sparseIntArray);
put(++pointer, permanentLinkHeaderRow, sparseIntArray);
put(++pointer, permanentLinkRow, sparseIntArray);
put(++pointer, dividerRow, sparseIntArray);
put(++pointer, createNewLinkRow, sparseIntArray);
put(++pointer, revokedHeader, sparseIntArray);
put(++pointer, revokeAllRow, sparseIntArray);
put(++pointer, createLinkHelpRow, sparseIntArray);
put(++pointer, creatorRow, sparseIntArray);
put(++pointer, creatorDividerRow, sparseIntArray);
put(++pointer, adminsHeaderRow, sparseIntArray);
put(++pointer, linksHeaderRow, sparseIntArray);
put(++pointer, linksLoadingRow, sparseIntArray);
}
private void put(int id, int position, SparseIntArray sparseIntArray) {
if (position >= 0) {
sparseIntArray.put(position, id);
}
}
}
private DiffCallback saveListState() {
DiffCallback callback = new DiffCallback();
callback.fillPositions(callback.oldPositionToItem);
callback.oldLinksStartRow = linksStartRow;
callback.oldLinksEndRow = linksEndRow;
callback.oldRevokedLinksStartRow = revokedLinksStartRow;
callback.oldRevokedLinksEndRow = revokedLinksEndRow;
callback.oldAdminsStartRow = adminsStartRow;
callback.oldAdminsEndRow = adminsEndRow;
callback.oldRowCount = rowCount;
callback.oldLinks.clear();
callback.oldLinks.addAll(invites);
callback.oldRevokedLinks.clear();
callback.oldRevokedLinks.addAll(revokedInvites);
return callback;
}
public void fixDate(TLRPC.TL_chatInviteExported edited) {
if (edited.expire_date > 0) {
edited.expired = getConnectionsManager().getCurrentTime() >= edited.expire_date;
} else if (edited.usage_limit > 0) {
edited.expired = edited.usage >= edited.usage_limit;
}
}
@Override
public ArrayList<ThemeDescription> getThemeDescriptions() {
ArrayList<ThemeDescription> themeDescriptions = new ArrayList<>();
ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> {
if (listView != null) {
int count = listView.getChildCount();
for (int a = 0; a < count; a++) {
View child = listView.getChildAt(a);
if (child instanceof ManageChatUserCell) {
((ManageChatUserCell) child).update(0);
}
if (child instanceof LinkActionView) {
((LinkActionView) child).updateColors();
}
}
}
if (inviteLinkBottomSheet != null) {
inviteLinkBottomSheet.updateColors();
}
};
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{HeaderCell.class, TextCell.class, LinkActionView.class, LinkCell.class}, null, null, null, Theme.key_windowBackgroundWhite));
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_windowBackgroundGray));
themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_windowBackgroundWhite));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle));
themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteGrayText));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, new String[]{"statusOnlineColor"}, null, null, cellDelegate, Theme.key_windowBackgroundWhiteBlueText));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ManageChatUserCell.class}, null, Theme.avatarDrawables, null, Theme.key_avatar_text));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundOrange));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundViolet));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundGreen));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundCyan));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue));
themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{HintInnerCell.class}, new String[]{"messageTextView"}, null, null, null, Theme.key_chats_message));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CHECKTAG, new Class[]{ManageChatTextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CHECKTAG, new Class[]{ManageChatTextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_chats_unreadCounterMuted));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CHECKTAG, new Class[]{ManageChatTextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueButton));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CHECKTAG, new Class[]{ManageChatTextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueIcon));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueText2));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_switchTrackChecked));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_checkboxCheck));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{HeaderCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlueHeader));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{LinkCell.class}, new String[]{"titleView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{LinkCell.class}, new String[]{"subtitleView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText));
themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{LinkCell.class}, new String[]{"optionsView"}, null, null, null, Theme.key_stickers_menu));
return themeDescriptions;
}
@Override
public boolean needDelayOpenAnimation() {
return true;
}
int animationIndex = -1;
@Override
protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
super.onTransitionAnimationEnd(isOpen, backward);
if (isOpen) {
isOpened = true;
if (backward && inviteLinkBottomSheet != null && inviteLinkBottomSheet.isNeedReopen) {
inviteLinkBottomSheet.show();
}
}
NotificationCenter.getInstance(currentAccount).onAnimationFinish(animationIndex);
}
@Override
protected void onTransitionAnimationStart(boolean isOpen, boolean backward) {
super.onTransitionAnimationStart(isOpen, backward);
animationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(animationIndex, null);
}
}