mirror of https://github.com/KokaKiwi/BarInsta
286 lines
13 KiB
Java
286 lines
13 KiB
Java
package awais.instagrabber.fragments.imageedit;
|
|
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.RectF;
|
|
import android.net.Uri;
|
|
import android.os.Bundle;
|
|
import android.os.Parcelable;
|
|
import android.util.Log;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
|
|
import androidx.activity.OnBackPressedCallback;
|
|
import androidx.activity.OnBackPressedDispatcher;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import androidx.fragment.app.Fragment;
|
|
import androidx.fragment.app.FragmentActivity;
|
|
import androidx.fragment.app.FragmentManager;
|
|
import androidx.fragment.app.FragmentTransaction;
|
|
import androidx.lifecycle.SavedStateHandle;
|
|
import androidx.lifecycle.ViewModelProvider;
|
|
import androidx.navigation.NavBackStackEntry;
|
|
import androidx.navigation.NavController;
|
|
import androidx.navigation.fragment.NavHostFragment;
|
|
|
|
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
|
import com.yalantis.ucrop.UCrop;
|
|
import com.yalantis.ucrop.UCropActivity;
|
|
import com.yalantis.ucrop.UCropFragment;
|
|
import com.yalantis.ucrop.UCropFragmentCallback;
|
|
|
|
import java.util.List;
|
|
|
|
import awais.instagrabber.R;
|
|
import awais.instagrabber.databinding.FragmentImageEditBinding;
|
|
import awais.instagrabber.fragments.imageedit.filters.filters.Filter;
|
|
import awais.instagrabber.models.SavedImageEditState;
|
|
import awais.instagrabber.utils.Utils;
|
|
import awais.instagrabber.viewmodels.ImageEditViewModel;
|
|
|
|
public class ImageEditFragment extends Fragment {
|
|
private static final String TAG = ImageEditFragment.class.getSimpleName();
|
|
private static final String ARGS_URI = "uri";
|
|
private static final String FILTERS_FRAGMENT_TAG = "Filters";
|
|
|
|
private FragmentImageEditBinding binding;
|
|
private ImageEditViewModel viewModel;
|
|
private ImageEditViewModel.Tab previousTab;
|
|
private FiltersFragment filtersFragment;
|
|
|
|
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
|
|
@Override
|
|
public void handleOnBackPressed() {
|
|
setEnabled(false);
|
|
remove();
|
|
if (previousTab != ImageEditViewModel.Tab.CROP
|
|
&& previousTab != ImageEditViewModel.Tab.TUNE
|
|
&& previousTab != ImageEditViewModel.Tab.FILTERS) {
|
|
return;
|
|
}
|
|
final FragmentManager fragmentManager = getChildFragmentManager();
|
|
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
|
fragmentTransaction.setReorderingAllowed(true)
|
|
.remove(previousTab == ImageEditViewModel.Tab.CROP ? uCropFragment : filtersFragment)
|
|
.commit();
|
|
viewModel.setCurrentTab(ImageEditViewModel.Tab.RESULT);
|
|
}
|
|
};
|
|
private FragmentActivity fragmentActivity;
|
|
private UCropFragment uCropFragment;
|
|
|
|
public static ImageEditFragment newInstance(final Uri uri) {
|
|
final Bundle args = new Bundle();
|
|
args.putParcelable(ARGS_URI, uri);
|
|
final ImageEditFragment fragment = new ImageEditFragment();
|
|
fragment.setArguments(args);
|
|
return fragment;
|
|
}
|
|
|
|
public ImageEditFragment() {}
|
|
|
|
@Override
|
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
fragmentActivity = getActivity();
|
|
viewModel = new ViewModelProvider(this).get(ImageEditViewModel.class);
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
|
|
binding = FragmentImageEditBinding.inflate(inflater, container, false);
|
|
return binding.getRoot();
|
|
}
|
|
|
|
@Override
|
|
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
|
init();
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
super.onDestroy();
|
|
}
|
|
|
|
@Override
|
|
public void onDestroyView() {
|
|
super.onDestroyView();
|
|
}
|
|
|
|
private void init() {
|
|
setupObservers();
|
|
final Bundle arguments = getArguments();
|
|
if (arguments == null) return;
|
|
final Parcelable parcelable = arguments.getParcelable(ARGS_URI);
|
|
Uri originalUri = null;
|
|
if (parcelable instanceof Uri) {
|
|
originalUri = (Uri) parcelable;
|
|
}
|
|
if (originalUri == null) return;
|
|
viewModel.setOriginalUri(originalUri);
|
|
viewModel.setCurrentTab(ImageEditViewModel.Tab.RESULT);
|
|
}
|
|
|
|
private void setupObservers() {
|
|
viewModel.isLoading().observe(getViewLifecycleOwner(), loading -> {});
|
|
viewModel.getCurrentTab().observe(getViewLifecycleOwner(), tab -> {
|
|
if (tab == null) return;
|
|
switch (tab) {
|
|
case RESULT:
|
|
setupResult();
|
|
break;
|
|
case CROP:
|
|
setupCropFragment();
|
|
break;
|
|
case TUNE:
|
|
case FILTERS:
|
|
setupFilterFragment();
|
|
break;
|
|
}
|
|
previousTab = tab;
|
|
});
|
|
viewModel.isCropped().observe(getViewLifecycleOwner(), isCropped -> binding.crop.setSelected(isCropped));
|
|
viewModel.isTuned().observe(getViewLifecycleOwner(), isTuned -> binding.tune.setSelected(isTuned));
|
|
viewModel.isFiltered().observe(getViewLifecycleOwner(), isFiltered -> binding.filters.setSelected(isFiltered));
|
|
viewModel.getResultUri().observe(getViewLifecycleOwner(), uri -> {
|
|
if (uri == null) {
|
|
binding.preview.setController(null);
|
|
return;
|
|
}
|
|
binding.preview.setController(Fresco.newDraweeControllerBuilder()
|
|
.setImageRequest(ImageRequestBuilder.newBuilderWithSource(uri)
|
|
.disableDiskCache()
|
|
.disableMemoryCache()
|
|
.build())
|
|
.build());
|
|
});
|
|
}
|
|
|
|
private void setupResult() {
|
|
binding.fragmentContainerView.setVisibility(View.GONE);
|
|
binding.cropBottomControls.setVisibility(View.GONE);
|
|
binding.preview.setVisibility(View.VISIBLE);
|
|
binding.resultBottomControls.setVisibility(View.VISIBLE);
|
|
binding.crop.setOnClickListener(v -> viewModel.setCurrentTab(ImageEditViewModel.Tab.CROP));
|
|
binding.tune.setOnClickListener(v -> viewModel.setCurrentTab(ImageEditViewModel.Tab.TUNE));
|
|
binding.filters.setOnClickListener(v -> viewModel.setCurrentTab(ImageEditViewModel.Tab.FILTERS));
|
|
binding.cancel.setOnClickListener(v -> {
|
|
viewModel.cancel();
|
|
final NavController navController = NavHostFragment.findNavController(this);
|
|
navController.navigateUp();
|
|
});
|
|
binding.done.setOnClickListener(v -> {
|
|
final Context context = getContext();
|
|
if (context == null) return;
|
|
Utils.mediaScanFile(context, viewModel.getDestinationFile(), (path, uri) -> {
|
|
final NavBackStackEntry navBackStackEntry = NavHostFragment.findNavController(this).getPreviousBackStackEntry();
|
|
if (navBackStackEntry == null) return;
|
|
final SavedStateHandle savedStateHandle = navBackStackEntry.getSavedStateHandle();
|
|
savedStateHandle.set("result", uri);
|
|
});
|
|
});
|
|
}
|
|
|
|
private void setupCropFragment() {
|
|
final Context context = getContext();
|
|
if (context == null) return;
|
|
binding.preview.setVisibility(View.GONE);
|
|
binding.resultBottomControls.setVisibility(View.GONE);
|
|
binding.fragmentContainerView.setVisibility(View.VISIBLE);
|
|
binding.cropBottomControls.setVisibility(View.VISIBLE);
|
|
final UCrop.Options options = new UCrop.Options();
|
|
options.setCompressionFormat(Bitmap.CompressFormat.JPEG);
|
|
options.setFreeStyleCropEnabled(true);
|
|
options.setAllowedGestures(UCropActivity.SCALE, UCropActivity.ROTATE, UCropActivity.ALL);
|
|
final UCrop uCrop = UCrop.of(viewModel.getOriginalUri(), viewModel.getCropDestinationUri()).withOptions(options);
|
|
final SavedImageEditState savedState = viewModel.getSavedImageEditState();
|
|
if (savedState != null && savedState.getCropImageMatrixValues() != null && savedState.getCropRect() != null) {
|
|
uCrop.withSavedState(savedState.getCropImageMatrixValues(), savedState.getCropRect());
|
|
}
|
|
uCropFragment = uCrop.getFragment(uCrop.getIntent(context).getExtras());
|
|
final FragmentManager fragmentManager = getChildFragmentManager();
|
|
uCropFragment.setCallback(new UCropFragmentCallback() {
|
|
@Override
|
|
public void loadingProgress(final boolean showLoader) {
|
|
Log.d(TAG, "loadingProgress: " + showLoader);
|
|
}
|
|
|
|
@Override
|
|
public void onCropFinish(final UCropFragment.UCropResult result) {
|
|
Log.d(TAG, "onCropFinish: " + result.mResultCode);
|
|
if (result.mResultCode == AppCompatActivity.RESULT_OK) {
|
|
final Intent resultData = result.mResultData;
|
|
final Bundle extras = resultData.getExtras();
|
|
if (extras == null) return;
|
|
final Object uri = extras.get(UCrop.EXTRA_OUTPUT_URI);
|
|
final Object imageMatrixValues = extras.get(UCrop.EXTRA_IMAGE_MATRIX_VALUES);
|
|
final Object cropRect = extras.get(UCrop.EXTRA_CROP_RECT);
|
|
if (uri instanceof Uri && imageMatrixValues instanceof float[] && cropRect instanceof RectF) {
|
|
Log.d(TAG, "onCropFinish: result uri: " + uri);
|
|
viewModel.setCropResult((float[]) imageMatrixValues, (RectF) cropRect);
|
|
viewModel.setCurrentTab(ImageEditViewModel.Tab.RESULT);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
|
fragmentTransaction.setReorderingAllowed(true)
|
|
.replace(R.id.fragment_container_view, uCropFragment, UCropFragment.TAG)
|
|
.commit();
|
|
if (!onBackPressedCallback.isEnabled()) {
|
|
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
|
|
onBackPressedCallback.setEnabled(true);
|
|
onBackPressedDispatcher.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
|
|
}
|
|
binding.cropCancel.setOnClickListener(v -> onBackPressedCallback.handleOnBackPressed());
|
|
binding.cropReset.setOnClickListener(v -> uCropFragment.reset());
|
|
binding.cropDone.setOnClickListener(v -> uCropFragment.cropAndSaveImage());
|
|
}
|
|
|
|
private void setupFilterFragment() {
|
|
binding.resultBottomControls.setVisibility(View.GONE);
|
|
binding.preview.setVisibility(View.GONE);
|
|
binding.cropBottomControls.setVisibility(View.GONE);
|
|
binding.fragmentContainerView.setVisibility(View.VISIBLE);
|
|
final Boolean isCropped = viewModel.isCropped().getValue();
|
|
final Uri uri = isCropped != null && isCropped ? viewModel.getCropDestinationUri() : viewModel.getOriginalUri();
|
|
final ImageEditViewModel.Tab value = viewModel.getCurrentTab().getValue();
|
|
final SavedImageEditState savedImageEditState = viewModel.getSavedImageEditState();
|
|
filtersFragment = FiltersFragment.newInstance(
|
|
uri,
|
|
viewModel.getDestinationUri(),
|
|
savedImageEditState.getAppliedTuningFilters(),
|
|
savedImageEditState.getAppliedFilter(),
|
|
value == null ? ImageEditViewModel.Tab.TUNE : value
|
|
);
|
|
final FragmentManager fragmentManager = getChildFragmentManager();
|
|
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
|
fragmentTransaction.setReorderingAllowed(true)
|
|
.replace(R.id.fragment_container_view, filtersFragment, FILTERS_FRAGMENT_TAG)
|
|
.commit();
|
|
if (!onBackPressedCallback.isEnabled()) {
|
|
final OnBackPressedDispatcher onBackPressedDispatcher = fragmentActivity.getOnBackPressedDispatcher();
|
|
onBackPressedCallback.setEnabled(true);
|
|
onBackPressedDispatcher.addCallback(getViewLifecycleOwner(), onBackPressedCallback);
|
|
}
|
|
filtersFragment.setCallback(new FiltersFragment.FilterCallback() {
|
|
@Override
|
|
public void onApply(final Uri uri, final List<Filter<?>> tuningFilters, final Filter<?> filter) {
|
|
viewModel.setAppliedFilters(tuningFilters, filter);
|
|
viewModel.setCurrentTab(ImageEditViewModel.Tab.RESULT);
|
|
}
|
|
|
|
@Override
|
|
public void onCancel() {
|
|
onBackPressedCallback.handleOnBackPressed();
|
|
}
|
|
});
|
|
}
|
|
}
|