Added support for multi-image receive.

This commit is contained in:
Greyson Parrelli
2018-11-08 23:33:37 -08:00
parent e665252b86
commit 47a10a0288
55 changed files with 1277 additions and 186 deletions

View File

@@ -19,6 +19,7 @@ package org.thoughtcrime.securesms;
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -36,15 +37,21 @@ import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import org.thoughtcrime.securesms.logging.Log;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
@@ -53,6 +60,8 @@ import org.thoughtcrime.securesms.components.viewpager.ExtendedOnPageChangedList
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
import org.thoughtcrime.securesms.database.loaders.PagingMediaLoader;
import org.thoughtcrime.securesms.mediapreview.AlbumRailAdapter;
import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.permissions.Permissions;
@@ -71,33 +80,49 @@ import java.util.WeakHashMap;
/**
* Activity for displaying media attachments in-app
*/
public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener, LoaderManager.LoaderCallbacks<Pair<Cursor, Integer>> {
public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener,
LoaderManager.LoaderCallbacks<Pair<Cursor, Integer>>,
AlbumRailAdapter.RailItemClickedListener
{
private final static String TAG = MediaPreviewActivity.class.getSimpleName();
public static final String ADDRESS_EXTRA = "address";
public static final String DATE_EXTRA = "date";
public static final String SIZE_EXTRA = "size";
public static final String CAPTION_EXTRA = "caption";
public static final String OUTGOING_EXTRA = "outgoing";
public static final String LEFT_IS_RECENT_EXTRA = "left_is_recent";
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private ViewPager mediaPager;
private Uri initialMediaUri;
private String initialMediaType;
private long initialMediaSize;
private Recipient conversationRecipient;
private boolean leftIsRecent;
private ViewPager mediaPager;
private View detailsContainer;
private TextView caption;
private View captionContainer;
private RecyclerView albumRail;
private AlbumRailAdapter albumRailAdapter;
private ViewGroup playbackControlsContainer;
private Uri initialMediaUri;
private String initialMediaType;
private long initialMediaSize;
private String initialCaption;
private Recipient conversationRecipient;
private boolean leftIsRecent;
private GestureDetector clickDetector;
private MediaPreviewViewModel viewModel;
private int restartItem = -1;
@SuppressWarnings("ConstantConditions")
@Override
protected void onCreate(Bundle bundle, boolean ready) {
this.setTheme(R.style.TextSecure_DarkTheme);
dynamicLanguage.onCreate(this);
viewModel = ViewModelProviders.of(this).get(MediaPreviewViewModel.class);
setFullscreenIfPossible();
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
@@ -107,6 +132,13 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
initializeViews();
initializeResources();
initializeObservers();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
clickDetector.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
@Override
@@ -126,6 +158,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
Util.runOnMain(this::initializeActionBar);
}
@Override
public void onRailItemClicked(int distanceFromActive) {
mediaPager.setCurrentItem(mediaPager.getCurrentItem() + distanceFromActive);
}
@SuppressWarnings("ConstantConditions")
private void initializeActionBar() {
MediaItem mediaItem = getCurrentMediaItem();
@@ -172,6 +209,17 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
mediaPager = findViewById(R.id.media_pager);
mediaPager.setOffscreenPageLimit(1);
mediaPager.addOnPageChangeListener(new ViewPagerListener());
albumRail = findViewById(R.id.media_preview_album_rail);
albumRailAdapter = new AlbumRailAdapter(GlideApp.with(this), this);
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);
}
private void initializeResources() {
@@ -180,6 +228,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
initialMediaUri = getIntent().getData();
initialMediaType = getIntent().getType();
initialMediaSize = getIntent().getLongExtra(SIZE_EXTRA, 0);
initialCaption = getIntent().getStringExtra(CAPTION_EXTRA);
leftIsRecent = getIntent().getBooleanExtra(LEFT_IS_RECENT_EXTRA, false);
restartItem = -1;
@@ -190,6 +239,49 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
}
}
private void initializeObservers() {
viewModel.getPreviewData().observe(this, previewData -> {
if (previewData == null) {
return;
}
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);
albumRailAdapter.setRecords(previewData.getAlbumThumbnails(), previewData.getActivePosition());
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();
}
});
clickDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (e.getY() < detailsContainer.getTop()) {
detailsContainer.setVisibility(detailsContainer.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
}
return super.onSingleTapUp(e);
}
});
}
private void initializeMedia() {
if (!isContentTypeSupported(initialMediaType)) {
Log.w(TAG, "Unsupported media type sent to MediaPreviewActivity, finishing.");
@@ -203,6 +295,12 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
getSupportLoaderManager().restartLoader(0, null, this);
} else {
mediaPager.setAdapter(new SingleItemPagerAdapter(this, GlideApp.with(this), getWindow(), initialMediaUri, initialMediaType, initialMediaSize));
if (initialCaption != null) {
detailsContainer.setVisibility(View.VISIBLE);
captionContainer.setVisibility(View.VISIBLE);
caption.setText(initialCaption);
}
}
}
@@ -348,6 +446,8 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
mediaPager.setAdapter(adapter);
adapter.setActive(true);
viewModel.setCursor(data.first, leftIsRecent);
if (restartItem < 0) mediaPager.setCurrentItem(data.second);
else mediaPager.setCurrentItem(restartItem);
}
@@ -369,7 +469,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
if (adapter != null) {
MediaItem item = adapter.getMediaItemFor(position);
if (item.recipient != null) item.recipient.addListener(MediaPreviewActivity.this);
viewModel.setActiveAlbumRailItem(MediaPreviewActivity.this, position);
initializeActionBar();
}
}
@@ -453,6 +553,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
public void pause(int position) {
}
@Override
public @Nullable View getPlaybackControls(int position) {
return null;
}
}
private static class CursorPagerAdapter extends PagerAdapter implements MediaItemAdapter {
@@ -511,7 +616,8 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
try {
//noinspection ConstantConditions
mediaView.set(glideRequests, window, mediaRecord.getAttachment().getDataUri(), mediaRecord.getAttachment().getContentType(), mediaRecord.getAttachment().getSize(), autoplay);
mediaView.set(glideRequests, window, mediaRecord.getAttachment().getDataUri(),
mediaRecord.getAttachment().getContentType(), mediaRecord.getAttachment().getSize(), autoplay);
} catch (IOException e) {
Log.w(TAG, e);
}
@@ -552,6 +658,13 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
if (mediaView != null) mediaView.pause();
}
@Override
public @Nullable View getPlaybackControls(int position) {
MediaView mediaView = mediaViews.get(position);
if (mediaView != null) return mediaView.getPlaybackControls();
return null;
}
private int getCursorPosition(int position) {
if (leftIsRecent) return position;
else return cursor.getCount() - 1 - position;
@@ -585,5 +698,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
interface MediaItemAdapter {
MediaItem getMediaItemFor(int position);
void pause(int position);
@Nullable View getPlaybackControls(int position);
}
}