2017-10-16 13:11:42 -07:00
|
|
|
/*
|
2014-08-12 12:11:23 -07:00
|
|
|
* Copyright (C) 2014 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;
|
|
|
|
|
2017-11-24 22:00:30 -08:00
|
|
|
import android.Manifest;
|
2018-01-04 11:11:49 -08:00
|
|
|
import android.annotation.SuppressLint;
|
|
|
|
import android.content.Context;
|
2015-02-10 01:46:43 -08:00
|
|
|
import android.content.Intent;
|
2018-01-04 11:11:49 -08:00
|
|
|
import android.database.Cursor;
|
2014-08-12 12:11:23 -07:00
|
|
|
import android.net.Uri;
|
2017-10-23 13:03:32 -07:00
|
|
|
import android.os.AsyncTask;
|
2014-08-12 12:11:23 -07:00
|
|
|
import android.os.Bundle;
|
2014-06-28 20:40:57 -07:00
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuInflater;
|
|
|
|
import android.view.MenuItem;
|
2014-08-12 12:11:23 -07:00
|
|
|
import android.view.View;
|
2018-01-04 11:11:49 -08:00
|
|
|
import android.view.ViewGroup;
|
2019-08-30 17:31:59 -04:00
|
|
|
import android.view.Window;
|
2014-08-12 12:11:23 -07:00
|
|
|
import android.view.WindowManager;
|
2018-11-08 23:33:37 -08:00
|
|
|
import android.widget.TextView;
|
2014-08-12 12:11:23 -07:00
|
|
|
import android.widget.Toast;
|
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.appcompat.app.AlertDialog;
|
|
|
|
import androidx.core.util.Pair;
|
2019-08-30 17:31:59 -04:00
|
|
|
import androidx.core.view.ViewCompat;
|
2019-07-19 11:43:55 -04:00
|
|
|
import androidx.fragment.app.Fragment;
|
|
|
|
import androidx.fragment.app.FragmentManager;
|
|
|
|
import androidx.fragment.app.FragmentStatePagerAdapter;
|
|
|
|
import androidx.lifecycle.ViewModelProviders;
|
|
|
|
import androidx.loader.app.LoaderManager;
|
|
|
|
import androidx.loader.content.Loader;
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import androidx.viewpager.widget.ViewPager;
|
|
|
|
|
2019-07-30 14:25:35 -04:00
|
|
|
import org.thoughtcrime.securesms.animation.DepthPageTransformer;
|
2018-03-13 18:24:42 -07:00
|
|
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
2018-01-04 11:11:49 -08:00
|
|
|
import org.thoughtcrime.securesms.components.viewpager.ExtendedOnPageChangedListener;
|
2019-07-19 11:43:55 -04:00
|
|
|
import org.thoughtcrime.securesms.database.MediaDatabase;
|
2018-01-04 11:11:49 -08:00
|
|
|
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
|
|
|
|
import org.thoughtcrime.securesms.database.loaders.PagingMediaLoader;
|
2019-05-02 11:36:20 -03:00
|
|
|
import org.thoughtcrime.securesms.logging.Log;
|
2019-12-03 11:05:03 -05:00
|
|
|
import org.thoughtcrime.securesms.mediaoverview.MediaOverviewActivity;
|
2019-07-19 11:43:55 -04:00
|
|
|
import org.thoughtcrime.securesms.mediapreview.MediaPreviewFragment;
|
2018-11-08 23:33:37 -08:00
|
|
|
import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel;
|
2019-05-02 11:36:20 -03:00
|
|
|
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter;
|
2017-10-16 13:11:42 -07:00
|
|
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
2017-11-24 22:00:30 -08:00
|
|
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
2014-08-12 12:11:23 -07:00
|
|
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
2019-08-07 14:22:51 -04:00
|
|
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
2020-02-05 16:34:54 -05:00
|
|
|
import org.thoughtcrime.securesms.sharing.ShareActivity;
|
2018-03-15 11:17:40 -07:00
|
|
|
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
2014-08-12 12:11:23 -07:00
|
|
|
import org.thoughtcrime.securesms.util.DateUtils;
|
|
|
|
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
|
|
|
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment;
|
2016-11-26 12:10:14 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Locale;
|
|
|
|
import java.util.Map;
|
2014-08-12 12:11:23 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Activity for displaying media attachments in-app
|
|
|
|
*/
|
2019-07-19 11:43:55 -04:00
|
|
|
public final class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
2019-08-07 14:22:51 -04:00
|
|
|
implements LoaderManager.LoaderCallbacks<Pair<Cursor, Integer>>,
|
2019-07-19 11:43:55 -04:00
|
|
|
MediaRailAdapter.RailItemListener,
|
|
|
|
MediaPreviewFragment.Events
|
2018-11-08 23:33:37 -08:00
|
|
|
{
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2014-08-12 12:11:23 -07:00
|
|
|
private final static String TAG = MediaPreviewActivity.class.getSimpleName();
|
|
|
|
|
2019-12-03 11:05:03 -05:00
|
|
|
private static final int NOT_IN_A_THREAD = -2;
|
|
|
|
|
|
|
|
public static final String THREAD_ID_EXTRA = "thread_id";
|
2018-01-23 12:39:30 -08:00
|
|
|
public static final String DATE_EXTRA = "date";
|
|
|
|
public static final String SIZE_EXTRA = "size";
|
2018-11-08 23:33:37 -08:00
|
|
|
public static final String CAPTION_EXTRA = "caption";
|
2018-01-23 12:39:30 -08:00
|
|
|
public static final String LEFT_IS_RECENT_EXTRA = "left_is_recent";
|
2019-12-03 11:05:03 -05:00
|
|
|
public static final String HIDE_ALL_MEDIA_EXTRA = "came_from_all_media";
|
|
|
|
public static final String SHOW_THREAD_EXTRA = "show_thread";
|
|
|
|
public static final String SORTING_EXTRA = "sorting";
|
2014-08-12 12:11:23 -07:00
|
|
|
|
2018-11-08 23:33:37 -08:00
|
|
|
private ViewPager mediaPager;
|
|
|
|
private View detailsContainer;
|
|
|
|
private TextView caption;
|
|
|
|
private View captionContainer;
|
|
|
|
private RecyclerView albumRail;
|
2018-11-20 09:59:23 -08:00
|
|
|
private MediaRailAdapter albumRailAdapter;
|
2018-11-08 23:33:37 -08:00
|
|
|
private ViewGroup playbackControlsContainer;
|
|
|
|
private Uri initialMediaUri;
|
|
|
|
private String initialMediaType;
|
|
|
|
private long initialMediaSize;
|
|
|
|
private String initialCaption;
|
|
|
|
private boolean leftIsRecent;
|
|
|
|
private MediaPreviewViewModel viewModel;
|
2019-05-02 11:36:20 -03:00
|
|
|
private ViewPagerListener viewPagerListener;
|
2014-08-12 12:11:23 -07:00
|
|
|
|
2019-12-03 11:05:03 -05:00
|
|
|
private int restartItem = -1;
|
|
|
|
private long threadId = NOT_IN_A_THREAD;
|
|
|
|
private boolean cameFromAllMedia;
|
|
|
|
private boolean showThread;
|
|
|
|
private MediaDatabase.Sorting sorting;
|
2018-01-16 12:06:55 -08:00
|
|
|
|
2018-01-04 11:11:49 -08:00
|
|
|
@SuppressWarnings("ConstantConditions")
|
2014-08-12 12:11:23 -07:00
|
|
|
@Override
|
2018-02-01 19:22:48 -08:00
|
|
|
protected void onCreate(Bundle bundle, boolean ready) {
|
2019-08-30 17:31:59 -04:00
|
|
|
this.setTheme(R.style.TextSecure_MediaPreview);
|
|
|
|
setContentView(R.layout.media_preview_activity);
|
|
|
|
|
|
|
|
setSupportActionBar(findViewById(R.id.toolbar));
|
2014-11-25 08:55:10 +02:00
|
|
|
|
2018-11-08 23:33:37 -08:00
|
|
|
viewModel = ViewModelProviders.of(this).get(MediaPreviewViewModel.class);
|
|
|
|
|
2014-08-12 12:11:23 -07:00
|
|
|
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
|
|
|
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
2014-11-25 08:55:10 +02:00
|
|
|
|
2019-08-30 17:31:59 -04:00
|
|
|
showSystemUI();
|
|
|
|
|
2014-08-12 12:11:23 -07:00
|
|
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
2014-11-25 08:55:10 +02:00
|
|
|
|
2015-02-10 01:46:43 -08:00
|
|
|
initializeViews();
|
2014-08-12 12:11:23 -07:00
|
|
|
initializeResources();
|
2018-11-08 23:33:37 -08:00
|
|
|
initializeObservers();
|
|
|
|
}
|
|
|
|
|
2017-11-24 22:00:30 -08:00
|
|
|
@Override
|
|
|
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
|
|
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
|
|
|
}
|
|
|
|
|
2018-11-08 23:33:37 -08:00
|
|
|
@Override
|
|
|
|
public void onRailItemClicked(int distanceFromActive) {
|
|
|
|
mediaPager.setCurrentItem(mediaPager.getCurrentItem() + distanceFromActive);
|
|
|
|
}
|
|
|
|
|
2018-11-20 09:59:23 -08:00
|
|
|
@Override
|
|
|
|
public void onRailItemDeleteClicked(int distanceFromActive) {
|
|
|
|
throw new UnsupportedOperationException("Callback unsupported.");
|
|
|
|
}
|
|
|
|
|
2018-01-04 11:11:49 -08:00
|
|
|
@SuppressWarnings("ConstantConditions")
|
2015-02-10 01:46:43 -08:00
|
|
|
private void initializeActionBar() {
|
2018-01-04 11:11:49 -08:00
|
|
|
MediaItem mediaItem = getCurrentMediaItem();
|
2017-10-04 11:35:16 -07:00
|
|
|
|
2018-01-04 11:11:49 -08:00
|
|
|
if (mediaItem != null) {
|
2019-12-03 11:05:03 -05:00
|
|
|
getSupportActionBar().setTitle(getTitleText(mediaItem));
|
|
|
|
getSupportActionBar().setSubtitle(getSubTitleText(mediaItem));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private @NonNull String getTitleText(@NonNull MediaItem mediaItem) {
|
|
|
|
String from;
|
|
|
|
if (mediaItem.outgoing) from = getString(R.string.MediaPreviewActivity_you);
|
|
|
|
else if (mediaItem.recipient != null) from = mediaItem.recipient.toShortString(this);
|
|
|
|
else from = "";
|
|
|
|
|
|
|
|
if (showThread) {
|
|
|
|
String to = null;
|
|
|
|
Recipient threadRecipient = mediaItem.threadRecipient;
|
|
|
|
|
|
|
|
if (threadRecipient != null) {
|
|
|
|
if (mediaItem.outgoing || threadRecipient.isGroup()) {
|
|
|
|
if (threadRecipient.isLocalNumber()) {
|
|
|
|
from = getString(R.string.note_to_self);
|
|
|
|
} else {
|
|
|
|
to = threadRecipient.toShortString(this);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
to = getString(R.string.MediaPreviewActivity_you);
|
|
|
|
}
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
2019-12-03 11:05:03 -05:00
|
|
|
return to != null ? getString(R.string.MediaPreviewActivity_s_to_s, from, to)
|
|
|
|
: from;
|
|
|
|
} else {
|
|
|
|
return from;
|
|
|
|
}
|
|
|
|
}
|
2017-10-04 11:35:16 -07:00
|
|
|
|
2019-12-03 11:05:03 -05:00
|
|
|
private @NonNull String getSubTitleText(@NonNull MediaItem mediaItem) {
|
|
|
|
if (mediaItem.date > 0) {
|
|
|
|
return DateUtils.getExtendedRelativeTimeSpanString(this, Locale.getDefault(), mediaItem.date);
|
|
|
|
} else {
|
|
|
|
return getString(R.string.MediaPreviewActivity_draft);
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
2015-02-10 01:46:43 -08:00
|
|
|
}
|
|
|
|
|
2014-08-12 12:11:23 -07:00
|
|
|
@Override
|
|
|
|
public void onResume() {
|
|
|
|
super.onResume();
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2015-02-10 01:46:43 -08:00
|
|
|
initializeMedia();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPause() {
|
|
|
|
super.onPause();
|
2018-01-16 12:06:55 -08:00
|
|
|
restartItem = cleanupMedia();
|
2015-02-10 01:46:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onNewIntent(Intent intent) {
|
|
|
|
super.onNewIntent(intent);
|
|
|
|
setIntent(intent);
|
|
|
|
initializeResources();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initializeViews() {
|
2018-01-04 11:11:49 -08:00
|
|
|
mediaPager = findViewById(R.id.media_pager);
|
|
|
|
mediaPager.setOffscreenPageLimit(1);
|
2019-07-30 14:25:35 -04:00
|
|
|
mediaPager.setPageTransformer(true, new DepthPageTransformer());
|
2019-05-02 11:36:20 -03:00
|
|
|
|
|
|
|
viewPagerListener = new ViewPagerListener();
|
|
|
|
mediaPager.addOnPageChangeListener(viewPagerListener);
|
2018-11-08 23:33:37 -08:00
|
|
|
|
|
|
|
albumRail = findViewById(R.id.media_preview_album_rail);
|
2018-11-20 09:59:23 -08:00
|
|
|
albumRailAdapter = new MediaRailAdapter(GlideApp.with(this), this, false);
|
2018-11-08 23:33:37 -08:00
|
|
|
|
|
|
|
albumRail.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
|
|
|
|
albumRail.setAdapter(albumRailAdapter);
|
|
|
|
|
|
|
|
detailsContainer = findViewById(R.id.media_preview_details_container);
|
|
|
|
caption = findViewById(R.id.media_preview_caption);
|
|
|
|
captionContainer = findViewById(R.id.media_preview_caption_container);
|
|
|
|
playbackControlsContainer = findViewById(R.id.media_preview_playback_controls_container);
|
2019-08-30 17:31:59 -04:00
|
|
|
|
|
|
|
View toolbarLayout = findViewById(R.id.toolbar_layout);
|
|
|
|
|
|
|
|
anchorMarginsToBottomInsets(detailsContainer);
|
|
|
|
|
|
|
|
anchorMarginsToTopInsets(toolbarLayout);
|
|
|
|
|
|
|
|
showAndHideWithSystemUI(getWindow(), detailsContainer, toolbarLayout);
|
2015-02-10 01:46:43 -08:00
|
|
|
}
|
2014-08-12 12:11:23 -07:00
|
|
|
|
2015-02-10 01:46:43 -08:00
|
|
|
private void initializeResources() {
|
2019-12-03 11:05:03 -05:00
|
|
|
Intent intent = getIntent();
|
|
|
|
|
|
|
|
threadId = intent.getLongExtra(THREAD_ID_EXTRA, NOT_IN_A_THREAD);
|
|
|
|
cameFromAllMedia = intent.getBooleanExtra(HIDE_ALL_MEDIA_EXTRA, false);
|
|
|
|
showThread = intent.getBooleanExtra(SHOW_THREAD_EXTRA, false);
|
|
|
|
sorting = MediaDatabase.Sorting.values()[intent.getIntExtra(SORTING_EXTRA, 0)];
|
|
|
|
|
|
|
|
initialMediaUri = intent.getData();
|
|
|
|
initialMediaType = intent.getType();
|
|
|
|
initialMediaSize = intent.getLongExtra(SIZE_EXTRA, 0);
|
|
|
|
initialCaption = intent.getStringExtra(CAPTION_EXTRA);
|
|
|
|
leftIsRecent = intent.getBooleanExtra(LEFT_IS_RECENT_EXTRA, false);
|
2018-01-16 12:06:55 -08:00
|
|
|
restartItem = -1;
|
2015-02-10 01:46:43 -08:00
|
|
|
}
|
2014-12-24 14:48:04 -08:00
|
|
|
|
2018-11-08 23:33:37 -08:00
|
|
|
private void initializeObservers() {
|
|
|
|
viewModel.getPreviewData().observe(this, previewData -> {
|
2018-11-27 09:32:56 -08:00
|
|
|
if (previewData == null || mediaPager == null || mediaPager.getAdapter() == null) {
|
2018-11-08 23:33:37 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-10-23 14:36:50 -07:00
|
|
|
if (!((MediaItemAdapter) mediaPager.getAdapter()).hasFragmentFor(mediaPager.getCurrentItem())) {
|
|
|
|
Log.d(TAG, "MediaItemAdapter wasn't ready. Posting again...");
|
|
|
|
viewModel.resubmitPreviewData();
|
|
|
|
}
|
|
|
|
|
2018-11-08 23:33:37 -08:00
|
|
|
View playbackControls = ((MediaItemAdapter) mediaPager.getAdapter()).getPlaybackControls(mediaPager.getCurrentItem());
|
|
|
|
|
|
|
|
if (previewData.getAlbumThumbnails().isEmpty() && previewData.getCaption() == null && playbackControls == null) {
|
|
|
|
detailsContainer.setVisibility(View.GONE);
|
|
|
|
} else {
|
|
|
|
detailsContainer.setVisibility(View.VISIBLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
albumRail.setVisibility(previewData.getAlbumThumbnails().isEmpty() ? View.GONE : View.VISIBLE);
|
2018-11-20 09:59:23 -08:00
|
|
|
albumRailAdapter.setMedia(previewData.getAlbumThumbnails(), previewData.getActivePosition());
|
2018-11-08 23:33:37 -08:00
|
|
|
albumRail.smoothScrollToPosition(previewData.getActivePosition());
|
|
|
|
|
|
|
|
captionContainer.setVisibility(previewData.getCaption() == null ? View.GONE : View.VISIBLE);
|
|
|
|
caption.setText(previewData.getCaption());
|
|
|
|
|
|
|
|
if (playbackControls != null) {
|
|
|
|
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
|
|
playbackControls.setLayoutParams(params);
|
|
|
|
|
|
|
|
playbackControlsContainer.removeAllViews();
|
|
|
|
playbackControlsContainer.addView(playbackControls);
|
|
|
|
} else {
|
|
|
|
playbackControlsContainer.removeAllViews();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-02-10 01:46:43 -08:00
|
|
|
private void initializeMedia() {
|
2018-01-04 11:11:49 -08:00
|
|
|
if (!isContentTypeSupported(initialMediaType)) {
|
2014-08-12 12:11:23 -07:00
|
|
|
Log.w(TAG, "Unsupported media type sent to MediaPreviewActivity, finishing.");
|
2014-12-15 09:44:41 -05:00
|
|
|
Toast.makeText(getApplicationContext(), R.string.MediaPreviewActivity_unssuported_media_type, Toast.LENGTH_LONG).show();
|
2014-08-12 12:11:23 -07:00
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
2018-08-02 09:25:33 -04:00
|
|
|
Log.i(TAG, "Loading Part URI: " + initialMediaUri);
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-12-03 11:05:03 -05:00
|
|
|
if (isMediaInDb()) {
|
2019-07-19 11:43:55 -04:00
|
|
|
LoaderManager.getInstance(this).restartLoader(0, null, this);
|
2018-01-04 11:11:49 -08:00
|
|
|
} else {
|
2019-07-19 11:43:55 -04:00
|
|
|
mediaPager.setAdapter(new SingleItemPagerAdapter(getSupportFragmentManager(), initialMediaUri, initialMediaType, initialMediaSize));
|
2018-11-08 23:33:37 -08:00
|
|
|
|
|
|
|
if (initialCaption != null) {
|
|
|
|
detailsContainer.setVisibility(View.VISIBLE);
|
|
|
|
captionContainer.setVisibility(View.VISIBLE);
|
|
|
|
caption.setText(initialCaption);
|
|
|
|
}
|
2014-08-12 12:11:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-16 12:06:55 -08:00
|
|
|
private int cleanupMedia() {
|
|
|
|
int restartItem = mediaPager.getCurrentItem();
|
|
|
|
|
2018-01-04 11:11:49 -08:00
|
|
|
mediaPager.removeAllViews();
|
|
|
|
mediaPager.setAdapter(null);
|
2018-01-16 12:06:55 -08:00
|
|
|
|
|
|
|
return restartItem;
|
2014-12-24 14:48:04 -08:00
|
|
|
}
|
|
|
|
|
2016-09-20 18:53:44 +02:00
|
|
|
private void showOverview() {
|
2019-12-03 11:05:03 -05:00
|
|
|
startActivity(MediaOverviewActivity.forThread(this, threadId));
|
2016-09-20 18:53:44 +02:00
|
|
|
}
|
|
|
|
|
2016-11-03 00:03:03 +01:00
|
|
|
private void forward() {
|
2018-01-04 11:11:49 -08:00
|
|
|
MediaItem mediaItem = getCurrentMediaItem();
|
|
|
|
|
|
|
|
if (mediaItem != null) {
|
|
|
|
Intent composeIntent = new Intent(this, ShareActivity.class);
|
|
|
|
composeIntent.putExtra(Intent.EXTRA_STREAM, mediaItem.uri);
|
|
|
|
composeIntent.setType(mediaItem.type);
|
|
|
|
startActivity(composeIntent);
|
|
|
|
}
|
2016-11-03 00:03:03 +01:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:11:49 -08:00
|
|
|
@SuppressWarnings("CodeBlock2Expr")
|
|
|
|
@SuppressLint("InlinedApi")
|
2014-08-12 12:11:23 -07:00
|
|
|
private void saveToDisk() {
|
2018-01-04 11:11:49 -08:00
|
|
|
MediaItem mediaItem = getCurrentMediaItem();
|
|
|
|
|
|
|
|
if (mediaItem != null) {
|
|
|
|
SaveAttachmentTask.showWarningDialog(this, (dialogInterface, i) -> {
|
|
|
|
Permissions.with(this)
|
|
|
|
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
|
|
|
|
.ifNecessary()
|
|
|
|
.withPermanentDenialDialog(getString(R.string.MediaPreviewActivity_signal_needs_the_storage_permission_in_order_to_write_to_external_storage_but_it_has_been_permanently_denied))
|
|
|
|
.onAnyDenied(() -> Toast.makeText(this, R.string.MediaPreviewActivity_unable_to_write_to_external_storage_without_permission, Toast.LENGTH_LONG).show())
|
|
|
|
.onAllGranted(() -> {
|
2018-01-24 19:17:44 -08:00
|
|
|
SaveAttachmentTask saveTask = new SaveAttachmentTask(MediaPreviewActivity.this);
|
2018-01-04 11:11:49 -08:00
|
|
|
long saveDate = (mediaItem.date > 0) ? mediaItem.date : System.currentTimeMillis();
|
|
|
|
saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, null));
|
|
|
|
})
|
|
|
|
.execute();
|
|
|
|
});
|
|
|
|
}
|
2014-08-12 12:11:23 -07:00
|
|
|
}
|
|
|
|
|
2018-03-13 18:24:42 -07:00
|
|
|
@SuppressLint("StaticFieldLeak")
|
|
|
|
private void deleteMedia() {
|
|
|
|
MediaItem mediaItem = getCurrentMediaItem();
|
|
|
|
if (mediaItem == null || mediaItem.attachment == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
builder.setIconAttribute(R.attr.dialog_alert_icon);
|
|
|
|
builder.setTitle(R.string.MediaPreviewActivity_media_delete_confirmation_title);
|
|
|
|
builder.setMessage(R.string.MediaPreviewActivity_media_delete_confirmation_message);
|
|
|
|
builder.setCancelable(true);
|
|
|
|
|
|
|
|
builder.setPositiveButton(R.string.delete, (dialogInterface, which) -> {
|
|
|
|
new AsyncTask<Void, Void, Void>() {
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground(Void... voids) {
|
2018-03-15 11:17:40 -07:00
|
|
|
AttachmentUtil.deleteAttachment(MediaPreviewActivity.this.getApplicationContext(),
|
|
|
|
mediaItem.attachment);
|
2018-03-13 18:24:42 -07:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
|
|
|
|
finish();
|
|
|
|
});
|
|
|
|
builder.setNegativeButton(android.R.string.cancel, null);
|
|
|
|
builder.show();
|
|
|
|
}
|
|
|
|
|
2014-08-12 12:11:23 -07:00
|
|
|
@Override
|
|
|
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
|
|
super.onPrepareOptionsMenu(menu);
|
|
|
|
|
|
|
|
menu.clear();
|
2014-06-28 20:40:57 -07:00
|
|
|
MenuInflater inflater = this.getMenuInflater();
|
2014-08-12 12:11:23 -07:00
|
|
|
inflater.inflate(R.menu.media_preview, menu);
|
2018-03-13 18:24:42 -07:00
|
|
|
|
|
|
|
if (!isMediaInDb()) {
|
|
|
|
menu.findItem(R.id.media_preview__overview).setVisible(false);
|
|
|
|
menu.findItem(R.id.delete).setVisible(false);
|
|
|
|
}
|
2014-08-12 12:11:23 -07:00
|
|
|
|
2019-12-03 11:05:03 -05:00
|
|
|
if (cameFromAllMedia) {
|
|
|
|
menu.findItem(R.id.media_preview__overview).setVisible(false);
|
|
|
|
}
|
|
|
|
|
2014-08-12 12:11:23 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
super.onOptionsItemSelected(item);
|
|
|
|
|
|
|
|
switch (item.getItemId()) {
|
2016-09-20 18:53:44 +02:00
|
|
|
case R.id.media_preview__overview: showOverview(); return true;
|
|
|
|
case R.id.media_preview__forward: forward(); return true;
|
|
|
|
case R.id.save: saveToDisk(); return true;
|
2018-03-13 18:24:42 -07:00
|
|
|
case R.id.delete: deleteMedia(); return true;
|
2016-09-20 18:53:44 +02:00
|
|
|
case android.R.id.home: finish(); return true;
|
2014-08-12 12:11:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-03-13 18:24:42 -07:00
|
|
|
private boolean isMediaInDb() {
|
2019-12-03 11:05:03 -05:00
|
|
|
return threadId != NOT_IN_A_THREAD;
|
2018-03-13 18:24:42 -07:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:11:49 -08:00
|
|
|
private @Nullable MediaItem getCurrentMediaItem() {
|
|
|
|
MediaItemAdapter adapter = (MediaItemAdapter)mediaPager.getAdapter();
|
|
|
|
|
|
|
|
if (adapter != null) {
|
|
|
|
return adapter.getMediaItemFor(mediaPager.getCurrentItem());
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-12 12:11:23 -07:00
|
|
|
public static boolean isContentTypeSupported(final String contentType) {
|
2016-11-26 12:10:14 -08:00
|
|
|
return contentType != null && (contentType.startsWith("image/") || contentType.startsWith("video/"));
|
2014-08-12 12:11:23 -07:00
|
|
|
}
|
2018-01-04 11:11:49 -08:00
|
|
|
|
|
|
|
@Override
|
2019-05-22 13:51:56 -03:00
|
|
|
public @NonNull Loader<Pair<Cursor, Integer>> onCreateLoader(int id, Bundle args) {
|
2019-12-03 11:05:03 -05:00
|
|
|
return new PagingMediaLoader(this, threadId, initialMediaUri, leftIsRecent, sorting);
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-05-22 13:51:56 -03:00
|
|
|
public void onLoadFinished(@NonNull Loader<Pair<Cursor, Integer>> loader, @Nullable Pair<Cursor, Integer> data) {
|
2018-01-04 11:11:49 -08:00
|
|
|
if (data != null) {
|
|
|
|
@SuppressWarnings("ConstantConditions")
|
2019-07-19 11:43:55 -04:00
|
|
|
CursorPagerAdapter adapter = new CursorPagerAdapter(getSupportFragmentManager(),this, data.first, data.second, leftIsRecent);
|
2018-01-04 11:11:49 -08:00
|
|
|
mediaPager.setAdapter(adapter);
|
|
|
|
adapter.setActive(true);
|
2018-01-16 12:06:55 -08:00
|
|
|
|
2019-10-23 14:36:50 -07:00
|
|
|
viewModel.setCursor(this, data.first, leftIsRecent);
|
2019-05-02 11:36:20 -03:00
|
|
|
|
2019-10-23 14:36:50 -07:00
|
|
|
int item = restartItem >= 0 ? restartItem : data.second;
|
|
|
|
mediaPager.setCurrentItem(item);
|
2019-10-17 19:44:27 -04:00
|
|
|
|
2019-10-23 14:36:50 -07:00
|
|
|
if (item == 0) {
|
|
|
|
viewPagerListener.onPageSelected(0);
|
|
|
|
}
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-05-22 13:51:56 -03:00
|
|
|
public void onLoaderReset(@NonNull Loader<Pair<Cursor, Integer>> loader) {
|
2018-01-04 11:11:49 -08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
@Override
|
|
|
|
public boolean singleTapOnMedia() {
|
2019-08-30 17:31:59 -04:00
|
|
|
toggleUiVisibility();
|
2019-07-19 11:43:55 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-08-30 17:31:59 -04:00
|
|
|
private void toggleUiVisibility() {
|
|
|
|
int systemUiVisibility = getWindow().getDecorView().getSystemUiVisibility();
|
|
|
|
if ((systemUiVisibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) {
|
|
|
|
showSystemUI();
|
|
|
|
} else {
|
|
|
|
hideSystemUI();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void hideSystemUI() {
|
|
|
|
getWindow().getDecorView().setSystemUiVisibility(
|
|
|
|
View.SYSTEM_UI_FLAG_IMMERSIVE |
|
|
|
|
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
|
|
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
|
|
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
|
|
|
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
|
|
|
View.SYSTEM_UI_FLAG_FULLSCREEN );
|
|
|
|
}
|
|
|
|
|
|
|
|
private void showSystemUI() {
|
|
|
|
getWindow().getDecorView().setSystemUiVisibility(
|
|
|
|
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
|
|
|
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
|
|
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN );
|
|
|
|
}
|
|
|
|
|
2018-01-04 11:11:49 -08:00
|
|
|
private class ViewPagerListener extends ExtendedOnPageChangedListener {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPageSelected(int position) {
|
|
|
|
super.onPageSelected(position);
|
|
|
|
|
|
|
|
MediaItemAdapter adapter = (MediaItemAdapter)mediaPager.getAdapter();
|
|
|
|
|
|
|
|
if (adapter != null) {
|
|
|
|
MediaItem item = adapter.getMediaItemFor(position);
|
2019-08-07 14:22:51 -04:00
|
|
|
if (item.recipient != null) item.recipient.live().observe(MediaPreviewActivity.this, r -> initializeActionBar());
|
2018-11-08 23:33:37 -08:00
|
|
|
viewModel.setActiveAlbumRailItem(MediaPreviewActivity.this, position);
|
2018-01-04 11:11:49 -08:00
|
|
|
initializeActionBar();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPageUnselected(int position) {
|
|
|
|
MediaItemAdapter adapter = (MediaItemAdapter)mediaPager.getAdapter();
|
|
|
|
|
|
|
|
if (adapter != null) {
|
|
|
|
MediaItem item = adapter.getMediaItemFor(position);
|
2019-08-07 14:22:51 -04:00
|
|
|
if (item.recipient != null) item.recipient.live().removeObservers(MediaPreviewActivity.this);
|
2018-01-04 11:11:49 -08:00
|
|
|
|
|
|
|
adapter.pause(position);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
private static class SingleItemPagerAdapter extends FragmentStatePagerAdapter implements MediaItemAdapter {
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
private final Uri uri;
|
|
|
|
private final String mediaType;
|
|
|
|
private final long size;
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
private MediaPreviewFragment mediaPreviewFragment;
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
SingleItemPagerAdapter(@NonNull FragmentManager fragmentManager,
|
|
|
|
@NonNull Uri uri,
|
|
|
|
@NonNull String mediaType,
|
2018-01-24 19:17:44 -08:00
|
|
|
long size)
|
2018-01-04 11:11:49 -08:00
|
|
|
{
|
2019-07-19 11:43:55 -04:00
|
|
|
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
|
|
|
this.uri = uri;
|
|
|
|
this.mediaType = mediaType;
|
|
|
|
this.size = size;
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getCount() {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
@NonNull
|
2018-01-04 11:11:49 -08:00
|
|
|
@Override
|
2019-07-19 11:43:55 -04:00
|
|
|
public Fragment getItem(int position) {
|
|
|
|
mediaPreviewFragment = MediaPreviewFragment.newInstance(uri, mediaType, size, true);
|
|
|
|
return mediaPreviewFragment;
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
2019-07-19 11:43:55 -04:00
|
|
|
if (mediaPreviewFragment != null) {
|
|
|
|
mediaPreviewFragment.cleanUp();
|
|
|
|
mediaPreviewFragment = null;
|
|
|
|
}
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public MediaItem getMediaItemFor(int position) {
|
2019-12-03 11:05:03 -05:00
|
|
|
return new MediaItem(null, null, null, uri, mediaType, -1, true);
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void pause(int position) {
|
2019-07-19 11:43:55 -04:00
|
|
|
if (mediaPreviewFragment != null) {
|
|
|
|
mediaPreviewFragment.pause();
|
|
|
|
}
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
2018-11-08 23:33:37 -08:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public @Nullable View getPlaybackControls(int position) {
|
2019-07-19 11:43:55 -04:00
|
|
|
if (mediaPreviewFragment != null) {
|
|
|
|
return mediaPreviewFragment.getPlaybackControls();
|
|
|
|
}
|
2018-11-08 23:33:37 -08:00
|
|
|
return null;
|
|
|
|
}
|
2019-10-23 14:36:50 -07:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean hasFragmentFor(int position) {
|
|
|
|
return mediaPreviewFragment != null;
|
|
|
|
}
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
2019-08-30 17:31:59 -04:00
|
|
|
private static void anchorMarginsToBottomInsets(@NonNull View viewToAnchor) {
|
|
|
|
ViewCompat.setOnApplyWindowInsetsListener(viewToAnchor, (view, insets) -> {
|
|
|
|
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
|
|
|
|
|
|
|
|
layoutParams.setMargins(insets.getSystemWindowInsetLeft(),
|
|
|
|
layoutParams.topMargin,
|
|
|
|
insets.getSystemWindowInsetRight(),
|
|
|
|
insets.getSystemWindowInsetBottom());
|
|
|
|
|
|
|
|
view.setLayoutParams(layoutParams);
|
|
|
|
|
|
|
|
return insets;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void anchorMarginsToTopInsets(@NonNull View viewToAnchor) {
|
|
|
|
ViewCompat.setOnApplyWindowInsetsListener(viewToAnchor, (view, insets) -> {
|
|
|
|
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
|
|
|
|
|
|
|
|
layoutParams.setMargins(insets.getSystemWindowInsetLeft(),
|
|
|
|
insets.getSystemWindowInsetTop(),
|
|
|
|
insets.getSystemWindowInsetRight(),
|
|
|
|
layoutParams.bottomMargin);
|
|
|
|
|
|
|
|
view.setLayoutParams(layoutParams);
|
|
|
|
|
|
|
|
return insets;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void showAndHideWithSystemUI(@NonNull Window window, @NonNull View... views) {
|
|
|
|
window.getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> {
|
|
|
|
boolean hide = (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
|
|
|
|
|
|
|
|
for (View view : views) {
|
|
|
|
view.animate()
|
|
|
|
.alpha(hide ? 0 : 1)
|
|
|
|
.start();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
private static class CursorPagerAdapter extends FragmentStatePagerAdapter implements MediaItemAdapter {
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
@SuppressLint("UseSparseArrays")
|
|
|
|
private final Map<Integer, MediaPreviewFragment> mediaFragments = new HashMap<>();
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
private final Context context;
|
|
|
|
private final Cursor cursor;
|
|
|
|
private final boolean leftIsRecent;
|
2018-01-04 11:11:49 -08:00
|
|
|
|
|
|
|
private boolean active;
|
|
|
|
private int autoPlayPosition;
|
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
CursorPagerAdapter(@NonNull FragmentManager fragmentManager,
|
|
|
|
@NonNull Context context,
|
|
|
|
@NonNull Cursor cursor,
|
|
|
|
int autoPlayPosition,
|
2018-01-24 19:17:44 -08:00
|
|
|
boolean leftIsRecent)
|
2018-01-04 11:11:49 -08:00
|
|
|
{
|
2019-07-19 11:43:55 -04:00
|
|
|
super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
2018-01-04 11:11:49 -08:00
|
|
|
this.context = context.getApplicationContext();
|
|
|
|
this.cursor = cursor;
|
|
|
|
this.autoPlayPosition = autoPlayPosition;
|
2018-01-23 12:39:30 -08:00
|
|
|
this.leftIsRecent = leftIsRecent;
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setActive(boolean active) {
|
|
|
|
this.active = active;
|
|
|
|
notifyDataSetChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getCount() {
|
|
|
|
if (!active) return 0;
|
|
|
|
else return cursor.getCount();
|
|
|
|
}
|
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
@NonNull
|
2018-01-04 11:11:49 -08:00
|
|
|
@Override
|
2019-07-19 11:43:55 -04:00
|
|
|
public Fragment getItem(int position) {
|
|
|
|
boolean autoPlay = autoPlayPosition == position;
|
|
|
|
int cursorPosition = getCursorPosition(position);
|
2018-01-04 11:11:49 -08:00
|
|
|
|
|
|
|
autoPlayPosition = -1;
|
|
|
|
|
2018-01-23 12:39:30 -08:00
|
|
|
cursor.moveToPosition(cursorPosition);
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
MediaDatabase.MediaRecord mediaRecord = MediaDatabase.MediaRecord.from(context, cursor);
|
|
|
|
DatabaseAttachment attachment = mediaRecord.getAttachment();
|
|
|
|
MediaPreviewFragment fragment = MediaPreviewFragment.newInstance(attachment, autoPlay);
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
mediaFragments.put(position, fragment);
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
return fragment;
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
2019-07-19 11:43:55 -04:00
|
|
|
MediaPreviewFragment removed = mediaFragments.remove(position);
|
|
|
|
|
|
|
|
if (removed != null) {
|
|
|
|
removed.cleanUp();
|
|
|
|
}
|
2018-01-04 11:11:49 -08:00
|
|
|
|
2019-07-19 11:43:55 -04:00
|
|
|
super.destroyItem(container, position, object);
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public MediaItem getMediaItemFor(int position) {
|
2018-01-23 12:39:30 -08:00
|
|
|
cursor.moveToPosition(getCursorPosition(position));
|
2019-12-03 11:05:03 -05:00
|
|
|
|
|
|
|
MediaRecord mediaRecord = MediaRecord.from(context, cursor);
|
|
|
|
RecipientId recipientId = mediaRecord.getRecipientId();
|
2019-12-04 20:13:51 -05:00
|
|
|
RecipientId threadRecipientId = mediaRecord.getThreadRecipientId();
|
2018-01-04 11:11:49 -08:00
|
|
|
|
|
|
|
if (mediaRecord.getAttachment().getDataUri() == null) throw new AssertionError();
|
|
|
|
|
2019-08-07 14:22:51 -04:00
|
|
|
return new MediaItem(Recipient.live(recipientId).get(),
|
2019-12-04 20:13:51 -05:00
|
|
|
Recipient.live(threadRecipientId).get(),
|
2018-03-13 18:24:42 -07:00
|
|
|
mediaRecord.getAttachment(),
|
2018-01-04 11:11:49 -08:00
|
|
|
mediaRecord.getAttachment().getDataUri(),
|
|
|
|
mediaRecord.getContentType(),
|
|
|
|
mediaRecord.getDate(),
|
|
|
|
mediaRecord.isOutgoing());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void pause(int position) {
|
2019-07-19 11:43:55 -04:00
|
|
|
MediaPreviewFragment mediaView = mediaFragments.get(position);
|
2018-01-04 11:11:49 -08:00
|
|
|
if (mediaView != null) mediaView.pause();
|
|
|
|
}
|
2018-01-23 12:39:30 -08:00
|
|
|
|
2018-11-08 23:33:37 -08:00
|
|
|
@Override
|
|
|
|
public @Nullable View getPlaybackControls(int position) {
|
2019-07-19 11:43:55 -04:00
|
|
|
MediaPreviewFragment mediaView = mediaFragments.get(position);
|
2018-11-08 23:33:37 -08:00
|
|
|
if (mediaView != null) return mediaView.getPlaybackControls();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-10-23 14:36:50 -07:00
|
|
|
@Override
|
|
|
|
public boolean hasFragmentFor(int position) {
|
|
|
|
return mediaFragments.containsKey(position);
|
|
|
|
}
|
|
|
|
|
2018-01-23 12:39:30 -08:00
|
|
|
private int getCursorPosition(int position) {
|
|
|
|
if (leftIsRecent) return position;
|
|
|
|
else return cursor.getCount() - 1 - position;
|
|
|
|
}
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
private static class MediaItem {
|
2018-03-13 18:24:42 -07:00
|
|
|
private final @Nullable Recipient recipient;
|
2019-12-03 11:05:03 -05:00
|
|
|
private final @Nullable Recipient threadRecipient;
|
2018-03-13 18:24:42 -07:00
|
|
|
private final @Nullable DatabaseAttachment attachment;
|
|
|
|
private final @NonNull Uri uri;
|
|
|
|
private final @NonNull String type;
|
|
|
|
private final long date;
|
|
|
|
private final boolean outgoing;
|
|
|
|
|
|
|
|
private MediaItem(@Nullable Recipient recipient,
|
2019-12-03 11:05:03 -05:00
|
|
|
@Nullable Recipient threadRecipient,
|
2018-03-13 18:24:42 -07:00
|
|
|
@Nullable DatabaseAttachment attachment,
|
|
|
|
@NonNull Uri uri,
|
|
|
|
@NonNull String type,
|
|
|
|
long date,
|
|
|
|
boolean outgoing)
|
|
|
|
{
|
2019-12-03 11:05:03 -05:00
|
|
|
this.recipient = recipient;
|
|
|
|
this.threadRecipient = threadRecipient;
|
|
|
|
this.attachment = attachment;
|
|
|
|
this.uri = uri;
|
|
|
|
this.type = type;
|
|
|
|
this.date = date;
|
|
|
|
this.outgoing = outgoing;
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
interface MediaItemAdapter {
|
|
|
|
MediaItem getMediaItemFor(int position);
|
|
|
|
void pause(int position);
|
2018-11-08 23:33:37 -08:00
|
|
|
@Nullable View getPlaybackControls(int position);
|
2019-10-23 14:36:50 -07:00
|
|
|
boolean hasFragmentFor(int position);
|
2018-01-04 11:11:49 -08:00
|
|
|
}
|
2014-08-12 12:11:23 -07:00
|
|
|
}
|