2016-11-25 22:37:23 -08:00
|
|
|
package org.thoughtcrime.securesms.components;
|
|
|
|
|
|
|
|
|
2019-01-17 12:15:00 -08:00
|
|
|
import android.annotation.TargetApi;
|
2016-11-25 22:37:23 -08:00
|
|
|
import android.content.Context;
|
|
|
|
import android.database.Cursor;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.provider.MediaStore;
|
2020-08-19 10:06:26 +10:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.loader.app.LoaderManager;
|
|
|
|
import androidx.loader.content.Loader;
|
|
|
|
import androidx.recyclerview.widget.DefaultItemAnimator;
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
|
|
import androidx.recyclerview.widget.RecyclerView;
|
2016-11-25 22:37:23 -08:00
|
|
|
import android.util.AttributeSet;
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
import android.widget.ImageView;
|
|
|
|
|
|
|
|
import com.bumptech.glide.load.Key;
|
2017-01-08 13:06:11 -08:00
|
|
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
2016-11-25 22:37:23 -08:00
|
|
|
import com.bumptech.glide.signature.MediaStoreSignature;
|
|
|
|
|
2019-07-24 12:30:23 +10:00
|
|
|
import network.loki.messenger.R;
|
2016-11-25 22:37:23 -08:00
|
|
|
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
|
|
|
import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader;
|
2017-10-11 17:12:46 -07:00
|
|
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
2016-11-25 22:37:23 -08:00
|
|
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
|
|
|
|
|
|
|
public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> {
|
|
|
|
|
|
|
|
@NonNull private final RecyclerView recyclerView;
|
|
|
|
@Nullable private OnItemClickedListener listener;
|
|
|
|
|
|
|
|
public RecentPhotoViewRail(Context context) {
|
|
|
|
this(context, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public RecentPhotoViewRail(Context context, AttributeSet attrs) {
|
|
|
|
this(context, attrs, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public RecentPhotoViewRail(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
|
|
super(context, attrs, defStyleAttr);
|
|
|
|
|
|
|
|
inflate(context, R.layout.recent_photo_view, this);
|
|
|
|
|
|
|
|
this.recyclerView = ViewUtil.findById(this, R.id.photo_list);
|
|
|
|
this.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
|
|
|
|
this.recyclerView.setItemAnimator(new DefaultItemAnimator());
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setListener(@Nullable OnItemClickedListener listener) {
|
|
|
|
this.listener = listener;
|
|
|
|
|
|
|
|
if (this.recyclerView.getAdapter() != null) {
|
|
|
|
((RecentPhotoAdapter)this.recyclerView.getAdapter()).setListener(listener);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-05-22 13:51:56 -03:00
|
|
|
public @NonNull Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
2016-11-25 22:37:23 -08:00
|
|
|
return new RecentPhotosLoader(getContext());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-05-22 13:51:56 -03:00
|
|
|
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
|
2016-11-25 22:37:23 -08:00
|
|
|
this.recyclerView.setAdapter(new RecentPhotoAdapter(getContext(), data, RecentPhotosLoader.BASE_URL, listener));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-05-22 13:51:56 -03:00
|
|
|
public void onLoaderReset(@NonNull Loader<Cursor> loader) {
|
2016-11-25 22:37:23 -08:00
|
|
|
((CursorRecyclerViewAdapter)this.recyclerView.getAdapter()).changeCursor(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class RecentPhotoAdapter extends CursorRecyclerViewAdapter<RecentPhotoAdapter.RecentPhotoViewHolder> {
|
|
|
|
|
2017-11-24 22:00:30 -08:00
|
|
|
@SuppressWarnings("unused")
|
2018-12-06 12:14:20 -08:00
|
|
|
private static final String TAG = RecentPhotoAdapter.class.getSimpleName();
|
2017-01-08 13:06:11 -08:00
|
|
|
|
2016-11-25 22:37:23 -08:00
|
|
|
@NonNull private final Uri baseUri;
|
|
|
|
@Nullable private OnItemClickedListener clickedListener;
|
|
|
|
|
|
|
|
private RecentPhotoAdapter(@NonNull Context context, @NonNull Cursor cursor, @NonNull Uri baseUri, @Nullable OnItemClickedListener listener) {
|
|
|
|
super(context, cursor);
|
|
|
|
this.baseUri = baseUri;
|
|
|
|
this.clickedListener = listener;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RecentPhotoViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
|
|
|
|
View itemView = LayoutInflater.from(parent.getContext())
|
|
|
|
.inflate(R.layout.recent_photo_view_item, parent, false);
|
|
|
|
|
|
|
|
return new RecentPhotoViewHolder(itemView);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onBindItemViewHolder(RecentPhotoViewHolder viewHolder, @NonNull Cursor cursor) {
|
|
|
|
viewHolder.imageView.setImageDrawable(null);
|
|
|
|
|
|
|
|
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns._ID));
|
|
|
|
long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_TAKEN));
|
|
|
|
long dateModified = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_MODIFIED));
|
|
|
|
String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.MIME_TYPE));
|
2018-11-20 09:59:23 -08:00
|
|
|
String bucketId = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.BUCKET_ID));
|
2016-11-25 22:37:23 -08:00
|
|
|
int orientation = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.ORIENTATION));
|
2019-03-14 17:01:23 -07:00
|
|
|
long size = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.SIZE));
|
2019-03-20 15:09:27 -07:00
|
|
|
int width = cursor.getInt(cursor.getColumnIndexOrThrow(getWidthColumn(orientation)));
|
|
|
|
int height = cursor.getInt(cursor.getColumnIndexOrThrow(getHeightColumn(orientation)));
|
2016-11-25 22:37:23 -08:00
|
|
|
|
|
|
|
final Uri uri = Uri.withAppendedPath(baseUri, Long.toString(id));
|
|
|
|
|
|
|
|
Key signature = new MediaStoreSignature(mimeType, dateModified, orientation);
|
|
|
|
|
2017-10-16 13:11:42 -07:00
|
|
|
GlideApp.with(getContext().getApplicationContext())
|
2017-10-11 17:12:46 -07:00
|
|
|
.load(uri)
|
|
|
|
.signature(signature)
|
|
|
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
|
|
|
.into(viewHolder.imageView);
|
2016-11-25 22:37:23 -08:00
|
|
|
|
2017-11-24 22:00:30 -08:00
|
|
|
viewHolder.imageView.setOnClickListener(v -> {
|
2019-03-14 17:01:23 -07:00
|
|
|
if (clickedListener != null) clickedListener.onItemClicked(uri, mimeType, bucketId, dateTaken, width, height, size);
|
2016-11-25 22:37:23 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-17 12:15:00 -08:00
|
|
|
@TargetApi(16)
|
|
|
|
@SuppressWarnings("SuspiciousNameCombination")
|
|
|
|
private String getWidthColumn(int orientation) {
|
|
|
|
if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.WIDTH;
|
|
|
|
else return MediaStore.Images.ImageColumns.HEIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
@TargetApi(16)
|
|
|
|
@SuppressWarnings("SuspiciousNameCombination")
|
|
|
|
private String getHeightColumn(int orientation) {
|
|
|
|
if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.HEIGHT;
|
|
|
|
else return MediaStore.Images.ImageColumns.WIDTH;
|
|
|
|
}
|
|
|
|
|
2016-11-25 22:37:23 -08:00
|
|
|
public void setListener(@Nullable OnItemClickedListener listener) {
|
|
|
|
this.clickedListener = listener;
|
|
|
|
}
|
|
|
|
|
|
|
|
static class RecentPhotoViewHolder extends RecyclerView.ViewHolder {
|
|
|
|
|
|
|
|
ImageView imageView;
|
|
|
|
|
|
|
|
RecentPhotoViewHolder(View itemView) {
|
|
|
|
super(itemView);
|
|
|
|
|
|
|
|
this.imageView = ViewUtil.findById(itemView, R.id.thumbnail);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface OnItemClickedListener {
|
2019-03-14 17:01:23 -07:00
|
|
|
void onItemClicked(Uri uri, String mimeType, String bucketId, long dateTaken, int width, int height, long size);
|
2016-11-25 22:37:23 -08:00
|
|
|
}
|
|
|
|
}
|