2014-08-12 21:11:23 +02: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;
|
|
|
|
|
|
|
|
import android.annotation.TargetApi;
|
|
|
|
import android.content.DialogInterface;
|
2015-02-10 10:46:43 +01:00
|
|
|
import android.content.Intent;
|
2014-08-12 21:11:23 +02:00
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Build.VERSION;
|
|
|
|
import android.os.Build.VERSION_CODES;
|
|
|
|
import android.os.Bundle;
|
2014-12-15 21:25:55 +01:00
|
|
|
import android.support.annotation.NonNull;
|
2014-08-12 21:11:23 +02:00
|
|
|
import android.util.Log;
|
2014-06-29 05:40:57 +02:00
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuInflater;
|
|
|
|
import android.view.MenuItem;
|
2014-08-12 21:11:23 +02:00
|
|
|
import android.view.View;
|
|
|
|
import android.view.WindowManager;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
2015-06-04 22:21:20 +02:00
|
|
|
import org.thoughtcrime.securesms.components.ZoomingImageView;
|
2014-11-04 00:16:04 +01:00
|
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
2017-07-26 18:59:15 +02:00
|
|
|
import org.thoughtcrime.securesms.database.Address;
|
2016-11-26 21:10:14 +01:00
|
|
|
import org.thoughtcrime.securesms.mms.VideoSlide;
|
2014-08-12 21:11:23 +02:00
|
|
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
2017-08-01 17:56:00 +02:00
|
|
|
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
2014-08-12 21:11:23 +02:00
|
|
|
import org.thoughtcrime.securesms.util.DateUtils;
|
|
|
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
|
|
|
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
|
|
|
import org.thoughtcrime.securesms.util.SaveAttachmentTask.Attachment;
|
2016-11-26 21:10:14 +01:00
|
|
|
import org.thoughtcrime.securesms.video.VideoPlayer;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
2014-08-12 21:11:23 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Activity for displaying media attachments in-app
|
|
|
|
*/
|
2015-02-10 10:46:43 +01:00
|
|
|
public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener {
|
2014-08-12 21:11:23 +02:00
|
|
|
private final static String TAG = MediaPreviewActivity.class.getSimpleName();
|
|
|
|
|
2017-07-26 18:59:15 +02:00
|
|
|
public static final String ADDRESS_EXTRA = "address";
|
2016-09-20 18:53:44 +02:00
|
|
|
public static final String THREAD_ID_EXTRA = "thread_id";
|
2014-12-15 21:25:55 +01:00
|
|
|
public static final String DATE_EXTRA = "date";
|
2016-11-26 21:10:14 +01:00
|
|
|
public static final String SIZE_EXTRA = "size";
|
2014-08-12 21:11:23 +02:00
|
|
|
|
|
|
|
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
|
|
|
|
|
|
|
private MasterSecret masterSecret;
|
|
|
|
|
2016-12-14 19:21:14 +01:00
|
|
|
private ZoomingImageView image;
|
|
|
|
private VideoPlayer video;
|
|
|
|
|
|
|
|
private Uri mediaUri;
|
|
|
|
private String mediaType;
|
|
|
|
private Recipient recipient;
|
|
|
|
private long threadId;
|
|
|
|
private long date;
|
|
|
|
private long size;
|
2014-08-12 21:11:23 +02:00
|
|
|
|
|
|
|
@Override
|
2014-12-15 21:25:55 +01:00
|
|
|
protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
|
|
|
|
this.masterSecret = masterSecret;
|
2014-11-25 07:55:10 +01:00
|
|
|
this.setTheme(R.style.TextSecure_DarkTheme);
|
|
|
|
dynamicLanguage.onCreate(this);
|
|
|
|
|
2014-08-12 21:11:23 +02:00
|
|
|
setFullscreenIfPossible();
|
|
|
|
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
|
|
|
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
2014-11-25 07:55:10 +01:00
|
|
|
|
2014-08-12 21:11:23 +02:00
|
|
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
|
|
setContentView(R.layout.media_preview_activity);
|
2014-11-25 07:55:10 +01:00
|
|
|
|
2015-02-10 10:46:43 +01:00
|
|
|
initializeViews();
|
2014-08-12 21:11:23 +02:00
|
|
|
initializeResources();
|
2015-02-10 10:46:43 +01:00
|
|
|
initializeActionBar();
|
2014-08-12 21:11:23 +02:00
|
|
|
}
|
|
|
|
|
2014-06-29 05:40:57 +02:00
|
|
|
@TargetApi(VERSION_CODES.JELLY_BEAN)
|
2014-08-12 21:11:23 +02:00
|
|
|
private void setFullscreenIfPossible() {
|
2014-06-29 05:40:57 +02:00
|
|
|
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
|
2014-08-12 21:11:23 +02:00
|
|
|
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-10 10:46:43 +01:00
|
|
|
@Override
|
|
|
|
public void onModified(Recipient recipient) {
|
|
|
|
initializeActionBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initializeActionBar() {
|
|
|
|
final CharSequence relativeTimeSpan;
|
|
|
|
if (date > 0) {
|
2016-08-05 22:17:31 +02:00
|
|
|
relativeTimeSpan = DateUtils.getExtendedRelativeTimeSpanString(this,dynamicLanguage.getCurrentLocale(),date);
|
2015-02-10 10:46:43 +01:00
|
|
|
} else {
|
2017-02-10 15:02:48 +01:00
|
|
|
relativeTimeSpan = getString(R.string.MediaPreviewActivity_draft);
|
2015-02-10 10:46:43 +01:00
|
|
|
}
|
2015-06-04 22:21:20 +02:00
|
|
|
getSupportActionBar().setTitle(recipient == null ? getString(R.string.MediaPreviewActivity_you)
|
|
|
|
: recipient.toShortString());
|
2015-02-10 10:46:43 +01:00
|
|
|
getSupportActionBar().setSubtitle(relativeTimeSpan);
|
|
|
|
}
|
|
|
|
|
2014-08-12 21:11:23 +02:00
|
|
|
@Override
|
|
|
|
public void onResume() {
|
|
|
|
super.onResume();
|
|
|
|
dynamicLanguage.onResume(this);
|
2015-02-10 10:46:43 +01:00
|
|
|
if (recipient != null) recipient.addListener(this);
|
|
|
|
initializeMedia();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPause() {
|
|
|
|
super.onPause();
|
|
|
|
if (recipient != null) recipient.removeListener(this);
|
|
|
|
cleanupMedia();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onNewIntent(Intent intent) {
|
|
|
|
super.onNewIntent(intent);
|
|
|
|
if (recipient != null) recipient.removeListener(this);
|
|
|
|
setIntent(intent);
|
|
|
|
initializeResources();
|
|
|
|
initializeActionBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initializeViews() {
|
2016-12-14 19:21:14 +01:00
|
|
|
image = (ZoomingImageView) findViewById(R.id.image);
|
|
|
|
video = (VideoPlayer) findViewById(R.id.video_player);
|
2015-02-10 10:46:43 +01:00
|
|
|
}
|
2014-08-12 21:11:23 +02:00
|
|
|
|
2015-02-10 10:46:43 +01:00
|
|
|
private void initializeResources() {
|
2017-07-26 18:59:15 +02:00
|
|
|
Address address = getIntent().getParcelableExtra(ADDRESS_EXTRA);
|
2014-12-24 23:48:04 +01:00
|
|
|
|
2015-02-10 12:15:50 +01:00
|
|
|
mediaUri = getIntent().getData();
|
|
|
|
mediaType = getIntent().getType();
|
2017-02-10 15:02:48 +01:00
|
|
|
date = getIntent().getLongExtra(DATE_EXTRA, -1);
|
2016-11-26 21:10:14 +01:00
|
|
|
size = getIntent().getLongExtra(SIZE_EXTRA, 0);
|
2016-09-20 18:53:44 +02:00
|
|
|
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
|
2014-08-12 21:11:23 +02:00
|
|
|
|
2017-07-26 18:59:15 +02:00
|
|
|
if (address != null) {
|
2017-08-22 03:32:38 +02:00
|
|
|
recipient = Recipient.from(this, address, true);
|
2015-02-10 10:46:43 +01:00
|
|
|
recipient.addListener(this);
|
2014-08-12 21:11:23 +02:00
|
|
|
} else {
|
2014-12-24 23:48:04 +01:00
|
|
|
recipient = null;
|
2014-08-12 21:11:23 +02:00
|
|
|
}
|
2015-02-10 10:46:43 +01:00
|
|
|
}
|
2014-12-24 23:48:04 +01:00
|
|
|
|
2015-02-10 10:46:43 +01:00
|
|
|
private void initializeMedia() {
|
2014-08-12 21:11:23 +02:00
|
|
|
if (!isContentTypeSupported(mediaType)) {
|
|
|
|
Log.w(TAG, "Unsupported media type sent to MediaPreviewActivity, finishing.");
|
2014-12-15 15:44:41 +01:00
|
|
|
Toast.makeText(getApplicationContext(), R.string.MediaPreviewActivity_unssuported_media_type, Toast.LENGTH_LONG).show();
|
2014-08-12 21:11:23 +02:00
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
2014-12-03 10:25:32 +01:00
|
|
|
Log.w(TAG, "Loading Part URI: " + mediaUri);
|
2014-08-12 21:11:23 +02:00
|
|
|
|
2016-11-26 21:10:14 +01:00
|
|
|
try {
|
|
|
|
if (mediaType != null && mediaType.startsWith("image/")) {
|
|
|
|
image.setVisibility(View.VISIBLE);
|
|
|
|
video.setVisibility(View.GONE);
|
2016-12-14 19:21:14 +01:00
|
|
|
image.setImageUri(masterSecret, mediaUri, mediaType);
|
2016-11-26 21:10:14 +01:00
|
|
|
} else if (mediaType != null && mediaType.startsWith("video/")) {
|
|
|
|
image.setVisibility(View.GONE);
|
|
|
|
video.setVisibility(View.VISIBLE);
|
|
|
|
video.setVideoSource(masterSecret, new VideoSlide(this, mediaUri, size));
|
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
|
|
Log.w(TAG, e);
|
|
|
|
Toast.makeText(getApplicationContext(), R.string.MediaPreviewActivity_unssuported_media_type, Toast.LENGTH_LONG).show();
|
|
|
|
finish();
|
2014-08-12 21:11:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-10 10:46:43 +01:00
|
|
|
private void cleanupMedia() {
|
2016-12-14 19:21:14 +01:00
|
|
|
image.cleanup();
|
2016-11-26 21:10:14 +01:00
|
|
|
video.cleanup();
|
2014-12-24 23:48:04 +01:00
|
|
|
}
|
|
|
|
|
2016-09-20 18:53:44 +02:00
|
|
|
private void showOverview() {
|
|
|
|
Intent intent = new Intent(this, MediaOverviewActivity.class);
|
|
|
|
intent.putExtra(MediaOverviewActivity.THREAD_ID_EXTRA, threadId);
|
|
|
|
startActivity(intent);
|
|
|
|
}
|
|
|
|
|
2016-11-03 00:03:03 +01:00
|
|
|
private void forward() {
|
|
|
|
Intent composeIntent = new Intent(this, ShareActivity.class);
|
|
|
|
composeIntent.putExtra(Intent.EXTRA_STREAM, mediaUri);
|
|
|
|
composeIntent.setType(mediaType);
|
|
|
|
startActivity(composeIntent);
|
|
|
|
}
|
|
|
|
|
2014-08-12 21:11:23 +02:00
|
|
|
private void saveToDisk() {
|
|
|
|
SaveAttachmentTask.showWarningDialog(this, new DialogInterface.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(DialogInterface dialogInterface, int i) {
|
2017-03-28 21:05:30 +02:00
|
|
|
SaveAttachmentTask saveTask = new SaveAttachmentTask(MediaPreviewActivity.this, masterSecret, image);
|
2017-02-10 15:02:48 +01:00
|
|
|
long saveDate = (date > 0) ? date : System.currentTimeMillis();
|
2017-03-28 21:05:30 +02:00
|
|
|
saveTask.execute(new Attachment(mediaUri, mediaType, saveDate, null));
|
2014-08-12 21:11:23 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
|
|
super.onPrepareOptionsMenu(menu);
|
|
|
|
|
|
|
|
menu.clear();
|
2014-06-29 05:40:57 +02:00
|
|
|
MenuInflater inflater = this.getMenuInflater();
|
2014-08-12 21:11:23 +02:00
|
|
|
inflater.inflate(R.menu.media_preview, menu);
|
2016-11-28 23:21:54 +01:00
|
|
|
if (threadId == -1) menu.findItem(R.id.media_preview__overview).setVisible(false);
|
2014-08-12 21:11:23 +02: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;
|
|
|
|
case android.R.id.home: finish(); return true;
|
2014-08-12 21:11:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean isContentTypeSupported(final String contentType) {
|
2016-11-26 21:10:14 +01:00
|
|
|
return contentType != null && (contentType.startsWith("image/") || contentType.startsWith("video/"));
|
2014-08-12 21:11:23 +02:00
|
|
|
}
|
|
|
|
}
|