Improve storage management detail view descriptions.
This commit is contained in:
parent
544b75a2a7
commit
911ca7c29d
10 changed files with 264 additions and 93 deletions
|
@ -13,34 +13,28 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/line1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toEndOf="@+id/image_container"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Sent voice note, 02:35"
|
||||
tools:visibility="visible" />
|
||||
tools:text="Sent voice note, 02:35" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/line2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="6dp"
|
||||
android:paddingEnd="6dp"
|
||||
android:singleLine="true"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toEndOf="@+id/image_container"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="2.7 MB, 11.06.19 at 5:25 AM"
|
||||
tools:visibility="visible" />
|
||||
tools:text="2.7 MB, 11.06.19 at 5:25 AM" />
|
||||
|
||||
</LinearLayout>
|
|
@ -353,11 +353,7 @@
|
|||
<string name="DeviceListItem_today">Today</string>
|
||||
|
||||
<!-- DocumentView -->
|
||||
<string name="DocumentView_unknown_file">Unknown file</string>
|
||||
<string name="DocumentView_unnamed_file">Unnamed file</string>
|
||||
<string name="DocumentView_audio_file">Audio file</string>
|
||||
<string name="DocumentView_image_file">Image file</string>
|
||||
<string name="DocumentView_video_file">Video file</string>
|
||||
|
||||
<!-- DozeReminder -->
|
||||
<string name="DozeReminder_optimize_for_missing_play_services">Optimize for missing Play Services</string>
|
||||
|
@ -486,6 +482,9 @@
|
|||
|
||||
<!-- MediaOverviewActivity -->
|
||||
<string name="MediaOverviewActivity_Media">Media</string>
|
||||
<string name="MediaOverviewActivity_Files">Files</string>
|
||||
<string name="MediaOverviewActivity_Audio">Audio</string>
|
||||
<string name="MediaOverviewActivity_All">All</string>
|
||||
<plurals name="MediaOverviewActivity_Media_delete_confirm_title">
|
||||
<item quantity="one">Delete selected item?</item>
|
||||
<item quantity="other">Delete selected items?</item>
|
||||
|
@ -496,11 +495,8 @@
|
|||
</plurals>
|
||||
<string name="MediaOverviewActivity_Media_delete_progress_title">Deleting</string>
|
||||
<string name="MediaOverviewActivity_Media_delete_progress_message">Deleting messages…</string>
|
||||
<string name="MediaOverviewActivity_Files">Files</string>
|
||||
<string name="MediaOverviewActivity_Select_all">Select all</string>
|
||||
<string name="MediaOverviewActivity_collecting_attachments">Collecting attachments…</string>
|
||||
<string name="MediaOverviewActivity_Audio">Audio</string>
|
||||
<string name="MediaOverviewActivity_All">All</string>
|
||||
<string name="MediaOverviewActivity_Sort_by">Sort by</string>
|
||||
<string name="MediaOverviewActivity_Newest">Newest</string>
|
||||
<string name="MediaOverviewActivity_Oldest">Oldest</string>
|
||||
|
@ -510,6 +506,18 @@
|
|||
<string name="MediaOverviewActivity_List_view_description">List view</string>
|
||||
<string name="MediaOverviewActivity_Selected_description">Selected</string>
|
||||
|
||||
<string name="MediaOverviewActivity_file">File</string>
|
||||
<string name="MediaOverviewActivity_audio">Audio</string>
|
||||
<string name="MediaOverviewActivity_video">Video</string>
|
||||
<string name="MediaOverviewActivity_image">Image</string>
|
||||
<string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string>
|
||||
<string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string>
|
||||
|
||||
<string name="MediaOverviewActivity_sent_by_s">Sent by %1$s</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you">Sent by you</string>
|
||||
<string name="MediaOverviewActivity_sent_by_s_to_s">Sent by %1$s to %2$s</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you_to_s">Sent by you to %1$s</string>
|
||||
|
||||
<!--- NotificationBarManager -->
|
||||
<string name="NotificationBarManager_signal_call_in_progress">Signal call in progress</string>
|
||||
<string name="NotificationBarManager__establishing_signal_call">Establishing Signal call</string>
|
||||
|
|
|
@ -52,7 +52,6 @@ import androidx.viewpager.widget.ViewPager;
|
|||
import org.thoughtcrime.securesms.animation.DepthPageTransformer;
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||
import org.thoughtcrime.securesms.components.viewpager.ExtendedOnPageChangedListener;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase;
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
|
||||
import org.thoughtcrime.securesms.database.loaders.PagingMediaLoader;
|
||||
|
@ -722,13 +721,12 @@ public final class MediaPreviewActivity extends PassphraseRequiredActionBarActiv
|
|||
|
||||
MediaRecord mediaRecord = MediaRecord.from(context, cursor);
|
||||
RecipientId recipientId = mediaRecord.getRecipientId();
|
||||
RecipientId threadRecipientId = DatabaseFactory.getThreadDatabase(context)
|
||||
.getRecipientIdForThreadId(mediaRecord.getThreadId());
|
||||
RecipientId threadRecipientId = mediaRecord.getThreadRecipientId();
|
||||
|
||||
if (mediaRecord.getAttachment().getDataUri() == null) throw new AssertionError();
|
||||
|
||||
return new MediaItem(Recipient.live(recipientId).get(),
|
||||
threadRecipientId != null ? Recipient.live(threadRecipientId).get() : null,
|
||||
Recipient.live(threadRecipientId).get(),
|
||||
mediaRecord.getAttachment(),
|
||||
mediaRecord.getAttachment().getDataUri(),
|
||||
mediaRecord.getContentType(),
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.database.ContentObserver;
|
|||
import android.database.Cursor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.sqlcipher.database.SQLiteDatabase;
|
||||
|
||||
|
@ -17,7 +18,8 @@ import java.util.List;
|
|||
|
||||
public class MediaDatabase extends Database {
|
||||
|
||||
public static final int ALL_THREADS = -1;
|
||||
public static final int ALL_THREADS = -1;
|
||||
private static final String THREAD_RECIPIENT_ID = "THREAD_RECIPIENT_ID";
|
||||
|
||||
private static final String BASE_MEDIA_QUERY = "SELECT " + AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.ROW_ID + " AS " + AttachmentDatabase.ROW_ID + ", "
|
||||
+ AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.CONTENT_TYPE + ", "
|
||||
|
@ -48,9 +50,12 @@ public class MediaDatabase extends Database {
|
|||
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_SENT + ", "
|
||||
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_RECEIVED + ", "
|
||||
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.THREAD_ID + ", "
|
||||
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.RECIPIENT_ID + " "
|
||||
+ MmsDatabase.TABLE_NAME + "." + MmsDatabase.RECIPIENT_ID + ", "
|
||||
+ ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.RECIPIENT_ID + " as " + THREAD_RECIPIENT_ID + " "
|
||||
+ "FROM " + AttachmentDatabase.TABLE_NAME + " LEFT JOIN " + MmsDatabase.TABLE_NAME
|
||||
+ " ON " + AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.MMS_ID + " = " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID + " "
|
||||
+ "LEFT JOIN " + ThreadDatabase.TABLE_NAME
|
||||
+ " ON " + ThreadDatabase.TABLE_NAME + "." + ThreadDatabase.ID + " = " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.THREAD_ID + " "
|
||||
+ "WHERE " + AttachmentDatabase.MMS_ID + " IN (SELECT " + MmsSmsColumns.ID
|
||||
+ " FROM " + MmsDatabase.TABLE_NAME
|
||||
+ " WHERE " + MmsDatabase.THREAD_ID + " __EQUALITY__ ?) AND (%s) AND "
|
||||
|
@ -167,16 +172,24 @@ public class MediaDatabase extends Database {
|
|||
|
||||
private final DatabaseAttachment attachment;
|
||||
private final RecipientId recipientId;
|
||||
private final RecipientId threadRecipientId;
|
||||
private final long threadId;
|
||||
private final long date;
|
||||
private final boolean outgoing;
|
||||
|
||||
private MediaRecord(DatabaseAttachment attachment, @NonNull RecipientId recipientId, long threadId, long date, boolean outgoing) {
|
||||
this.attachment = attachment;
|
||||
this.recipientId = recipientId;
|
||||
this.threadId = threadId;
|
||||
this.date = date;
|
||||
this.outgoing = outgoing;
|
||||
private MediaRecord(@Nullable DatabaseAttachment attachment,
|
||||
@NonNull RecipientId recipientId,
|
||||
@NonNull RecipientId threadRecipientId,
|
||||
long threadId,
|
||||
long date,
|
||||
boolean outgoing)
|
||||
{
|
||||
this.attachment = attachment;
|
||||
this.recipientId = recipientId;
|
||||
this.threadRecipientId = threadRecipientId;
|
||||
this.threadId = threadId;
|
||||
this.date = date;
|
||||
this.outgoing = outgoing;
|
||||
}
|
||||
|
||||
public static MediaRecord from(@NonNull Context context, @NonNull Cursor cursor) {
|
||||
|
@ -194,10 +207,17 @@ public class MediaDatabase extends Database {
|
|||
date = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.DATE_RECEIVED));
|
||||
}
|
||||
|
||||
return new MediaRecord(attachments != null && attachments.size() > 0 ? attachments.get(0) : null, recipientId, threadId, date, outgoing);
|
||||
RecipientId threadRecipient = RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_RECIPIENT_ID)));
|
||||
|
||||
return new MediaRecord(attachments != null && attachments.size() > 0 ? attachments.get(0) : null,
|
||||
recipientId,
|
||||
threadRecipient,
|
||||
threadId,
|
||||
date,
|
||||
outgoing);
|
||||
}
|
||||
|
||||
public DatabaseAttachment getAttachment() {
|
||||
public @Nullable DatabaseAttachment getAttachment() {
|
||||
return attachment;
|
||||
}
|
||||
|
||||
|
@ -209,6 +229,10 @@ public class MediaDatabase extends Database {
|
|||
return recipientId;
|
||||
}
|
||||
|
||||
public @NonNull RecipientId getThreadRecipientId() {
|
||||
return threadRecipientId;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
return threadId;
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
package org.thoughtcrime.securesms.mediaoverview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.codewaves.stickyheadergrid.StickyHeaderGridAdapter;
|
||||
|
@ -37,9 +39,14 @@ import org.thoughtcrime.securesms.database.loaders.GroupedThreadMediaLoader.Grou
|
|||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataPair;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
@ -50,6 +57,7 @@ import java.util.Map;
|
|||
final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
||||
|
||||
private final Context context;
|
||||
private final boolean showThread;
|
||||
private final GlideRequests glideRequests;
|
||||
private final ItemClickListener itemClickListener;
|
||||
private final Map<AttachmentId, MediaRecord> selected = new HashMap<>();
|
||||
|
@ -63,12 +71,18 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
private static final int GALLERY_DETAIL = 3;
|
||||
private static final int DOCUMENT_DETAIL = 4;
|
||||
|
||||
public void pause(RecyclerView.ViewHolder holder) {
|
||||
void pause(RecyclerView.ViewHolder holder) {
|
||||
if (holder instanceof AudioDetailViewHolder) {
|
||||
((AudioDetailViewHolder) holder).pause();
|
||||
}
|
||||
}
|
||||
|
||||
void detach(RecyclerView.ViewHolder holder) {
|
||||
if (holder instanceof SelectableViewHolder) {
|
||||
((SelectableViewHolder) holder).onDetached();
|
||||
}
|
||||
}
|
||||
|
||||
private static class HeaderHolder extends HeaderViewHolder {
|
||||
TextView textView;
|
||||
|
||||
|
@ -82,13 +96,15 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
@NonNull GlideRequests glideRequests,
|
||||
GroupedThreadMedia media,
|
||||
ItemClickListener clickListener,
|
||||
boolean showFileSizes)
|
||||
boolean showFileSizes,
|
||||
boolean showThread)
|
||||
{
|
||||
this.context = context;
|
||||
this.glideRequests = glideRequests;
|
||||
this.media = media;
|
||||
this.itemClickListener = clickListener;
|
||||
this.showFileSizes = showFileSizes;
|
||||
this.showThread = showThread;
|
||||
}
|
||||
|
||||
public void setMedia(GroupedThreadMedia media) {
|
||||
|
@ -143,7 +159,7 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {
|
||||
super.onViewDetachedFromWindow(holder);
|
||||
if (holder instanceof SelectableViewHolder) {
|
||||
((SelectableViewHolder) holder).detached();
|
||||
((SelectableViewHolder) holder).onDetached();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,8 +198,10 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
}
|
||||
|
||||
void selectAllMedia() {
|
||||
for (int section = 0; section < media.getSectionCount(); section++) {
|
||||
for (int item = 0; item < media.getSectionItemCount(section); item++) {
|
||||
int sectionCount = media.getSectionCount();
|
||||
for (int section = 0; section < sectionCount; section++) {
|
||||
int sectionItemCount = media.getSectionItemCount(section);
|
||||
for (int item = 0; item < sectionItemCount; item++) {
|
||||
MediaRecord mediaRecord = media.get(section, item);
|
||||
selected.put(mediaRecord.getAttachment().getAttachmentId(), mediaRecord);
|
||||
}
|
||||
|
@ -203,6 +221,7 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
|
||||
private final View selectedIndicator;
|
||||
private MediaDatabase.MediaRecord mediaRecord;
|
||||
private boolean bound;
|
||||
|
||||
SelectableViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
|
@ -210,8 +229,16 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
}
|
||||
|
||||
public void bind(@NonNull Context context, @NonNull MediaDatabase.MediaRecord mediaRecord, @NonNull Slide slide) {
|
||||
if (bound) {
|
||||
unbind();
|
||||
}
|
||||
this.mediaRecord = mediaRecord;
|
||||
updateSelectedView();
|
||||
bound = true;
|
||||
}
|
||||
|
||||
void unbind() {
|
||||
bound = false;
|
||||
}
|
||||
|
||||
private void updateSelectedView() {
|
||||
|
@ -226,7 +253,10 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
return true;
|
||||
}
|
||||
|
||||
void detached() {
|
||||
void onDetached() {
|
||||
if (bound) {
|
||||
unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,16 +289,22 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
void detached() {
|
||||
void unbind() {
|
||||
thumbnailView.clear(glideRequests);
|
||||
super.unbind();
|
||||
}
|
||||
}
|
||||
|
||||
private class DetailViewHolder extends SelectableViewHolder {
|
||||
private abstract class DetailViewHolder extends SelectableViewHolder implements Observer<Pair<Recipient, Recipient>> {
|
||||
|
||||
protected final View itemView;
|
||||
private final TextView line1;
|
||||
private final TextView line2;
|
||||
protected final View itemView;
|
||||
private final TextView line1;
|
||||
private final TextView line2;
|
||||
private LiveDataPair<Recipient, Recipient> liveDataPair;
|
||||
private Optional<String> fileName;
|
||||
private String fileTypeDescription;
|
||||
private Handler handler;
|
||||
private Runnable selectForMarque;
|
||||
|
||||
DetailViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
|
@ -281,27 +317,82 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
public void bind(@NonNull Context context, @NonNull MediaDatabase.MediaRecord mediaRecord, @NonNull Slide slide) {
|
||||
super.bind(context, mediaRecord, slide);
|
||||
|
||||
line1.setText(getLine1(context, slide));
|
||||
line2.setText(getLine2(mediaRecord, slide));
|
||||
line1.setVisibility(View.VISIBLE);
|
||||
line2.setVisibility(View.VISIBLE);
|
||||
fileName = slide.getFileName();
|
||||
fileTypeDescription = getFileTypeDescription(context, slide);
|
||||
|
||||
line1.setText(fileName.or(fileTypeDescription));
|
||||
line2.setText(getLine2(context, mediaRecord, slide));
|
||||
itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
|
||||
itemView.setOnLongClickListener(view -> onLongClick());
|
||||
selectForMarque = () -> line1.setSelected(true);
|
||||
handler = new Handler();
|
||||
handler.postDelayed(selectForMarque, 2500);
|
||||
|
||||
LiveRecipient from = mediaRecord.isOutgoing() ? Recipient.self().live() : Recipient.live(mediaRecord.getRecipientId());
|
||||
LiveRecipient to = Recipient.live(mediaRecord.getThreadRecipientId());
|
||||
|
||||
liveDataPair = new LiveDataPair<>(from.getLiveData(), to.getLiveData(), Recipient.UNKNOWN, Recipient.UNKNOWN);
|
||||
liveDataPair.observeForever(this);
|
||||
}
|
||||
|
||||
private String getLine1(@NonNull Context context, @NonNull Slide slide) {
|
||||
return slide.getFileName()
|
||||
.or(slide.getCaption())
|
||||
.or(() -> describeUnnamedFile(context, slide));
|
||||
@Override
|
||||
void unbind() {
|
||||
liveDataPair.removeObserver(this);
|
||||
handler.removeCallbacks(selectForMarque);
|
||||
line1.setSelected(false);
|
||||
super.unbind();
|
||||
}
|
||||
|
||||
private String getLine2(@NonNull MediaDatabase.MediaRecord mediaRecord, @NonNull Slide slide) {
|
||||
String date = DateUtils.formatDate(Locale.getDefault(), mediaRecord.getDate());
|
||||
return Util.getPrettyFileSize(slide.getFileSize()) + " " + date;
|
||||
private String getLine2(@NonNull Context context, @NonNull MediaDatabase.MediaRecord mediaRecord, @NonNull Slide slide) {
|
||||
return context.getString(R.string.MediaOverviewActivity_detail_line_3_part,
|
||||
Util.getPrettyFileSize(slide.getFileSize()),
|
||||
getFileTypeDescription(context, slide),
|
||||
DateUtils.formatDateWithoutDayOfWeek(Locale.getDefault(), mediaRecord.getDate()));
|
||||
}
|
||||
|
||||
protected String describeUnnamedFile(@NonNull Context context, @NonNull Slide slide) {
|
||||
return context.getString(R.string.DocumentView_unnamed_file);
|
||||
protected String getFileTypeDescription(@NonNull Context context, @NonNull Slide slide){
|
||||
return context.getString(R.string.MediaOverviewActivity_file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(Pair<Recipient, Recipient> fromToPair) {
|
||||
line1.setText(describe(fromToPair.first(), fromToPair.second()));
|
||||
}
|
||||
|
||||
private String describe(@NonNull Recipient from, @NonNull Recipient thread) {
|
||||
if (from == Recipient.UNKNOWN && thread == Recipient.UNKNOWN) {
|
||||
return fileName.or(fileTypeDescription);
|
||||
}
|
||||
|
||||
String sentFromToString = getSentFromToString(from, thread);
|
||||
|
||||
if (fileName.isPresent()) {
|
||||
return context.getString(R.string.MediaOverviewActivity_detail_line_2_part,
|
||||
fileName.get(),
|
||||
sentFromToString);
|
||||
} else {
|
||||
return sentFromToString;
|
||||
}
|
||||
}
|
||||
|
||||
private String getSentFromToString(@NonNull Recipient from, @NonNull Recipient thread) {
|
||||
if (from.isLocalNumber() && from == thread) {
|
||||
return context.getString(R.string.note_to_self);
|
||||
}
|
||||
|
||||
if (showThread && (from.isLocalNumber() || thread.isGroup())) {
|
||||
if (from.isLocalNumber()) {
|
||||
return context.getString(R.string.MediaOverviewActivity_sent_by_you_to_s, thread.toShortString(context));
|
||||
} else {
|
||||
return context.getString(R.string.MediaOverviewActivity_sent_by_s_to_s, from.toShortString(context), thread.toShortString(context));
|
||||
}
|
||||
} else {
|
||||
if (from.isLocalNumber()) {
|
||||
return context.getString(R.string.MediaOverviewActivity_sent_by_you);
|
||||
} else {
|
||||
return context.getString(R.string.MediaOverviewActivity_sent_by_s, from.toShortString(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,13 +436,14 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
void detached() {
|
||||
void unbind() {
|
||||
audioView.stopPlaybackAndReset();
|
||||
super.unbind();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String describeUnnamedFile(@NonNull Context context, @NonNull Slide slide) {
|
||||
return context.getString(R.string.DocumentView_audio_file);
|
||||
protected String getFileTypeDescription(@NonNull Context context, @NonNull Slide slide) {
|
||||
return context.getString(R.string.MediaOverviewActivity_audio);
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
|
@ -377,15 +469,16 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected String describeUnnamedFile(@NonNull Context context, @NonNull Slide slide) {
|
||||
if (slide.hasVideo()) return context.getString(R.string.DocumentView_video_file);
|
||||
if (slide.hasImage()) return context.getString(R.string.DocumentView_image_file);
|
||||
return super.describeUnnamedFile(context, slide);
|
||||
protected String getFileTypeDescription(@NonNull Context context, @NonNull Slide slide) {
|
||||
if (slide.hasVideo()) return context.getString(R.string.MediaOverviewActivity_video);
|
||||
if (slide.hasImage()) return context.getString(R.string.MediaOverviewActivity_image);
|
||||
return super.getFileTypeDescription(context, slide);
|
||||
}
|
||||
|
||||
@Override
|
||||
void detached() {
|
||||
void unbind() {
|
||||
thumbnailView.clear(glideRequests);
|
||||
super.unbind();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,8 @@ public final class MediaOverviewPageFragment extends Fragment
|
|||
GlideApp.with(this),
|
||||
new GroupedThreadMediaLoader.EmptyGroupedThreadMedia(),
|
||||
this,
|
||||
sorting.isRelatedToFileSize());
|
||||
sorting.isRelatedToFileSize(),
|
||||
threadId == MediaDatabase.ALL_THREADS);
|
||||
this.recyclerView.setAdapter(adapter);
|
||||
this.recyclerView.setLayoutManager(gridManager);
|
||||
this.recyclerView.setHasFixedSize(true);
|
||||
|
@ -182,7 +183,16 @@ public final class MediaOverviewPageFragment extends Fragment
|
|||
int childCount = recyclerView.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
adapter.pause(recyclerView.getChildViewHolder(recyclerView.getChildAt(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
int childCount = recyclerView.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
adapter.detach(recyclerView.getChildViewHolder(recyclerView.getChildAt(i)));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMediaMultiSelectClick(@NonNull MediaDatabase.MediaRecord mediaRecord) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.text.TextUtils;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
|
@ -168,6 +169,10 @@ public final class LiveRecipient {
|
|||
set(recipient);
|
||||
}
|
||||
|
||||
public @NonNull LiveData<Recipient> getLiveData() {
|
||||
return liveData;
|
||||
}
|
||||
|
||||
private @NonNull Recipient fetchRecipientFromDisk(RecipientId id) {
|
||||
RecipientSettings settings = recipientDatabase.getRecipientSettings(id);
|
||||
RecipientDetails details = settings.getGroupId() != null ? getGroupRecipientDetails(settings)
|
||||
|
|
|
@ -4,7 +4,6 @@ import androidx.annotation.MainThread;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MediatorLiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.SavedStateHandle;
|
||||
import androidx.lifecycle.Transformations;
|
||||
|
@ -14,6 +13,7 @@ import org.thoughtcrime.securesms.logging.Log;
|
|||
import org.thoughtcrime.securesms.registration.service.RegistrationService;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataPair;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse;
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil;
|
||||
|
@ -201,27 +201,4 @@ public final class RegistrationViewModel extends ViewModel {
|
|||
}
|
||||
}, this::setKeyBackupCurrentToken);
|
||||
}
|
||||
|
||||
public static class LiveDataPair<A, B> extends MediatorLiveData<Pair<A, B>> {
|
||||
private A a;
|
||||
private B b;
|
||||
|
||||
public LiveDataPair(LiveData<A> ld1, LiveData<B> ld2) {
|
||||
setValue(new Pair<>(a, b));
|
||||
|
||||
addSource(ld1, (a) -> {
|
||||
if(a != null) {
|
||||
this.a = a;
|
||||
}
|
||||
setValue(new Pair<>(a, b));
|
||||
});
|
||||
|
||||
addSource(ld2, (b) -> {
|
||||
if(b != null) {
|
||||
this.b = b;
|
||||
}
|
||||
setValue(new Pair<>(a, b));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import androidx.annotation.NonNull;
|
|||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -136,6 +137,10 @@ public class DateUtils extends android.text.format.DateUtils {
|
|||
return getFormattedDateTime(timestamp, "EEE, MMM d, yyyy", locale);
|
||||
}
|
||||
|
||||
public static String formatDateWithoutDayOfWeek(@NonNull Locale locale, long timestamp) {
|
||||
return getFormattedDateTime(timestamp, "MMM d yyyy", locale);
|
||||
}
|
||||
|
||||
public static boolean isSameDay(long t1, long t2) {
|
||||
return DATE_FORMAT.format(new Date(t1)).equals(DATE_FORMAT.format(new Date(t2)));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package org.thoughtcrime.securesms.util.livedata;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MediatorLiveData;
|
||||
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
|
||||
public final class LiveDataPair<A, B> extends MediatorLiveData<Pair<A, B>> {
|
||||
private A a;
|
||||
private B b;
|
||||
|
||||
public LiveDataPair(@NonNull LiveData<A> liveDataA,
|
||||
@NonNull LiveData<B> liveDataB)
|
||||
{
|
||||
this(liveDataA, liveDataB, null, null);
|
||||
}
|
||||
|
||||
public LiveDataPair(@NonNull LiveData<A> liveDataA,
|
||||
@NonNull LiveData<B> liveDataB,
|
||||
@Nullable A initialA,
|
||||
@Nullable B initialB)
|
||||
{
|
||||
a = initialA;
|
||||
b = initialB;
|
||||
setValue(new Pair<>(a, b));
|
||||
|
||||
if (liveDataA == liveDataB) {
|
||||
|
||||
addSource(liveDataA, (a) -> {
|
||||
if (a != null) {
|
||||
this.a = a;
|
||||
//noinspection unchecked: A is B if live datas are same instance
|
||||
this.b = (B) a;
|
||||
}
|
||||
setValue(new Pair<>(a, b));
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
addSource(liveDataA, (a) -> {
|
||||
if (a != null) {
|
||||
this.a = a;
|
||||
}
|
||||
setValue(new Pair<>(a, b));
|
||||
});
|
||||
|
||||
addSource(liveDataB, (b) -> {
|
||||
if (b != null) {
|
||||
this.b = b;
|
||||
}
|
||||
setValue(new Pair<>(a, b));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue