/* * This is the source code of Telegram for Android v. 2.0.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; import android.app.Activity; import android.content.Context; import android.view.Gravity; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.PhotoPickerAlbumsCell; import org.telegram.ui.Cells.PhotoPickerSearchCell; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PickerBottomLayout; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.HashMap; public class PhotoAlbumPickerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public interface PhotoAlbumPickerActivityDelegate { void didSelectPhotos(ArrayList photos); void startPhotoSelectActivity(); } private HashMap selectedPhotos = new HashMap<>(); private ArrayList selectedPhotosOrder = new ArrayList<>(); private ArrayList albumsSorted = null; private HashMap recentImagesWebKeys = new HashMap<>(); private HashMap recentImagesGifKeys = new HashMap<>(); private ArrayList recentWebImages = new ArrayList<>(); private ArrayList recentGifImages = new ArrayList<>(); private boolean loading = false; private int columnsCount = 2; private RecyclerListView listView; private ListAdapter listAdapter; private FrameLayout progressView; private TextView emptyView; private PickerBottomLayout pickerBottomLayout; private boolean sendPressed; private int selectPhotoType; private boolean allowSearchImages = true; private boolean allowGifs; private boolean allowCaption; private ChatActivity chatActivity; private int maxSelectedPhotos; private PhotoAlbumPickerActivityDelegate delegate; public PhotoAlbumPickerActivity(int selectPhotoType, boolean allowGifs, boolean allowCaption, ChatActivity chatActivity) { super(); this.chatActivity = chatActivity; this.selectPhotoType = selectPhotoType; this.allowGifs = allowGifs; this.allowCaption = allowCaption; } @Override public boolean onFragmentCreate() { loading = true; MediaController.loadGalleryPhotosAlbums(classGuid); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.albumsDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentImagesDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.closeChats); return super.onFragmentCreate(); } @Override public void onFragmentDestroy() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.albumsDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentImagesDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.closeChats); super.onFragmentDestroy(); } @SuppressWarnings("unchecked") @Override public View createView(Context context) { actionBar.setBackgroundColor(Theme.ACTION_BAR_MEDIA_PICKER_COLOR); actionBar.setTitleColor(0xffffffff); actionBar.setItemsBackgroundColor(Theme.ACTION_BAR_PICKER_SELECTOR_COLOR, false); actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(int id) { if (id == -1) { finishFragment(); } else if (id == 1) { if (delegate != null) { finishFragment(false); delegate.startPhotoSelectActivity(); } } } }); ActionBarMenu menu = actionBar.createMenu(); menu.addItem(1, R.drawable.ic_ab_other); fragmentView = new FrameLayout(context); FrameLayout frameLayout = (FrameLayout) fragmentView; frameLayout.setBackgroundColor(0xff000000); actionBar.setTitle(LocaleController.getString("Gallery", R.string.Gallery)); listView = new RecyclerListView(context); listView.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), AndroidUtilities.dp(4)); listView.setClipToPadding(false); listView.setHorizontalScrollBarEnabled(false); listView.setVerticalScrollBarEnabled(false); listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setDrawingCacheEnabled(false); frameLayout.addView(listView); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = LayoutHelper.MATCH_PARENT; layoutParams.bottomMargin = AndroidUtilities.dp(48); listView.setLayoutParams(layoutParams); listView.setAdapter(listAdapter = new ListAdapter(context)); listView.setGlowColor(0xff333333); emptyView = new TextView(context); emptyView.setTextColor(0xff808080); emptyView.setTextSize(20); emptyView.setGravity(Gravity.CENTER); emptyView.setVisibility(View.GONE); emptyView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos)); frameLayout.addView(emptyView); layoutParams = (FrameLayout.LayoutParams) emptyView.getLayoutParams(); layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = LayoutHelper.MATCH_PARENT; layoutParams.bottomMargin = AndroidUtilities.dp(48); emptyView.setLayoutParams(layoutParams); emptyView.setOnTouchListener((v, event) -> true); progressView = new FrameLayout(context); progressView.setVisibility(View.GONE); frameLayout.addView(progressView); layoutParams = (FrameLayout.LayoutParams) progressView.getLayoutParams(); layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = LayoutHelper.MATCH_PARENT; layoutParams.bottomMargin = AndroidUtilities.dp(48); progressView.setLayoutParams(layoutParams); RadialProgressView progressBar = new RadialProgressView(context); progressView.addView(progressBar); layoutParams = (FrameLayout.LayoutParams) progressView.getLayoutParams(); layoutParams.width = LayoutHelper.WRAP_CONTENT; layoutParams.height = LayoutHelper.WRAP_CONTENT; layoutParams.gravity = Gravity.CENTER; progressView.setLayoutParams(layoutParams); pickerBottomLayout = new PickerBottomLayout(context); frameLayout.addView(pickerBottomLayout); layoutParams = (FrameLayout.LayoutParams) pickerBottomLayout.getLayoutParams(); layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = AndroidUtilities.dp(48); layoutParams.gravity = Gravity.BOTTOM; pickerBottomLayout.setLayoutParams(layoutParams); pickerBottomLayout.cancelButton.setOnClickListener(view -> finishFragment()); pickerBottomLayout.doneButton.setOnClickListener(view -> { sendSelectedPhotos(selectedPhotos, selectedPhotosOrder); finishFragment(); }); if (loading && (albumsSorted == null || albumsSorted != null && albumsSorted.isEmpty())) { progressView.setVisibility(View.VISIBLE); listView.setEmptyView(null); } else { progressView.setVisibility(View.GONE); listView.setEmptyView(emptyView); } pickerBottomLayout.updateSelectedCount(selectedPhotos.size(), true); return fragmentView; } @Override public void onResume() { super.onResume(); if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } fixLayout(); } @Override public void onConfigurationChanged(android.content.res.Configuration newConfig) { super.onConfigurationChanged(newConfig); fixLayout(); } @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.albumsDidLoad) { int guid = (Integer) args[0]; if (classGuid == guid) { if (selectPhotoType != 0 || !allowSearchImages) { albumsSorted = (ArrayList) args[2]; } else { albumsSorted = (ArrayList) args[1]; } if (progressView != null) { progressView.setVisibility(View.GONE); } if (listView != null && listView.getEmptyView() == null) { listView.setEmptyView(emptyView); } if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } loading = false; } } else if (id == NotificationCenter.closeChats) { removeSelfFromStack(); } else if (id == NotificationCenter.recentImagesDidLoad) { int type = (Integer) args[0]; if (type == 0) { recentWebImages = (ArrayList) args[1]; recentImagesWebKeys.clear(); for (MediaController.SearchImage searchImage : recentWebImages) { recentImagesWebKeys.put(searchImage.id, searchImage); } } else if (type == 1) { recentGifImages = (ArrayList) args[1]; recentImagesGifKeys.clear(); for (MediaController.SearchImage searchImage : recentGifImages) { recentImagesGifKeys.put(searchImage.id, searchImage); } } } } public void setMaxSelectedPhotos(int value) { maxSelectedPhotos = value; } public void setAllowSearchImages(boolean value) { allowSearchImages = value; } public void setDelegate(PhotoAlbumPickerActivityDelegate delegate) { this.delegate = delegate; } private void sendSelectedPhotos(HashMap photos, ArrayList order) { if (photos.isEmpty() || delegate == null || sendPressed) { return; } sendPressed = true; boolean gifChanged = false; boolean webChange = false; ArrayList media = new ArrayList<>(); for (int a = 0; a < order.size(); a++) { Object object = photos.get(order.get(a)); SendMessagesHelper.SendingMediaInfo info = new SendMessagesHelper.SendingMediaInfo(); media.add(info); if (object instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object; if (photoEntry.isVideo) { info.path = photoEntry.path; info.videoEditedInfo = photoEntry.editedInfo; } else if (photoEntry.imagePath != null) { info.path = photoEntry.imagePath; } else if (photoEntry.path != null) { info.path = photoEntry.path; } info.isVideo = photoEntry.isVideo; info.caption = photoEntry.caption != null ? photoEntry.caption.toString() : null; info.entities = photoEntry.entities; info.masks = !photoEntry.stickers.isEmpty() ? new ArrayList<>(photoEntry.stickers) : null; info.ttl = photoEntry.ttl; } else if (object instanceof MediaController.SearchImage) { MediaController.SearchImage searchImage = (MediaController.SearchImage) object; if (searchImage.imagePath != null) { info.path = searchImage.imagePath; } else { info.searchImage = searchImage; } info.caption = searchImage.caption != null ? searchImage.caption.toString() : null; info.entities = searchImage.entities; info.masks = !searchImage.stickers.isEmpty() ? new ArrayList<>(searchImage.stickers) : null; info.ttl = searchImage.ttl; searchImage.date = (int) (System.currentTimeMillis() / 1000); if (searchImage.type == 0) { webChange = true; MediaController.SearchImage recentImage = recentImagesWebKeys.get(searchImage.id); if (recentImage != null) { recentWebImages.remove(recentImage); recentWebImages.add(0, recentImage); } else { recentWebImages.add(0, searchImage); } } else if (searchImage.type == 1) { gifChanged = true; MediaController.SearchImage recentImage = recentImagesGifKeys.get(searchImage.id); if (recentImage != null) { recentGifImages.remove(recentImage); recentGifImages.add(0, recentImage); } else { recentGifImages.add(0, searchImage); } } } } if (webChange) { MessagesStorage.getInstance(currentAccount).putWebRecent(recentWebImages); } if (gifChanged) { MessagesStorage.getInstance(currentAccount).putWebRecent(recentGifImages); } delegate.didSelectPhotos(media); } private void fixLayout() { if (listView != null) { ViewTreeObserver obs = listView.getViewTreeObserver(); obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { fixLayoutInternal(); if (listView != null) { listView.getViewTreeObserver().removeOnPreDrawListener(this); } return true; } }); } } private void fixLayoutInternal() { if (getParentActivity() == null) { return; } WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); int rotation = manager.getDefaultDisplay().getRotation(); columnsCount = 2; if (!AndroidUtilities.isTablet() && (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90)) { columnsCount = 4; } listAdapter.notifyDataSetChanged(); } private void openPhotoPicker(MediaController.AlbumEntry albumEntry, int type) { ArrayList recentImages = null; if (albumEntry == null) { if (type == 0) { recentImages = recentWebImages; } else if (type == 1) { recentImages = recentGifImages; } } PhotoPickerActivity fragment; if (albumEntry != null) { fragment = new PhotoPickerActivity(type, albumEntry, selectedPhotos, selectedPhotosOrder, recentImages, selectPhotoType, allowCaption, chatActivity); fragment.setDelegate(new PhotoPickerActivity.PhotoPickerActivityDelegate() { @Override public void selectedPhotosChanged() { if (pickerBottomLayout != null) { pickerBottomLayout.updateSelectedCount(selectedPhotos.size(), true); } } @Override public void actionButtonPressed(boolean canceled) { removeSelfFromStack(); if (!canceled) { sendSelectedPhotos(selectedPhotos, selectedPhotosOrder); } } }); } else { final HashMap photos = new HashMap<>(); final ArrayList order = new ArrayList<>(); fragment = new PhotoPickerActivity(type, albumEntry, photos, order, recentImages, selectPhotoType, allowCaption, chatActivity); fragment.setDelegate(new PhotoPickerActivity.PhotoPickerActivityDelegate() { @Override public void selectedPhotosChanged() { } @Override public void actionButtonPressed(boolean canceled) { removeSelfFromStack(); if (!canceled) { sendSelectedPhotos(photos, order); } } }); } fragment.setMaxSelectedPhotos(maxSelectedPhotos); presentFragment(fragment); } private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; public ListAdapter(Context context) { mContext = context; } @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { return true; } @Override public int getItemCount() { if (!allowSearchImages) { return albumsSorted != null ? (int) Math.ceil(albumsSorted.size() / (float) columnsCount) : 0; } return 1 + (albumsSorted != null ? (int) Math.ceil(albumsSorted.size() / (float) columnsCount) : 0); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { case 0: { PhotoPickerAlbumsCell cell = new PhotoPickerAlbumsCell(mContext); cell.setDelegate(albumEntry -> openPhotoPicker(albumEntry, 0)); view = cell; break; } case 1: default: { PhotoPickerSearchCell cell = new PhotoPickerSearchCell(mContext, allowGifs); cell.setDelegate(index -> openPhotoPicker(null, index)); view = cell; break; } } return new RecyclerListView.Holder(view); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder.getItemViewType() == 0) { PhotoPickerAlbumsCell photoPickerAlbumsCell = (PhotoPickerAlbumsCell) holder.itemView; photoPickerAlbumsCell.setAlbumsCount(columnsCount); for (int a = 0; a < columnsCount; a++) { int index; if (!allowSearchImages) { index = position * columnsCount + a; } else { index = (position - 1) * columnsCount + a; } if (index < albumsSorted.size()) { MediaController.AlbumEntry albumEntry = albumsSorted.get(index); photoPickerAlbumsCell.setAlbum(a, albumEntry); } else { photoPickerAlbumsCell.setAlbum(a, null); } } photoPickerAlbumsCell.requestLayout(); } } @Override public int getItemViewType(int i) { if (!allowSearchImages) { return 0; } if (i == 0) { return 1; } return 0; } } }