2018-11-20 09:59:23 -08:00
|
|
|
package org.thoughtcrime.securesms.mediasend;
|
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
import android.Manifest;
|
2018-11-20 09:59:23 -08:00
|
|
|
import android.arch.lifecycle.ViewModelProviders;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.support.annotation.NonNull;
|
2019-03-01 10:50:48 -08:00
|
|
|
import android.support.v4.app.Fragment;
|
|
|
|
import android.support.v4.app.FragmentManager;
|
|
|
|
import android.view.View;
|
2019-03-13 16:05:25 -07:00
|
|
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
2019-03-19 12:24:45 -07:00
|
|
|
import android.view.animation.AccelerateInterpolator;
|
2019-03-13 16:05:25 -07:00
|
|
|
import android.view.animation.Animation;
|
2019-03-19 12:24:45 -07:00
|
|
|
import android.view.animation.DecelerateInterpolator;
|
2019-03-13 16:05:25 -07:00
|
|
|
import android.view.animation.OvershootInterpolator;
|
|
|
|
import android.view.animation.ScaleAnimation;
|
2019-03-01 10:50:48 -08:00
|
|
|
import android.widget.TextView;
|
2019-03-13 16:05:25 -07:00
|
|
|
import android.widget.Toast;
|
2018-11-20 09:59:23 -08:00
|
|
|
|
|
|
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
|
|
|
|
import org.thoughtcrime.securesms.R;
|
|
|
|
import org.thoughtcrime.securesms.TransportOption;
|
|
|
|
import org.thoughtcrime.securesms.database.Address;
|
2019-03-01 10:50:48 -08:00
|
|
|
import org.thoughtcrime.securesms.logging.Log;
|
2019-03-14 17:01:23 -07:00
|
|
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
2019-03-13 16:05:25 -07:00
|
|
|
import org.thoughtcrime.securesms.providers.BlobProvider;
|
2018-11-20 09:59:23 -08:00
|
|
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
|
|
|
import org.thoughtcrime.securesms.scribbles.ScribbleFragment;
|
|
|
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
2019-03-13 16:05:25 -07:00
|
|
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
2018-11-20 09:59:23 -08:00
|
|
|
import org.thoughtcrime.securesms.util.Util;
|
2019-03-13 16:05:25 -07:00
|
|
|
import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
|
2018-11-20 09:59:23 -08:00
|
|
|
import org.whispersystems.libsignal.util.guava.Optional;
|
|
|
|
|
2019-03-13 16:05:25 -07:00
|
|
|
import java.io.IOException;
|
2018-11-20 09:59:23 -08:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2019-03-01 10:50:48 -08:00
|
|
|
import java.util.Locale;
|
2018-11-20 09:59:23 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Encompasses the entire flow of sending media, starting from the selection process to the actual
|
|
|
|
* captioning and editing of the content.
|
|
|
|
*
|
|
|
|
* This activity is intended to be launched via {@link #startActivityForResult(Intent, int)}.
|
|
|
|
* It will return the {@link Media} that the user decided to send.
|
|
|
|
*/
|
|
|
|
public class MediaSendActivity extends PassphraseRequiredActionBarActivity implements MediaPickerFolderFragment.Controller,
|
|
|
|
MediaPickerItemFragment.Controller,
|
|
|
|
MediaSendFragment.Controller,
|
2019-03-13 16:05:25 -07:00
|
|
|
ScribbleFragment.Controller,
|
|
|
|
Camera1Fragment.Controller
|
2018-11-20 09:59:23 -08:00
|
|
|
{
|
2019-03-13 16:05:25 -07:00
|
|
|
private static final String TAG = MediaSendActivity.class.getSimpleName();
|
|
|
|
|
2018-11-20 09:59:23 -08:00
|
|
|
public static final String EXTRA_MEDIA = "media";
|
|
|
|
public static final String EXTRA_MESSAGE = "message";
|
|
|
|
public static final String EXTRA_TRANSPORT = "transport";
|
|
|
|
|
|
|
|
|
|
|
|
private static final String KEY_ADDRESS = "address";
|
|
|
|
private static final String KEY_BODY = "body";
|
|
|
|
private static final String KEY_MEDIA = "media";
|
|
|
|
private static final String KEY_TRANSPORT = "transport";
|
2019-03-13 16:05:25 -07:00
|
|
|
private static final String KEY_IS_CAMERA = "is_camera";
|
2018-11-20 09:59:23 -08:00
|
|
|
|
|
|
|
private static final String TAG_FOLDER_PICKER = "folder_picker";
|
|
|
|
private static final String TAG_ITEM_PICKER = "item_picker";
|
|
|
|
private static final String TAG_SEND = "send";
|
2019-03-13 16:05:25 -07:00
|
|
|
private static final String TAG_CAMERA = "camera";
|
2018-11-20 09:59:23 -08:00
|
|
|
|
|
|
|
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
|
|
|
|
|
|
|
private Recipient recipient;
|
|
|
|
private TransportOption transport;
|
|
|
|
private MediaSendViewModel viewModel;
|
|
|
|
|
2019-03-01 10:50:48 -08:00
|
|
|
private View countButton;
|
|
|
|
private TextView countButtonText;
|
2019-03-14 17:01:23 -07:00
|
|
|
private View cameraButton;
|
2019-03-01 10:50:48 -08:00
|
|
|
|
2018-11-20 09:59:23 -08:00
|
|
|
/**
|
|
|
|
* Get an intent to launch the media send flow starting with the picker.
|
|
|
|
*/
|
2019-03-13 16:05:25 -07:00
|
|
|
public static Intent buildGalleryIntent(@NonNull Context context, @NonNull Recipient recipient, @NonNull String body, @NonNull TransportOption transport) {
|
2018-11-20 09:59:23 -08:00
|
|
|
Intent intent = new Intent(context, MediaSendActivity.class);
|
|
|
|
intent.putExtra(KEY_ADDRESS, recipient.getAddress().serialize());
|
|
|
|
intent.putExtra(KEY_TRANSPORT, transport);
|
2019-01-17 11:42:01 -08:00
|
|
|
intent.putExtra(KEY_BODY, body);
|
2018-11-20 09:59:23 -08:00
|
|
|
return intent;
|
|
|
|
}
|
|
|
|
|
2019-03-13 16:05:25 -07:00
|
|
|
/**
|
|
|
|
* Get an intent to launch the media send flow starting with the picker.
|
|
|
|
*/
|
|
|
|
public static Intent buildCameraIntent(@NonNull Context context, @NonNull Recipient recipient, @NonNull TransportOption transport) {
|
|
|
|
Intent intent = buildGalleryIntent(context, recipient, "", transport);
|
|
|
|
intent.putExtra(KEY_IS_CAMERA, true);
|
|
|
|
return intent;
|
|
|
|
}
|
|
|
|
|
2018-11-20 09:59:23 -08:00
|
|
|
/**
|
|
|
|
* Get an intent to launch the media send flow with a specific list of media. Will jump right to
|
|
|
|
* the editor screen.
|
|
|
|
*/
|
2019-03-13 16:05:25 -07:00
|
|
|
public static Intent buildEditorIntent(@NonNull Context context,
|
|
|
|
@NonNull List<Media> media,
|
|
|
|
@NonNull Recipient recipient,
|
|
|
|
@NonNull String body,
|
|
|
|
@NonNull TransportOption transport)
|
2018-11-20 09:59:23 -08:00
|
|
|
{
|
2019-03-13 16:05:25 -07:00
|
|
|
Intent intent = buildGalleryIntent(context, recipient, body, transport);
|
2018-11-20 09:59:23 -08:00
|
|
|
intent.putParcelableArrayListExtra(KEY_MEDIA, new ArrayList<>(media));
|
|
|
|
return intent;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPreCreate() {
|
|
|
|
dynamicLanguage.onCreate(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onCreate(Bundle savedInstanceState, boolean ready) {
|
2019-03-01 10:50:48 -08:00
|
|
|
setContentView(R.layout.mediasend_activity);
|
2018-11-20 09:59:23 -08:00
|
|
|
setResult(RESULT_CANCELED);
|
|
|
|
|
|
|
|
if (savedInstanceState != null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-01 10:50:48 -08:00
|
|
|
countButton = findViewById(R.id.mediasend_count_button);
|
|
|
|
countButtonText = findViewById(R.id.mediasend_count_button_text);
|
2019-03-14 17:01:23 -07:00
|
|
|
cameraButton = findViewById(R.id.mediasend_camera_button);
|
2019-03-01 10:50:48 -08:00
|
|
|
|
2019-03-13 16:05:25 -07:00
|
|
|
viewModel = ViewModelProviders.of(this, new MediaSendViewModel.Factory(getApplication(), new MediaRepository())).get(MediaSendViewModel.class);
|
2018-11-20 09:59:23 -08:00
|
|
|
recipient = Recipient.from(this, Address.fromSerialized(getIntent().getStringExtra(KEY_ADDRESS)), true);
|
|
|
|
transport = getIntent().getParcelableExtra(KEY_TRANSPORT);
|
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
viewModel.setTransport(transport);
|
2019-03-01 10:50:48 -08:00
|
|
|
viewModel.onBodyChanged(getIntent().getStringExtra(KEY_BODY));
|
|
|
|
|
2019-03-13 16:05:25 -07:00
|
|
|
List<Media> media = getIntent().getParcelableArrayListExtra(KEY_MEDIA);
|
|
|
|
boolean isCamera = getIntent().getBooleanExtra(KEY_IS_CAMERA, false);
|
2018-11-20 09:59:23 -08:00
|
|
|
|
2019-03-13 16:05:25 -07:00
|
|
|
if (isCamera) {
|
|
|
|
Fragment fragment = Camera1Fragment.newInstance();
|
|
|
|
getSupportFragmentManager().beginTransaction()
|
|
|
|
.replace(R.id.mediasend_fragment_container, fragment, TAG_CAMERA)
|
|
|
|
.commit();
|
|
|
|
|
|
|
|
} else if (!Util.isEmpty(media)) {
|
2019-03-01 10:50:48 -08:00
|
|
|
viewModel.onSelectedMediaChanged(this, media);
|
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
Fragment fragment = MediaSendFragment.newInstance(recipient, transport, dynamicLanguage.getCurrentLocale());
|
2019-03-01 10:50:48 -08:00
|
|
|
getSupportFragmentManager().beginTransaction()
|
|
|
|
.replace(R.id.mediasend_fragment_container, fragment, TAG_SEND)
|
|
|
|
.commit();
|
2018-11-20 09:59:23 -08:00
|
|
|
} else {
|
2019-03-01 10:50:48 -08:00
|
|
|
MediaPickerFolderFragment fragment = MediaPickerFolderFragment.newInstance(recipient);
|
|
|
|
getSupportFragmentManager().beginTransaction()
|
|
|
|
.replace(R.id.mediasend_fragment_container, fragment, TAG_FOLDER_PICKER)
|
|
|
|
.commit();
|
2018-11-20 09:59:23 -08:00
|
|
|
}
|
2019-03-01 10:50:48 -08:00
|
|
|
|
|
|
|
initializeCountButtonObserver(transport, dynamicLanguage.getCurrentLocale());
|
2019-03-14 17:01:23 -07:00
|
|
|
initializeCameraButtonObserver();
|
|
|
|
initializeErrorObserver();
|
|
|
|
|
|
|
|
cameraButton.setOnClickListener(v -> {
|
|
|
|
int maxSelection = viewModel.getMaxSelection();
|
|
|
|
|
|
|
|
if (viewModel.getSelectedMedia().getValue() != null && viewModel.getSelectedMedia().getValue().size() >= maxSelection) {
|
|
|
|
Toast.makeText(this, getResources().getQuantityString(R.plurals.MediaSendActivity_cant_share_more_than_n_items, maxSelection, maxSelection), Toast.LENGTH_SHORT).show();
|
|
|
|
} else {
|
|
|
|
navigateToCamera();
|
|
|
|
}
|
|
|
|
});
|
2018-11-20 09:59:23 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onResume() {
|
|
|
|
super.onResume();
|
|
|
|
dynamicLanguage.onResume(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onBackPressed() {
|
|
|
|
MediaSendFragment sendFragment = (MediaSendFragment) getSupportFragmentManager().findFragmentByTag(TAG_SEND);
|
2019-01-15 15:08:35 -08:00
|
|
|
if (sendFragment == null || !sendFragment.isVisible() || !sendFragment.handleBackPress()) {
|
2018-11-20 09:59:23 -08:00
|
|
|
super.onBackPressed();
|
2019-03-13 16:05:25 -07:00
|
|
|
|
|
|
|
if (getIntent().getBooleanExtra(KEY_IS_CAMERA, false) && getSupportFragmentManager().getBackStackEntryCount() == 0) {
|
|
|
|
viewModel.onImageCaptureUndo(this);
|
|
|
|
}
|
2018-11-20 09:59:23 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
@Override
|
|
|
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
|
|
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
|
|
|
}
|
|
|
|
|
2018-11-20 09:59:23 -08:00
|
|
|
@Override
|
|
|
|
public void onFolderSelected(@NonNull MediaFolder folder) {
|
|
|
|
viewModel.onFolderSelected(folder.getBucketId());
|
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
MediaPickerItemFragment fragment = MediaPickerItemFragment.newInstance(folder.getBucketId(), folder.getTitle(), viewModel.getMaxSelection());
|
2018-11-20 09:59:23 -08:00
|
|
|
getSupportFragmentManager().beginTransaction()
|
2019-03-01 10:50:48 -08:00
|
|
|
.setCustomAnimations(R.anim.slide_from_right, R.anim.slide_to_left, R.anim.slide_from_left, R.anim.slide_to_right)
|
|
|
|
.replace(R.id.mediasend_fragment_container, fragment, TAG_ITEM_PICKER)
|
2018-11-20 09:59:23 -08:00
|
|
|
.addToBackStack(null)
|
|
|
|
.commit();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-03-19 16:11:46 -07:00
|
|
|
public void onMediaSelected(@NonNull Media media) {
|
|
|
|
viewModel.onSingleMediaSelected(this, media);
|
2019-03-14 17:01:23 -07:00
|
|
|
navigateToMediaSend(recipient, transport, dynamicLanguage.getCurrentLocale());
|
2018-11-20 09:59:23 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onAddMediaClicked(@NonNull String bucketId) {
|
2019-03-01 10:50:48 -08:00
|
|
|
// TODO: Get actual folder title somehow
|
2018-11-20 09:59:23 -08:00
|
|
|
MediaPickerFolderFragment folderFragment = MediaPickerFolderFragment.newInstance(recipient);
|
2019-03-14 17:01:23 -07:00
|
|
|
MediaPickerItemFragment itemFragment = MediaPickerItemFragment.newInstance(bucketId, "", viewModel.getMaxSelection());
|
2018-11-20 09:59:23 -08:00
|
|
|
|
|
|
|
getSupportFragmentManager().beginTransaction()
|
2019-03-01 10:50:48 -08:00
|
|
|
.setCustomAnimations(R.anim.stationary, R.anim.slide_to_left, R.anim.slide_from_left, R.anim.slide_to_right)
|
|
|
|
.replace(R.id.mediasend_fragment_container, folderFragment, TAG_FOLDER_PICKER)
|
2018-11-20 09:59:23 -08:00
|
|
|
.addToBackStack(null)
|
|
|
|
.commit();
|
|
|
|
|
|
|
|
getSupportFragmentManager().beginTransaction()
|
2019-03-01 10:50:48 -08:00
|
|
|
.setCustomAnimations(R.anim.slide_from_right, R.anim.stationary, R.anim.slide_from_left, R.anim.slide_to_right)
|
|
|
|
.replace(R.id.mediasend_fragment_container, itemFragment, TAG_ITEM_PICKER)
|
2018-11-20 09:59:23 -08:00
|
|
|
.addToBackStack(null)
|
|
|
|
.commit();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSendClicked(@NonNull List<Media> media, @NonNull String message, @NonNull TransportOption transport) {
|
2019-03-13 16:05:25 -07:00
|
|
|
viewModel.onSendClicked();
|
|
|
|
|
2018-11-20 09:59:23 -08:00
|
|
|
ArrayList<Media> mediaList = new ArrayList<>(media);
|
|
|
|
Intent intent = new Intent();
|
|
|
|
|
|
|
|
intent.putParcelableArrayListExtra(EXTRA_MEDIA, mediaList);
|
|
|
|
intent.putExtra(EXTRA_MESSAGE, message);
|
|
|
|
intent.putExtra(EXTRA_TRANSPORT, transport);
|
|
|
|
setResult(RESULT_OK, intent);
|
|
|
|
finish();
|
|
|
|
|
|
|
|
overridePendingTransition(R.anim.stationary, R.anim.camera_slide_to_bottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onNoMediaAvailable() {
|
|
|
|
setResult(RESULT_CANCELED);
|
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onImageEditComplete(@NonNull Uri uri, int width, int height, long size, @NonNull Optional<String> message, @NonNull Optional<TransportOption> transport) {
|
|
|
|
throw new UnsupportedOperationException("Callback unsupported.");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onImageEditFailure() {
|
|
|
|
throw new UnsupportedOperationException("Callback unsupported.");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onTouchEventsNeeded(boolean needed) {
|
|
|
|
MediaSendFragment fragment = (MediaSendFragment) getSupportFragmentManager().findFragmentByTag(TAG_SEND);
|
|
|
|
if (fragment != null) {
|
|
|
|
fragment.onTouchEventsNeeded(needed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 16:05:25 -07:00
|
|
|
@Override
|
|
|
|
public void onCameraError() {
|
|
|
|
Toast.makeText(this, R.string.MediaSendActivity_camera_unavailable, Toast.LENGTH_SHORT).show();
|
|
|
|
setResult(RESULT_CANCELED, new Intent());
|
|
|
|
finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onImageCaptured(@NonNull byte[] data, int width, int height) {
|
|
|
|
Log.i(TAG, "Camera image captured.");
|
|
|
|
|
|
|
|
SimpleTask.run(getLifecycle(), () -> {
|
|
|
|
try {
|
|
|
|
Uri uri = BlobProvider.getInstance()
|
|
|
|
.forData(data)
|
|
|
|
.withMimeType(MediaUtil.IMAGE_JPEG)
|
2019-03-19 15:34:04 -07:00
|
|
|
.createForSingleSessionOnDisk(this, e -> Log.w(TAG, "Failed to write to disk.", e));
|
2019-03-13 16:05:25 -07:00
|
|
|
return new Media(uri,
|
|
|
|
MediaUtil.IMAGE_JPEG,
|
|
|
|
System.currentTimeMillis(),
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
data.length,
|
|
|
|
Optional.of(Media.ALL_MEDIA_BUCKET_ID),
|
|
|
|
Optional.absent());
|
|
|
|
} catch (IOException e) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}, media -> {
|
|
|
|
if (media == null) {
|
|
|
|
onImageEditFailure();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Log.i(TAG, "Camera capture stored: " + media.getUri().toString());
|
|
|
|
|
|
|
|
viewModel.onImageCaptured(media);
|
2019-03-14 17:01:23 -07:00
|
|
|
navigateToMediaSend(recipient, transport, dynamicLanguage.getCurrentLocale());
|
2019-03-13 16:05:25 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getDisplayRotation() {
|
|
|
|
return getWindowManager().getDefaultDisplay().getRotation();
|
|
|
|
}
|
|
|
|
|
2019-03-01 10:50:48 -08:00
|
|
|
private void initializeCountButtonObserver(@NonNull TransportOption transport, @NonNull Locale locale) {
|
|
|
|
viewModel.getCountButtonState().observe(this, buttonState -> {
|
|
|
|
if (buttonState == null) return;
|
2018-11-20 09:59:23 -08:00
|
|
|
|
2019-03-01 10:50:48 -08:00
|
|
|
countButtonText.setText(String.valueOf(buttonState.getCount()));
|
2019-03-14 17:01:23 -07:00
|
|
|
countButton.setEnabled(buttonState.isVisible());
|
|
|
|
animateButtonVisibility(countButton, countButton.getVisibility(), buttonState.isVisible() ? View.VISIBLE : View.GONE);
|
2019-03-13 16:05:25 -07:00
|
|
|
|
|
|
|
if (buttonState.getCount() > 0) {
|
2019-03-14 17:01:23 -07:00
|
|
|
countButton.setOnClickListener(v -> navigateToMediaSend(recipient, transport, locale));
|
2019-03-19 16:11:46 -07:00
|
|
|
if (buttonState.isVisible()) {
|
|
|
|
animateButtonTextChange(countButton);
|
|
|
|
}
|
2019-03-13 16:05:25 -07:00
|
|
|
} else {
|
|
|
|
countButton.setOnClickListener(null);
|
|
|
|
}
|
2019-03-01 10:50:48 -08:00
|
|
|
});
|
2018-11-20 09:59:23 -08:00
|
|
|
}
|
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
private void initializeCameraButtonObserver() {
|
|
|
|
viewModel.getCameraButtonVisibility().observe(this, visible -> {
|
|
|
|
if (visible == null) return;
|
|
|
|
animateButtonVisibility(cameraButton, cameraButton.getVisibility(), visible ? View.VISIBLE : View.GONE);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initializeErrorObserver() {
|
|
|
|
viewModel.getError().observe(this, error -> {
|
|
|
|
if (error == null) return;
|
|
|
|
|
|
|
|
switch (error) {
|
|
|
|
case ITEM_TOO_LARGE:
|
|
|
|
Toast.makeText(this, R.string.MediaSendActivity_an_item_was_removed_because_it_exceeded_the_size_limit, Toast.LENGTH_LONG).show();
|
|
|
|
break;
|
|
|
|
case TOO_MANY_ITEMS:
|
|
|
|
int maxSelection = viewModel.getMaxSelection();
|
|
|
|
Toast.makeText(this, getResources().getQuantityString(R.plurals.MediaSendActivity_cant_share_more_than_n_items, maxSelection, maxSelection), Toast.LENGTH_SHORT).show();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private void navigateToMediaSend(@NonNull Recipient recipient, @NonNull TransportOption transport, @NonNull Locale locale) {
|
|
|
|
MediaSendFragment fragment = MediaSendFragment.newInstance(recipient, transport, locale);
|
2019-03-01 10:50:48 -08:00
|
|
|
String backstackTag = null;
|
|
|
|
|
|
|
|
if (getSupportFragmentManager().findFragmentByTag(TAG_SEND) != null) {
|
|
|
|
getSupportFragmentManager().popBackStack(TAG_SEND, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
|
|
|
backstackTag = TAG_SEND;
|
|
|
|
}
|
2018-11-20 09:59:23 -08:00
|
|
|
|
|
|
|
getSupportFragmentManager().beginTransaction()
|
2019-03-01 10:50:48 -08:00
|
|
|
.setCustomAnimations(R.anim.slide_from_right, R.anim.slide_to_left, R.anim.slide_from_left, R.anim.slide_to_right)
|
|
|
|
.replace(R.id.mediasend_fragment_container, fragment, TAG_SEND)
|
|
|
|
.addToBackStack(backstackTag)
|
2018-11-20 09:59:23 -08:00
|
|
|
.commit();
|
|
|
|
}
|
2019-03-13 16:05:25 -07:00
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
private void navigateToCamera() {
|
|
|
|
Permissions.with(this)
|
|
|
|
.request(Manifest.permission.CAMERA)
|
|
|
|
.ifNecessary()
|
|
|
|
.withRationaleDialog(getString(R.string.ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera), R.drawable.ic_photo_camera_white_48dp)
|
|
|
|
.withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video))
|
|
|
|
.onAllGranted(() -> {
|
|
|
|
Camera1Fragment fragment = getOrCreateCameraFragment();
|
|
|
|
getSupportFragmentManager().beginTransaction()
|
|
|
|
.setCustomAnimations(R.anim.slide_from_right, R.anim.slide_to_left, R.anim.slide_from_left, R.anim.slide_to_right)
|
|
|
|
.replace(R.id.mediasend_fragment_container, fragment, TAG_CAMERA)
|
|
|
|
.addToBackStack(null)
|
|
|
|
.commit();
|
|
|
|
})
|
|
|
|
.onAnyDenied(() -> Toast.makeText(MediaSendActivity.this, R.string.ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video, Toast.LENGTH_LONG).show())
|
|
|
|
.execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
private Camera1Fragment getOrCreateCameraFragment() {
|
|
|
|
Camera1Fragment fragment = (Camera1Fragment) getSupportFragmentManager().findFragmentByTag(TAG_CAMERA);
|
|
|
|
|
|
|
|
return fragment != null ? fragment
|
|
|
|
: Camera1Fragment.newInstance();
|
|
|
|
}
|
|
|
|
|
2019-03-19 12:24:45 -07:00
|
|
|
private void animateButtonVisibility(@NonNull View button, int oldVisibility, int newVisibility) {
|
2019-03-13 16:05:25 -07:00
|
|
|
if (oldVisibility == newVisibility) return;
|
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
if (button.getAnimation() != null) {
|
|
|
|
button.getAnimation().cancel();
|
|
|
|
button.setVisibility(newVisibility);
|
2019-03-13 16:05:25 -07:00
|
|
|
} else if (newVisibility == View.VISIBLE) {
|
2019-03-14 17:01:23 -07:00
|
|
|
button.setVisibility(View.VISIBLE);
|
2019-03-13 16:05:25 -07:00
|
|
|
|
|
|
|
Animation animation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
|
|
|
animation.setDuration(250);
|
|
|
|
animation.setInterpolator(new OvershootInterpolator());
|
2019-03-14 17:01:23 -07:00
|
|
|
button.startAnimation(animation);
|
2019-03-13 16:05:25 -07:00
|
|
|
} else {
|
|
|
|
Animation animation = new ScaleAnimation(1, 0, 1, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
|
|
|
animation.setDuration(150);
|
|
|
|
animation.setInterpolator(new AccelerateDecelerateInterpolator());
|
|
|
|
animation.setAnimationListener(new SimpleAnimationListener() {
|
|
|
|
@Override
|
|
|
|
public void onAnimationEnd(Animation animation) {
|
2019-03-14 17:01:23 -07:00
|
|
|
button.setVisibility(View.GONE);
|
2019-03-13 16:05:25 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-03-14 17:01:23 -07:00
|
|
|
button.startAnimation(animation);
|
2019-03-13 16:05:25 -07:00
|
|
|
}
|
|
|
|
}
|
2019-03-19 12:24:45 -07:00
|
|
|
|
|
|
|
private void animateButtonTextChange(@NonNull View button) {
|
|
|
|
if (button.getAnimation() != null) {
|
|
|
|
button.getAnimation().cancel();
|
|
|
|
}
|
|
|
|
|
|
|
|
Animation grow = new ScaleAnimation(1f, 1.3f, 1f, 1.3f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
|
|
|
grow.setDuration(125);
|
|
|
|
grow.setInterpolator(new AccelerateInterpolator());
|
|
|
|
grow.setAnimationListener(new SimpleAnimationListener() {
|
|
|
|
@Override
|
|
|
|
public void onAnimationEnd(Animation animation) {
|
|
|
|
Animation shrink = new ScaleAnimation(1.3f, 1f, 1.3f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
|
|
|
shrink.setDuration(125);
|
|
|
|
shrink.setInterpolator(new DecelerateInterpolator());
|
|
|
|
button.startAnimation(shrink);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
button.startAnimation(grow);
|
|
|
|
}
|
2018-11-20 09:59:23 -08:00
|
|
|
}
|