Signal-Android/app/src/main/java/org/thoughtcrime/securesms/mediasend/AvatarSelectionActivity.java

225 lines
7.4 KiB
Java

package org.thoughtcrime.securesms.mediasend;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProviders;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.TransportOptions;
import org.thoughtcrime.securesms.imageeditor.model.EditorModel;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.scribbles.ImageEditorFragment;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.whispersystems.libsignal.util.guava.Optional;
import java.io.FileDescriptor;
import java.util.Collections;
public class AvatarSelectionActivity extends AppCompatActivity implements CameraFragment.Controller, ImageEditorFragment.Controller, MediaPickerFolderFragment.Controller, MediaPickerItemFragment.Controller {
private static final Point AVATAR_DIMENSIONS = new Point(AvatarHelper.AVATAR_DIMENSIONS, AvatarHelper.AVATAR_DIMENSIONS);
private static final String IMAGE_CAPTURE = "IMAGE_CAPTURE";
private static final String IMAGE_EDITOR = "IMAGE_EDITOR";
private static final String ARG_GALLERY = "ARG_GALLERY";
public static final String EXTRA_MEDIA = "avatar.media";
private Media currentMedia;
public static Intent getIntentForCameraCapture(@NonNull Context context) {
return new Intent(context, AvatarSelectionActivity.class);
}
public static Intent getIntentForGallery(@NonNull Context context) {
Intent intent = getIntentForCameraCapture(context);
intent.putExtra(ARG_GALLERY, true);
return intent;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.avatar_selection_activity);
MediaSendViewModel viewModel = ViewModelProviders.of(this, new MediaSendViewModel.Factory(getApplication(), new MediaRepository())).get(MediaSendViewModel.class);
viewModel.setTransport(TransportOptions.getPushTransportOption(this));
if (isGalleryFirst()) {
onGalleryClicked();
} else {
onCameraSelected();
}
}
@Override
public void onCameraError() {
Toast.makeText(this, R.string.error, Toast.LENGTH_SHORT).show();
finish();
}
@Override
public void onImageCaptured(@NonNull byte[] data, int width, int height) {
Uri blobUri = BlobProvider.getInstance()
.forData(data)
.withMimeType(MediaUtil.IMAGE_JPEG)
.createForSingleSessionInMemory();
onMediaSelected(new Media(blobUri,
MediaUtil.IMAGE_JPEG,
System.currentTimeMillis(),
width,
height,
data.length,
0,
Optional.of(Media.ALL_MEDIA_BUCKET_ID),
Optional.absent(),
Optional.absent()));
}
@Override
public void onVideoCaptured(@NonNull FileDescriptor fd) {
throw new UnsupportedOperationException("Cannot set profile as video");
}
@Override
public void onVideoCaptureError() {
throw new AssertionError("This should never happen");
}
@Override
public void onGalleryClicked() {
if (isGalleryFirst() && popToRoot()) {
return;
}
MediaPickerFolderFragment fragment = MediaPickerFolderFragment.newInstance(this, null);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, fragment);
if (isCameraFirst()) {
transaction.addToBackStack(null);
}
transaction.commit();
}
@Override
public int getDisplayRotation() {
return getWindowManager().getDefaultDisplay().getRotation();
}
@Override
public void onCameraCountButtonClicked() {
throw new UnsupportedOperationException("Cannot select more than one photo");
}
@Override
public void onTouchEventsNeeded(boolean needed) {
}
@Override
public void onRequestFullScreen(boolean fullScreen, boolean hideKeyboard) {
}
@Override
public void onFolderSelected(@NonNull MediaFolder folder) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, MediaPickerItemFragment.newInstance(folder.getBucketId(), folder.getTitle(), 1, false))
.addToBackStack(null)
.commit();
}
@Override
public void onMediaSelected(@NonNull Media media) {
currentMedia = media;
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, ImageEditorFragment.newInstanceForAvatar(media.getUri()), IMAGE_EDITOR)
.addToBackStack(IMAGE_EDITOR)
.commit();
}
@Override
public void onCameraSelected() {
if (isCameraFirst() && popToRoot()) {
return;
}
Fragment fragment = CameraFragment.newInstanceForAvatarCapture();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, fragment, IMAGE_CAPTURE);
if (isGalleryFirst()) {
transaction.addToBackStack(null);
}
transaction.commit();
}
@Override
public void onDoneEditing() {
handleSave();
}
public boolean popToRoot() {
final int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
if (backStackCount == 0) {
return false;
}
for (int i = 0; i < backStackCount; i++) {
getSupportFragmentManager().popBackStack();
}
return true;
}
private boolean isGalleryFirst() {
return getIntent().getBooleanExtra(ARG_GALLERY, false);
}
private boolean isCameraFirst() {
return !isGalleryFirst();
}
private void handleSave() {
ImageEditorFragment fragment = (ImageEditorFragment) getSupportFragmentManager().findFragmentByTag(IMAGE_EDITOR);
if (fragment == null) {
throw new AssertionError();
}
ImageEditorFragment.Data data = (ImageEditorFragment.Data) fragment.saveState();
EditorModel model = data.readModel();
if (model == null) {
throw new AssertionError();
}
MediaRepository.transformMedia(this,
Collections.singletonList(currentMedia),
Collections.singletonMap(currentMedia, new ImageEditorModelRenderMediaTransform(model, AVATAR_DIMENSIONS)),
output -> {
Media transformed = output.get(currentMedia);
Intent result = new Intent();
result.putExtra(EXTRA_MEDIA, transformed);
setResult(RESULT_OK, result);
finish();
});
}
}