mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-31 07:36:09 +00:00
refactor: replacing the media loader calls to no longer bucket them by dates
This commit is contained in:
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.codewaves.stickyheadergrid.StickyHeaderGridAdapter;
|
||||
|
||||
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView;
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
|
||||
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
class MediaGalleryAdapter extends StickyHeaderGridAdapter {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = MediaGalleryAdapter.class.getSimpleName();
|
||||
|
||||
private final Context context;
|
||||
private final GlideRequests glideRequests;
|
||||
private final Locale locale;
|
||||
private final ItemClickListener itemClickListener;
|
||||
private final Set<MediaRecord> selected;
|
||||
|
||||
private BucketedThreadMedia media;
|
||||
|
||||
private static class ViewHolder extends StickyHeaderGridAdapter.ItemViewHolder {
|
||||
ThumbnailView imageView;
|
||||
View selectedIndicator;
|
||||
|
||||
ViewHolder(View v) {
|
||||
super(v);
|
||||
imageView = v.findViewById(R.id.image);
|
||||
selectedIndicator = v.findViewById(R.id.selected_indicator);
|
||||
}
|
||||
}
|
||||
|
||||
private static class HeaderHolder extends StickyHeaderGridAdapter.HeaderViewHolder {
|
||||
TextView textView;
|
||||
|
||||
HeaderHolder(View itemView) {
|
||||
super(itemView);
|
||||
textView = itemView.findViewById(R.id.text);
|
||||
}
|
||||
}
|
||||
|
||||
MediaGalleryAdapter(@NonNull Context context,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
BucketedThreadMedia media,
|
||||
Locale locale,
|
||||
ItemClickListener clickListener)
|
||||
{
|
||||
this.context = context;
|
||||
this.glideRequests = glideRequests;
|
||||
this.locale = locale;
|
||||
this.media = media;
|
||||
this.itemClickListener = clickListener;
|
||||
this.selected = new HashSet<>();
|
||||
}
|
||||
|
||||
public void setMedia(BucketedThreadMedia media) {
|
||||
this.media = media;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StickyHeaderGridAdapter.HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent, int headerType) {
|
||||
return new HeaderHolder(LayoutInflater.from(context).inflate(R.layout.media_overview_gallery_item_header, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemViewHolder onCreateItemViewHolder(ViewGroup parent, int itemType) {
|
||||
return new ViewHolder(LayoutInflater.from(context).inflate(R.layout.media_overview_gallery_item, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindHeaderViewHolder(StickyHeaderGridAdapter.HeaderViewHolder viewHolder, int section) {
|
||||
((HeaderHolder)viewHolder).textView.setText(media.getName(section, locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindItemViewHolder(ItemViewHolder viewHolder, int section, int offset) {
|
||||
MediaRecord mediaRecord = media.get(section, offset);
|
||||
ThumbnailView thumbnailView = ((ViewHolder)viewHolder).imageView;
|
||||
View selectedIndicator = ((ViewHolder)viewHolder).selectedIndicator;
|
||||
Slide slide = MediaUtil.getSlideForAttachment(context, mediaRecord.getAttachment());
|
||||
|
||||
if (slide != null) {
|
||||
thumbnailView.setImageResource(glideRequests, slide, false, false);
|
||||
}
|
||||
|
||||
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
|
||||
thumbnailView.setOnLongClickListener(view -> {
|
||||
itemClickListener.onMediaLongClicked(mediaRecord);
|
||||
return true;
|
||||
});
|
||||
|
||||
selectedIndicator.setVisibility(selected.contains(mediaRecord) ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSectionCount() {
|
||||
return media.getSectionCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSectionItemCount(int section) {
|
||||
return media.getSectionItemCount(section);
|
||||
}
|
||||
|
||||
public void toggleSelection(@NonNull MediaRecord mediaRecord) {
|
||||
if (!selected.remove(mediaRecord)) {
|
||||
selected.add(mediaRecord);
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public int getSelectedMediaCount() {
|
||||
return selected.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Collection<MediaRecord> getSelectedMedia() {
|
||||
return new HashSet<>(selected);
|
||||
}
|
||||
|
||||
public void clearSelection() {
|
||||
selected.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
void selectAllMedia() {
|
||||
for (int section = 0; section < media.getSectionCount(); section++) {
|
||||
for (int item = 0; item < media.getSectionItemCount(section); item++) {
|
||||
selected.add(media.get(section, item));
|
||||
}
|
||||
}
|
||||
this.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
interface ItemClickListener {
|
||||
void onMediaClicked(@NonNull MediaRecord mediaRecord);
|
||||
void onMediaLongClicked(MediaRecord mediaRecord);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.thoughtcrime.securesms
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.MediaOverviewGalleryItemBinding
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord
|
||||
|
||||
class MediaGalleryAdapter(private val itemClickListener: ItemClickListener): RecyclerView.Adapter<MediaGalleryAdapter.ViewHolder>() {
|
||||
|
||||
private val items: MutableList<MediaRecord> = mutableListOf()
|
||||
private val selectedItems: MutableList<MediaRecord> = mutableListOf()
|
||||
|
||||
fun setItems(newItems: List<MediaRecord>) {
|
||||
items.clear()
|
||||
items += newItems
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.media_overview_gallery_item, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
holder.bind(item, selectedItems.contains(item), itemClickListener)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
||||
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
private val binding = MediaOverviewGalleryItemBinding.bind(itemView)
|
||||
|
||||
fun bind(item: MediaRecord, isSelected: Boolean, itemClickListener: ItemClickListener) {
|
||||
binding.image.setOnClickListener { itemClickListener.onMediaClicked(item) }
|
||||
binding.image.setOnLongClickListener {
|
||||
itemClickListener.onMediaLongClicked(item)
|
||||
true
|
||||
}
|
||||
binding.selectedIndicator.isVisible = isSelected
|
||||
}
|
||||
}
|
||||
|
||||
interface ItemClickListener {
|
||||
fun onMediaClicked(mediaRecord: MediaRecord)
|
||||
fun onMediaLongClicked(mediaRecord: MediaRecord?)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -75,7 +75,9 @@ import org.thoughtcrime.securesms.util.AttachmentUtil;
|
||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -244,7 +246,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
|
||||
}
|
||||
|
||||
public static class MediaOverviewGalleryFragment
|
||||
extends MediaOverviewFragment<BucketedThreadMedia>
|
||||
extends MediaOverviewFragment<ThreadMediaLoader>
|
||||
implements MediaGalleryAdapter.ItemClickListener
|
||||
{
|
||||
|
||||
@@ -260,11 +262,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
|
||||
this.noMedia = ViewUtil.findById(view, R.id.no_images);
|
||||
this.gridManager = new StickyHeaderGridLayoutManager(getResources().getInteger(R.integer.media_overview_cols));
|
||||
|
||||
this.recyclerView.setAdapter(new MediaGalleryAdapter(getContext(),
|
||||
GlideApp.with(this),
|
||||
new BucketedThreadMedia(getContext()),
|
||||
locale,
|
||||
this));
|
||||
this.recyclerView.setAdapter(new MediaGalleryAdapter(this));
|
||||
this.recyclerView.setLayoutManager(gridManager);
|
||||
this.recyclerView.setHasFixedSize(true);
|
||||
|
||||
@@ -281,22 +279,21 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Loader<BucketedThreadMedia> onCreateLoader(int i, Bundle bundle) {
|
||||
return new BucketedThreadMediaLoader(getContext(), recipient.getAddress());
|
||||
public @NonNull Loader<ThreadMediaLoader> onCreateLoader(int i, Bundle bundle) {
|
||||
return new ThreadMediaLoader(getContext(), recipient.getAddress(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(@NonNull Loader<BucketedThreadMedia> loader, BucketedThreadMedia bucketedThreadMedia) {
|
||||
((MediaGalleryAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia);
|
||||
((MediaGalleryAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged();
|
||||
public void onLoadFinished(@NonNull Loader<ThreadMediaLoader> loader, ThreadMediaLoader threadMedia) {
|
||||
((MediaGalleryAdapter) recyclerView.getAdapter()).setItems(threadMedia.);
|
||||
|
||||
noMedia.setVisibility(recyclerView.getAdapter().getItemCount() > 0 ? View.GONE : View.VISIBLE);
|
||||
getActivity().invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(@NonNull Loader<BucketedThreadMedia> cursorLoader) {
|
||||
((MediaGalleryAdapter) recyclerView.getAdapter()).setMedia(new BucketedThreadMedia(getContext()));
|
||||
public void onLoaderReset(@NonNull Loader<ThreadMediaLoader> cursorLoader) {
|
||||
((MediaGalleryAdapter) recyclerView.getAdapter()).setItems(new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
<dimen name="quote_corner_radius_bottom">2dp</dimen>
|
||||
<dimen name="quote_corner_radius_preview">16dp</dimen>
|
||||
|
||||
<integer name="media_overview_cols">3</integer>
|
||||
<integer name="media_overview_cols">4</integer>
|
||||
|
||||
<dimen name="contact_selection_actions_tap_area">10dp</dimen>
|
||||
|
||||
|
||||
@@ -55,9 +55,8 @@ public class DatabaseAttachment extends Attachment {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return other != null &&
|
||||
other instanceof DatabaseAttachment &&
|
||||
((DatabaseAttachment) other).attachmentId.equals(this.attachmentId);
|
||||
return other instanceof DatabaseAttachment &&
|
||||
((DatabaseAttachment) other).attachmentId.equals(this.attachmentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -103,8 +103,6 @@
|
||||
<dimen name="quote_corner_radius_bottom">2dp</dimen>
|
||||
<dimen name="quote_corner_radius_preview">16dp</dimen>
|
||||
|
||||
<integer name="media_overview_cols">3</integer>
|
||||
|
||||
<dimen name="contact_selection_actions_tap_area">10dp</dimen>
|
||||
|
||||
<dimen name="unread_count_bubble_radius">13sp</dimen>
|
||||
|
||||
Reference in New Issue
Block a user