Migrate Upload Package To View Binding from Butterknife (#5590)

* Butterknife to ViewBinding
* Butterknife to ViewBinding
* code cleanup and tests fixed
* code cleanup and optimised imports
This commit is contained in:
Shashank Kumar 2024-03-16 01:07:28 +05:30 committed by GitHub
parent 1b5df47362
commit f73c9dc4d3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 340 additions and 409 deletions

View file

@ -8,16 +8,12 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.widget.Button;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.view.SimpleDraweeView;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.databinding.FragmentSimilarImageDialogBinding;
import java.io.File; import java.io.File;
/** /**
@ -26,17 +22,11 @@ import java.io.File;
public class SimilarImageDialogFragment extends DialogFragment { public class SimilarImageDialogFragment extends DialogFragment {
@BindView(R.id.orginalImage)
SimpleDraweeView originalImage;
@BindView(R.id.possibleImage)
SimpleDraweeView possibleImage;
@BindView(R.id.postive_button)
Button positiveButton;
@BindView(R.id.negative_button)
Button negativeButton;
Callback callback;//Implemented interface from shareActivity Callback callback;//Implemented interface from shareActivity
Boolean gotResponse = false; Boolean gotResponse = false;
private FragmentSimilarImageDialogBinding binding;
public SimilarImageDialogFragment() { public SimilarImageDialogFragment() {
} }
public interface Callback { public interface Callback {
@ -51,17 +41,17 @@ public class SimilarImageDialogFragment extends DialogFragment {
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_similar_image_dialog, container, false); binding = FragmentSimilarImageDialogBinding.inflate(inflater, container, false);
ButterKnife.bind(this,view);
originalImage.setHierarchy(GenericDraweeHierarchyBuilder
binding.orginalImage.setHierarchy(GenericDraweeHierarchyBuilder
.newInstance(getResources()) .newInstance(getResources())
.setPlaceholderImage(VectorDrawableCompat.create(getResources(), .setPlaceholderImage(VectorDrawableCompat.create(getResources(),
R.drawable.ic_image_black_24dp,getContext().getTheme())) R.drawable.ic_image_black_24dp,getContext().getTheme()))
.setFailureImage(VectorDrawableCompat.create(getResources(), .setFailureImage(VectorDrawableCompat.create(getResources(),
R.drawable.ic_error_outline_black_24dp, getContext().getTheme())) R.drawable.ic_error_outline_black_24dp, getContext().getTheme()))
.build()); .build());
possibleImage.setHierarchy(GenericDraweeHierarchyBuilder binding.possibleImage.setHierarchy(GenericDraweeHierarchyBuilder
.newInstance(getResources()) .newInstance(getResources())
.setPlaceholderImage(VectorDrawableCompat.create(getResources(), .setPlaceholderImage(VectorDrawableCompat.create(getResources(),
R.drawable.ic_image_black_24dp,getContext().getTheme())) R.drawable.ic_image_black_24dp,getContext().getTheme()))
@ -69,10 +59,13 @@ public class SimilarImageDialogFragment extends DialogFragment {
R.drawable.ic_error_outline_black_24dp, getContext().getTheme())) R.drawable.ic_error_outline_black_24dp, getContext().getTheme()))
.build()); .build());
originalImage.setImageURI(Uri.fromFile(new File(getArguments().getString("originalImagePath")))); binding.orginalImage.setImageURI(Uri.fromFile(new File(getArguments().getString("originalImagePath"))));
possibleImage.setImageURI(Uri.fromFile(new File(getArguments().getString("possibleImagePath")))); binding.possibleImage.setImageURI(Uri.fromFile(new File(getArguments().getString("possibleImagePath"))));
return view; binding.postiveButton.setOnClickListener(v -> onPositiveButtonClicked());
binding.negativeButton.setOnClickListener(v -> onNegativeButtonClicked());
return binding.getRoot();
} }
@Override @Override
@ -96,17 +89,21 @@ public class SimilarImageDialogFragment extends DialogFragment {
super.onDismiss(dialog); super.onDismiss(dialog);
} }
@OnClick(R.id.negative_button)
public void onNegativeButtonClicked() { public void onNegativeButtonClicked() {
callback.onNegativeResponse(); callback.onNegativeResponse();
gotResponse = true; gotResponse = true;
dismiss(); dismiss();
} }
@OnClick(R.id.postive_button)
public void onPositiveButtonClicked() { public void onPositiveButtonClicked() {
callback.onPositiveResponse(); callback.onPositiveResponse();
gotResponse = true; gotResponse = true;
dismiss(); dismiss();
} }
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
} }

View file

@ -10,21 +10,16 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.facebook.drawee.view.SimpleDraweeView; import com.facebook.drawee.view.SimpleDraweeView;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.databinding.ItemUploadThumbnailBinding;
import fr.free.nrw.commons.filepicker.UploadableFile;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.filepicker.UploadableFile;
/** /**
* The adapter class for image thumbnails to be shown while uploading. * The adapter class for image thumbnails to be shown while uploading.
*/ */
@ -33,6 +28,8 @@ class ThumbnailsAdapter extends RecyclerView.Adapter<ThumbnailsAdapter.ViewHolde
List<UploadableFile> uploadableFiles; List<UploadableFile> uploadableFiles;
private Callback callback; private Callback callback;
private ItemUploadThumbnailBinding binding;
public ThumbnailsAdapter(Callback callback) { public ThumbnailsAdapter(Callback callback) {
this.uploadableFiles = new ArrayList<>(); this.uploadableFiles = new ArrayList<>();
this.callback = callback; this.callback = callback;
@ -51,8 +48,8 @@ class ThumbnailsAdapter extends RecyclerView.Adapter<ThumbnailsAdapter.ViewHolde
@NonNull @NonNull
@Override @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new ViewHolder(LayoutInflater.from(viewGroup.getContext()) binding = ItemUploadThumbnailBinding.inflate(LayoutInflater.from(viewGroup.getContext()), viewGroup, false);
.inflate(R.layout.item_upload_thumbnail, viewGroup, false)); return new ViewHolder(binding.getRoot());
} }
@Override @Override
@ -67,16 +64,16 @@ class ThumbnailsAdapter extends RecyclerView.Adapter<ThumbnailsAdapter.ViewHolde
public class ViewHolder extends RecyclerView.ViewHolder { public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.rl_container)
RelativeLayout rlContainer; RelativeLayout rlContainer;
@BindView(R.id.iv_thumbnail)
SimpleDraweeView background; SimpleDraweeView background;
@BindView(R.id.iv_error)
ImageView ivError; ImageView ivError;
public ViewHolder(@NonNull View itemView) { public ViewHolder(@NonNull View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView); rlContainer = binding.rlContainer;
background = binding.ivThumbnail;
ivError = binding.ivError;
} }
/** /**

View file

@ -21,28 +21,21 @@ import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.View; import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter; import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import androidx.work.ExistingWorkPolicy; import androidx.work.ExistingWorkPolicy;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.LoginActivity; import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.contributions.ContributionController; import fr.free.nrw.commons.contributions.ContributionController;
import fr.free.nrw.commons.databinding.ActivityUploadBinding;
import fr.free.nrw.commons.filepicker.Constants.RequestCodes; import fr.free.nrw.commons.filepicker.Constants.RequestCodes;
import fr.free.nrw.commons.filepicker.UploadableFile; import fr.free.nrw.commons.filepicker.UploadableFile;
import fr.free.nrw.commons.kvstore.BasicKvStore; import fr.free.nrw.commons.kvstore.BasicKvStore;
@ -93,28 +86,6 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Inject @Inject
LocationServiceManager locationManager; LocationServiceManager locationManager;
@BindView(R.id.cv_container_top_card)
CardView cvContainerTopCard;
@BindView(R.id.ll_container_top_card)
LinearLayout llContainerTopCard;
@BindView(R.id.rl_container_title)
RelativeLayout rlContainerTitle;
@BindView(R.id.tv_top_card_title)
TextView tvTopCardTitle;
@BindView(R.id.ib_toggle_top_card)
ImageButton ibToggleTopCard;
@BindView(R.id.rv_thumbnails)
RecyclerView rvThumbnails;
@BindView(R.id.vp_upload)
ViewPager vpUpload;
private boolean isTitleExpanded = true; private boolean isTitleExpanded = true;
private CompositeDisposable compositeDisposable; private CompositeDisposable compositeDisposable;
@ -169,12 +140,15 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
*/ */
private boolean isFragmentsSaved = false; private boolean isFragmentsSaved = false;
private ActivityUploadBinding binding;
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload); binding = ActivityUploadBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
/* /*
If Configuration of device is changed then get the new fragments If Configuration of device is changed then get the new fragments
@ -190,7 +164,6 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
} }
ButterKnife.bind(this);
compositeDisposable = new CompositeDisposable(); compositeDisposable = new CompositeDisposable();
init(); init();
nearbyPopupAnswers = new HashMap<>(); nearbyPopupAnswers = new HashMap<>();
@ -223,17 +196,17 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
} }
private void initThumbnailsRecyclerView() { private void initThumbnailsRecyclerView() {
rvThumbnails.setLayoutManager(new LinearLayoutManager(this, binding.rvThumbnails.setLayoutManager(new LinearLayoutManager(this,
LinearLayoutManager.HORIZONTAL, false)); LinearLayoutManager.HORIZONTAL, false));
thumbnailsAdapter = new ThumbnailsAdapter(() -> currentSelectedPosition); thumbnailsAdapter = new ThumbnailsAdapter(() -> currentSelectedPosition);
rvThumbnails.setAdapter(thumbnailsAdapter); binding.rvThumbnails.setAdapter(thumbnailsAdapter);
} }
private void initViewPager() { private void initViewPager() {
uploadImagesAdapter = new UploadImageAdapter(getSupportFragmentManager()); uploadImagesAdapter = new UploadImageAdapter(getSupportFragmentManager());
vpUpload.setAdapter(uploadImagesAdapter); binding.vpUpload.setAdapter(uploadImagesAdapter);
vpUpload.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { binding.vpUpload.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override @Override
public void onPageScrolled(int position, float positionOffset, public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) { int positionOffsetPixels) {
@ -244,10 +217,10 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
public void onPageSelected(int position) { public void onPageSelected(int position) {
currentSelectedPosition = position; currentSelectedPosition = position;
if (position >= uploadableFiles.size()) { if (position >= uploadableFiles.size()) {
cvContainerTopCard.setVisibility(View.GONE); binding.cvContainerTopCard.setVisibility(View.GONE);
} else { } else {
thumbnailsAdapter.notifyDataSetChanged(); thumbnailsAdapter.notifyDataSetChanged();
cvContainerTopCard.setVisibility(View.VISIBLE); binding.cvContainerTopCard.setVisibility(View.VISIBLE);
} }
} }
@ -298,14 +271,14 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
if (hasAllPermissions) { if (hasAllPermissions) {
// All required permissions are granted, so enable UI elements and perform actions // All required permissions are granted, so enable UI elements and perform actions
receiveSharedItems(); receiveSharedItems();
cvContainerTopCard.setVisibility(View.VISIBLE); binding.cvContainerTopCard.setVisibility(View.VISIBLE);
} else { } else {
// Permissions are missing // Permissions are missing
cvContainerTopCard.setVisibility(View.INVISIBLE); binding.cvContainerTopCard.setVisibility(View.INVISIBLE);
if(showPermissionsDialog){ if(showPermissionsDialog){
checkPermissionsAndPerformAction(this, checkPermissionsAndPerformAction(this,
() -> { () -> {
cvContainerTopCard.setVisibility(View.VISIBLE); binding.cvContainerTopCard.setVisibility(View.VISIBLE);
this.receiveSharedItems(); this.receiveSharedItems();
},() -> { },() -> {
this.showPermissionsDialog = true; this.showPermissionsDialog = true;
@ -379,7 +352,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override @Override
public void showHideTopCard(boolean shouldShow) { public void showHideTopCard(boolean shouldShow) {
llContainerTopCard.setVisibility(shouldShow ? View.VISIBLE : View.GONE); binding.llContainerTopCard.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
} }
@Override @Override
@ -392,7 +365,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override @Override
public void updateTopCardTitle() { public void updateTopCardTitle() {
tvTopCardTitle.setText(getResources() binding.tvTopCardTitle.setText(getResources()
.getQuantityString(R.plurals.upload_count_title, uploadableFiles.size(), uploadableFiles.size())); .getQuantityString(R.plurals.upload_count_title, uploadableFiles.size(), uploadableFiles.size()));
} }
@ -475,9 +448,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
> 1) {//If there is only file, no need to show the image thumbnails > 1) {//If there is only file, no need to show the image thumbnails
thumbnailsAdapter.setUploadableFiles(uploadableFiles); thumbnailsAdapter.setUploadableFiles(uploadableFiles);
} else { } else {
llContainerTopCard.setVisibility(View.GONE); binding.llContainerTopCard.setVisibility(View.GONE);
} }
tvTopCardTitle.setText(getResources() binding.tvTopCardTitle.setText(getResources()
.getQuantityString(R.plurals.upload_count_title, uploadableFiles.size(), uploadableFiles.size())); .getQuantityString(R.plurals.upload_count_title, uploadableFiles.size(), uploadableFiles.size()));
@ -568,7 +541,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
public void changeThumbnail(int index, String filepath) { public void changeThumbnail(int index, String filepath) {
uploadableFiles.remove(index); uploadableFiles.remove(index);
uploadableFiles.add(index, new UploadableFile(new File(filepath))); uploadableFiles.add(index, new UploadableFile(new File(filepath)));
rvThumbnails.getAdapter().notifyDataSetChanged(); binding.rvThumbnails.getAdapter().notifyDataSetChanged();
} }
@Override @Override
@ -642,9 +615,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override @Override
public void onNextButtonClicked(int index) { public void onNextButtonClicked(int index) {
if (index < fragments.size() - 1) { if (index < fragments.size() - 1) {
vpUpload.setCurrentItem(index + 1, false); binding.vpUpload.setCurrentItem(index + 1, false);
fragments.get(index + 1).onBecameVisible(); fragments.get(index + 1).onBecameVisible();
((LinearLayoutManager) rvThumbnails.getLayoutManager()) ((LinearLayoutManager) binding.rvThumbnails.getLayoutManager())
.scrollToPositionWithOffset((index > 0) ? index-1 : 0, 0); .scrollToPositionWithOffset((index > 0) ? index-1 : 0, 0);
} else { } else {
presenter.handleSubmit(); presenter.handleSubmit();
@ -654,9 +627,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override @Override
public void onPreviousButtonClicked(int index) { public void onPreviousButtonClicked(int index) {
if (index != 0) { if (index != 0) {
vpUpload.setCurrentItem(index - 1, true); binding.vpUpload.setCurrentItem(index - 1, true);
fragments.get(index - 1).onBecameVisible(); fragments.get(index - 1).onBecameVisible();
((LinearLayoutManager) rvThumbnails.getLayoutManager()) ((LinearLayoutManager) binding.rvThumbnails.getLayoutManager())
.scrollToPositionWithOffset((index > 3) ? index-2 : 0, 0); .scrollToPositionWithOffset((index > 3) ? index-2 : 0, 0);
} }
} }
@ -691,7 +664,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
} }
uploadImagesAdapter.setFragments(fragments); uploadImagesAdapter.setFragments(fragments);
vpUpload.setOffscreenPageLimit(fragments.size()); binding.vpUpload.setOffscreenPageLimit(fragments.size());
} }
} }
@ -719,9 +692,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
*/ */
@Override @Override
public void highlightNextImageOnCancelledImage(int index, int maxSize) { public void highlightNextImageOnCancelledImage(int index, int maxSize) {
if (vpUpload != null && index < (maxSize)) { if (binding.vpUpload != null && index < (maxSize)) {
vpUpload.setCurrentItem(index + 1, false); binding.vpUpload.setCurrentItem(index + 1, false);
vpUpload.setCurrentItem(index, false); binding.vpUpload.setCurrentItem(index, false);
} }
} }
@ -810,9 +783,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override @Override
public void onNextButtonClicked(int index) { public void onNextButtonClicked(int index) {
if (index < fragments.size() - 1) { if (index < fragments.size() - 1) {
vpUpload.setCurrentItem(index + 1, false); binding.vpUpload.setCurrentItem(index + 1, false);
fragments.get(index + 1).onBecameVisible(); fragments.get(index + 1).onBecameVisible();
((LinearLayoutManager) rvThumbnails.getLayoutManager()) ((LinearLayoutManager) binding.rvThumbnails.getLayoutManager())
.scrollToPositionWithOffset((index > 0) ? index-1 : 0, 0); .scrollToPositionWithOffset((index > 0) ? index-1 : 0, 0);
} else { } else {
presenter.handleSubmit(); presenter.handleSubmit();
@ -822,9 +795,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override @Override
public void onPreviousButtonClicked(int index) { public void onPreviousButtonClicked(int index) {
if (index != 0) { if (index != 0) {
vpUpload.setCurrentItem(index - 1, true); binding.vpUpload.setCurrentItem(index - 1, true);
fragments.get(index - 1).onBecameVisible(); fragments.get(index - 1).onBecameVisible();
((LinearLayoutManager) rvThumbnails.getLayoutManager()) ((LinearLayoutManager) binding.rvThumbnails.getLayoutManager())
.scrollToPositionWithOffset((index > 3) ? index-2 : 0, 0); .scrollToPositionWithOffset((index > 3) ? index-2 : 0, 0);
} }
} }
@ -866,9 +839,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@OnClick(R.id.rl_container_title) @OnClick(R.id.rl_container_title)
public void onRlContainerTitleClicked() { public void onRlContainerTitleClicked() {
rvThumbnails.setVisibility(isTitleExpanded ? View.GONE : View.VISIBLE); binding.rvThumbnails.setVisibility(isTitleExpanded ? View.GONE : View.VISIBLE);
isTitleExpanded = !isTitleExpanded; isTitleExpanded = !isTitleExpanded;
ibToggleTopCard.setRotation(ibToggleTopCard.getRotation() + 180); binding.ibToggleTopCard.setRotation(binding.ibToggleTopCard.getRotation() + 180);
} }
@Override @Override

View file

@ -1,9 +1,7 @@
package fr.free.nrw.commons.upload; package fr.free.nrw.commons.upload;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
/** /**

View file

@ -25,10 +25,9 @@ import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.databinding.RowItemDescriptionBinding;
import fr.free.nrw.commons.recentlanguages.Language; import fr.free.nrw.commons.recentlanguages.Language;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter; import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao; import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
@ -61,6 +60,8 @@ public class UploadMediaDetailAdapter extends
private SelectedVoiceIcon selectedVoiceIcon; private SelectedVoiceIcon selectedVoiceIcon;
private static final int REQUEST_CODE_FOR_VOICE_INPUT = 1213; private static final int REQUEST_CODE_FOR_VOICE_INPUT = 1213;
private RowItemDescriptionBinding binding;
public UploadMediaDetailAdapter(Fragment fragment, String savedLanguageValue, public UploadMediaDetailAdapter(Fragment fragment, String savedLanguageValue,
RecentLanguagesDao recentLanguagesDao) { RecentLanguagesDao recentLanguagesDao) {
uploadMediaDetails = new ArrayList<>(); uploadMediaDetails = new ArrayList<>();
@ -100,8 +101,9 @@ public class UploadMediaDetailAdapter extends
@NonNull @NonNull
@Override @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()) LayoutInflater inflater = LayoutInflater.from(parent.getContext());
.inflate(R.layout.row_item_description, parent, false)); binding = RowItemDescriptionBinding.inflate(inflater, parent, false);
return new ViewHolder(binding.getRoot());
} }
/** /**
@ -203,44 +205,34 @@ public class UploadMediaDetailAdapter extends
public class ViewHolder extends RecyclerView.ViewHolder { public class ViewHolder extends RecyclerView.ViewHolder {
@Nullable TextView descriptionLanguages ;
@BindView(R.id.description_languages)
TextView descriptionLanguages;
@BindView(R.id.description_item_edit_text)
PasteSensitiveTextInputEditText descItemEditText; PasteSensitiveTextInputEditText descItemEditText;
@BindView(R.id.description_item_edit_text_input_layout)
TextInputLayout descInputLayout; TextInputLayout descInputLayout;
@BindView(R.id.caption_item_edit_text)
PasteSensitiveTextInputEditText captionItemEditText; PasteSensitiveTextInputEditText captionItemEditText;
@BindView(R.id.caption_item_edit_text_input_layout)
TextInputLayout captionInputLayout; TextInputLayout captionInputLayout;
@BindView(R.id.btn_remove)
ImageView removeButton; ImageView removeButton;
@BindView(R.id.btn_add)
ImageView addButton; ImageView addButton;
@BindView(R.id.cl_parent)
ConstraintLayout clParent; ConstraintLayout clParent;
@BindView(R.id.ll_write_better_caption)
LinearLayout betterCaptionLinearLayout; LinearLayout betterCaptionLinearLayout;
@BindView(R.id.ll_write_better_description)
LinearLayout betterDescriptionLinearLayout; LinearLayout betterDescriptionLinearLayout;
private
AbstractTextWatcher captionListener; AbstractTextWatcher captionListener;
AbstractTextWatcher descriptionListener; AbstractTextWatcher descriptionListener;
public ViewHolder(View itemView) { public ViewHolder(View itemView) {
super(itemView); super(itemView);
ButterKnife.bind(this, itemView);
Timber.i("descItemEditText:" + descItemEditText); Timber.i("descItemEditText:" + descItemEditText);
} }
@ -248,6 +240,18 @@ public class UploadMediaDetailAdapter extends
UploadMediaDetail uploadMediaDetail = uploadMediaDetails.get(position); UploadMediaDetail uploadMediaDetail = uploadMediaDetails.get(position);
Timber.d("UploadMediaDetail is " + uploadMediaDetail); Timber.d("UploadMediaDetail is " + uploadMediaDetail);
descriptionLanguages = binding.descriptionLanguages;
descItemEditText = binding.descriptionItemEditText;
descInputLayout = binding.descriptionItemEditTextInputLayout;
captionItemEditText = binding.captionItemEditText;
captionInputLayout = binding.captionItemEditTextInputLayout;
removeButton = binding.btnRemove;
addButton = binding.btnAdd;
clParent = binding.clParent;
betterCaptionLinearLayout = binding.llWriteBetterCaption;
betterDescriptionLinearLayout = binding.llWriteBetterDescription;
descriptionLanguages.setFocusable(false); descriptionLanguages.setFocusable(false);
captionItemEditText.addTextChangedListener(new AbstractTextWatcher( captionItemEditText.addTextChangedListener(new AbstractTextWatcher(
value -> { value -> {
@ -495,7 +499,9 @@ public class UploadMediaDetailAdapter extends
((RecentLanguagesAdapter) adapterView ((RecentLanguagesAdapter) adapterView
.getAdapter()).setSelectedLangCode(languageCode); .getAdapter()).setSelectedLangCode(languageCode);
Timber.d("Description language code is: %s", languageCode); Timber.d("Description language code is: %s", languageCode);
descriptionLanguages.setText(languageCode); if (descriptionLanguages!=null) {
descriptionLanguages.setText(languageCode);
}
dialog.dismiss(); dialog.dismiss();
} }
@ -528,12 +534,15 @@ public class UploadMediaDetailAdapter extends
languageHistoryListView.setVisibility(View.VISIBLE); languageHistoryListView.setVisibility(View.VISIBLE);
recentLanguagesTextView.setVisibility(View.VISIBLE); recentLanguagesTextView.setVisibility(View.VISIBLE);
separator.setVisibility(View.VISIBLE); separator.setVisibility(View.VISIBLE);
final RecentLanguagesAdapter recentLanguagesAdapter
= new RecentLanguagesAdapter( if (descriptionLanguages!=null) {
descriptionLanguages.getContext(), final RecentLanguagesAdapter recentLanguagesAdapter
recentLanguagesDao.getRecentLanguages(), = new RecentLanguagesAdapter(
selectedLanguages); descriptionLanguages.getContext(),
languageHistoryListView.setAdapter(recentLanguagesAdapter); recentLanguagesDao.getRecentLanguages(),
selectedLanguages);
languageHistoryListView.setAdapter(recentLanguagesAdapter);
}
} }
} }

View file

@ -201,8 +201,9 @@ class CategoriesPresenter @Inject constructor(
* @param wikiText current WikiText from server * @param wikiText current WikiText from server
*/ */
override fun updateCategories(media: Media, wikiText: String) { override fun updateCategories(media: Media, wikiText: String) {
//check if view.existingCategories is null
if (repository.selectedCategories.isNotEmpty() if (repository.selectedCategories.isNotEmpty()
|| repository.selectedExistingCategories.size != view.existingCategories.size || (view.existingCategories != null && repository.selectedExistingCategories.size != view.existingCategories.size)
) { ) {
val selectedCategories: MutableList<String> = val selectedCategories: MutableList<String> =
(repository.selectedCategories.map { it.name }.toMutableList() (repository.selectedCategories.map { it.name }.toMutableList()

View file

@ -12,28 +12,19 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.google.android.material.textfield.TextInputLayout;
import com.jakewharton.rxbinding2.view.RxView; import com.jakewharton.rxbinding2.view.RxView;
import com.jakewharton.rxbinding2.widget.RxTextView; import com.jakewharton.rxbinding2.widget.RxTextView;
import fr.free.nrw.commons.Media; import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.category.CategoryItem; import fr.free.nrw.commons.category.CategoryItem;
import fr.free.nrw.commons.contributions.ContributionsFragment; import fr.free.nrw.commons.contributions.ContributionsFragment;
import fr.free.nrw.commons.databinding.UploadCategoriesFragmentBinding;
import fr.free.nrw.commons.media.MediaDetailFragment; import fr.free.nrw.commons.media.MediaDetailFragment;
import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText;
import fr.free.nrw.commons.upload.UploadActivity; import fr.free.nrw.commons.upload.UploadActivity;
import fr.free.nrw.commons.upload.UploadBaseFragment; import fr.free.nrw.commons.upload.UploadBaseFragment;
import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.DialogUtil;
@ -48,25 +39,6 @@ import timber.log.Timber;
public class UploadCategoriesFragment extends UploadBaseFragment implements CategoriesContract.View { public class UploadCategoriesFragment extends UploadBaseFragment implements CategoriesContract.View {
@BindView(R.id.tv_title)
TextView tvTitle;
@BindView(R.id.tv_subtitle)
TextView tvSubTitle;
@BindView(R.id.til_container_search)
TextInputLayout tilContainerEtSearch;
@BindView(R.id.et_search)
PasteSensitiveTextInputEditText etSearch;
@BindView(R.id.pb_categories)
ProgressBar pbCategories;
@BindView(R.id.rv_categories)
RecyclerView rvCategories;
@BindView(R.id.tooltip)
ImageView tooltip;
@BindView(R.id.btn_next)
Button btnNext;
@BindView(R.id.btn_previous)
Button btnPrevious;
@Inject @Inject
CategoriesContract.UserActionListener presenter; CategoriesContract.UserActionListener presenter;
private UploadCategoryAdapter adapter; private UploadCategoryAdapter adapter;
@ -85,17 +57,19 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
private String wikiText; private String wikiText;
private String nearbyPlaceCategory; private String nearbyPlaceCategory;
private UploadCategoriesFragmentBinding binding;
@Nullable @Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.upload_categories_fragment, container, false); binding = UploadCategoriesFragmentBinding.inflate(inflater, container, false);
return binding.getRoot();
} }
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
final Bundle bundle = getArguments(); final Bundle bundle = getArguments();
if (bundle != null) { if (bundle != null) {
media = bundle.getParcelable("Existing_Categories"); media = bundle.getParcelable("Existing_Categories");
@ -108,20 +82,23 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
} }
private void init() { private void init() {
if (binding == null) {
return;
}
if (media == null) { if (media == null) {
if (callback != null) { if (callback != null) {
tvTitle.setText(getString(R.string.step_count, callback.getIndexInViewFlipper(this) + 1, binding.tvTitle.setText(getString(R.string.step_count, callback.getIndexInViewFlipper(this) + 1,
callback.getTotalNumberOfSteps(), getString(R.string.categories_activity_title))); callback.getTotalNumberOfSteps(), getString(R.string.categories_activity_title)));
} }
} else { } else {
tvTitle.setText(R.string.edit_categories); binding.tvTitle.setText(R.string.edit_categories);
tvSubTitle.setVisibility(View.GONE); binding.tvSubtitle.setVisibility(View.GONE);
btnNext.setText(R.string.menu_save_categories); binding.btnNext.setText(R.string.menu_save_categories);
btnPrevious.setText(R.string.menu_cancel_upload); binding.btnPrevious.setText(R.string.menu_cancel_upload);
} }
setTvSubTitle(); setTvSubTitle();
tooltip.setOnClickListener(new OnClickListener() { binding.tooltip.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
DialogUtil.showAlertDialog(getActivity(), getString(R.string.categories_activity_title), getString(R.string.categories_tooltip), getString(android.R.string.ok), null, true); DialogUtil.showAlertDialog(getActivity(), getString(R.string.categories_activity_title), getString(R.string.categories_tooltip), getString(android.R.string.ok), null, true);
@ -132,14 +109,20 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
} else { } else {
presenter.onAttachViewWithMedia(this, media); presenter.onAttachViewWithMedia(this, media);
} }
binding.btnNext.setOnClickListener(v -> onNextButtonClicked());
binding.btnPrevious.setOnClickListener(v -> onPreviousButtonClicked());
initRecyclerView(); initRecyclerView();
addTextChangeListenerToEtSearch(); addTextChangeListenerToEtSearch();
} }
private void addTextChangeListenerToEtSearch() { private void addTextChangeListenerToEtSearch() {
subscribe = RxTextView.textChanges(etSearch) if (binding == null) {
.doOnEach(v -> tilContainerEtSearch.setError(null)) return;
.takeUntil(RxView.detaches(etSearch)) }
subscribe = RxTextView.textChanges(binding.etSearch)
.doOnEach(v -> binding.tilContainerSearch.setError(null))
.takeUntil(RxView.detaches(binding.etSearch))
.debounce(500, TimeUnit.MILLISECONDS) .debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(filter -> searchForCategory(filter.toString()), Timber::e); .subscribe(filter -> searchForCategory(filter.toString()), Timber::e);
@ -154,7 +137,7 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
if (activity instanceof UploadActivity) { if (activity instanceof UploadActivity) {
final boolean isMultipleFileSelected = ((UploadActivity) activity).getIsMultipleFilesSelected(); final boolean isMultipleFileSelected = ((UploadActivity) activity).getIsMultipleFilesSelected();
if (!isMultipleFileSelected) { if (!isMultipleFileSelected) {
tvSubTitle.setVisibility(View.GONE); binding.tvSubtitle.setVisibility(View.GONE);
} }
} }
} }
@ -168,8 +151,11 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
presenter.onCategoryItemClicked(categoryItem); presenter.onCategoryItemClicked(categoryItem);
return Unit.INSTANCE; return Unit.INSTANCE;
}, nearbyPlaceCategory); }, nearbyPlaceCategory);
rvCategories.setLayoutManager(new LinearLayoutManager(getContext()));
rvCategories.setAdapter(adapter); if (binding!=null) {
binding.rvCategories.setLayoutManager(new LinearLayoutManager(getContext()));
binding.rvCategories.setAdapter(adapter);
}
} }
@Override @Override
@ -181,17 +167,23 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
@Override @Override
public void showProgress(boolean shouldShow) { public void showProgress(boolean shouldShow) {
pbCategories.setVisibility(shouldShow ? View.VISIBLE : View.GONE); if (binding != null) {
binding.pbCategories.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
}
} }
@Override @Override
public void showError(String error) { public void showError(String error) {
tilContainerEtSearch.setError(error); if (binding != null) {
binding.tilContainerSearch.setError(error);
}
} }
@Override @Override
public void showError(int stringResourceId) { public void showError(int stringResourceId) {
tilContainerEtSearch.setError(getString(stringResourceId)); if (binding != null) {
binding.tilContainerSearch.setError(getString(stringResourceId));
}
} }
@Override @Override
@ -203,16 +195,20 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
} }
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
if (binding == null) {
return;
}
// Nested waiting for search result data to load into the category // Nested waiting for search result data to load into the category
// list and smoothly scroll to the top of the search result list. // list and smoothly scroll to the top of the search result list.
rvCategories.post(new Runnable() { binding.rvCategories.post(new Runnable() {
@Override @Override
public void run() { public void run() {
rvCategories.smoothScrollToPosition(0); binding.rvCategories.smoothScrollToPosition(0);
rvCategories.post(new Runnable() { binding.rvCategories.post(new Runnable() {
@Override @Override
public void run() { public void run() {
rvCategories.smoothScrollToPosition(0); binding.rvCategories.smoothScrollToPosition(0);
} }
}); });
} }
@ -284,7 +280,9 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
*/ */
@Override @Override
public void dismissProgressDialog() { public void dismissProgressDialog() {
progressDialog.dismiss(); if (progressDialog != null) {
progressDialog.dismiss();
}
} }
/** /**
@ -297,7 +295,6 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
mediaDetailFragment.updateCategories(); mediaDetailFragment.updateCategories();
} }
@OnClick(R.id.btn_next)
public void onNextButtonClicked() { public void onNextButtonClicked() {
if (media != null) { if (media != null) {
presenter.updateCategories(media, wikiText); presenter.updateCategories(media, wikiText);
@ -306,7 +303,6 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
} }
} }
@OnClick(R.id.btn_previous)
public void onPreviousButtonClicked() { public void onPreviousButtonClicked() {
if (media != null) { if (media != null) {
presenter.clearPreviousSelection(); presenter.clearPreviousSelection();
@ -325,8 +321,11 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
@Override @Override
protected void onBecameVisible() { protected void onBecameVisible() {
super.onBecameVisible(); super.onBecameVisible();
if (binding == null) {
return;
}
presenter.selectCategories(); presenter.selectCategories();
final Editable text = etSearch.getText(); final Editable text = binding.etSearch.getText();
if (text != null) { if (text != null) {
presenter.searchForCategories(text.toString()); presenter.searchForCategories(text.toString());
} }
@ -340,9 +339,9 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
super.onResume(); super.onResume();
if (media != null) { if (media != null) {
etSearch.setOnKeyListener((v, keyCode, event) -> { binding.etSearch.setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK) { if (keyCode == KeyEvent.KEYCODE_BACK) {
etSearch.clearFocus(); binding.etSearch.clearFocus();
presenter.clearPreviousSelection(); presenter.clearPreviousSelection();
final MediaDetailFragment mediaDetailFragment = (MediaDetailFragment) getParentFragment(); final MediaDetailFragment mediaDetailFragment = (MediaDetailFragment) getParentFragment();
assert mediaDetailFragment != null; assert mediaDetailFragment != null;
@ -392,4 +391,10 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
.show(); .show();
} }
} }
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
} }

View file

@ -10,29 +10,20 @@ import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.google.android.material.textfield.TextInputLayout;
import com.jakewharton.rxbinding2.view.RxView; import com.jakewharton.rxbinding2.view.RxView;
import com.jakewharton.rxbinding2.widget.RxTextView; import com.jakewharton.rxbinding2.widget.RxTextView;
import fr.free.nrw.commons.Media; import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.ContributionsFragment; import fr.free.nrw.commons.contributions.ContributionsFragment;
import fr.free.nrw.commons.databinding.UploadDepictsFragmentBinding;
import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.media.MediaDetailFragment; import fr.free.nrw.commons.media.MediaDetailFragment;
import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText;
import fr.free.nrw.commons.upload.UploadActivity; import fr.free.nrw.commons.upload.UploadActivity;
import fr.free.nrw.commons.upload.UploadBaseFragment; import fr.free.nrw.commons.upload.UploadBaseFragment;
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
@ -53,24 +44,6 @@ import timber.log.Timber;
*/ */
public class DepictsFragment extends UploadBaseFragment implements DepictsContract.View { public class DepictsFragment extends UploadBaseFragment implements DepictsContract.View {
@BindView(R.id.depicts_title)
TextView depictsTitle;
@BindView(R.id.depicts_subtitle)
TextView depictsSubTitle;
@BindView(R.id.depicts_search_container)
TextInputLayout depictsSearchContainer;
@BindView(R.id.depicts_search)
PasteSensitiveTextInputEditText depictsSearch;
@BindView(R.id.depictsSearchInProgress)
ProgressBar depictsSearchInProgress;
@BindView(R.id.depicts_recycler_view)
RecyclerView depictsRecyclerView;
@BindView(R.id.tooltip)
ImageView tooltip;
@BindView(R.id.depicts_next)
Button btnNext;
@BindView(R.id.depicts_previous)
Button btnPrevious;
@Inject @Inject
@Named("default_preferences") @Named("default_preferences")
public public
@ -88,18 +61,20 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
private int count; private int count;
private Place nearbyPlace; private Place nearbyPlace;
private UploadDepictsFragmentBinding binding;
@Nullable @Nullable
@Override @Override
public android.view.View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, public android.view.View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.upload_depicts_fragment, container, false); binding = UploadDepictsFragmentBinding.inflate(inflater, container, false);
return binding.getRoot();
} }
@Override @Override
public void onViewCreated(@NonNull android.view.View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull android.view.View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
Bundle bundle = getArguments(); Bundle bundle = getArguments();
if (bundle != null) { if (bundle != null) {
media = bundle.getParcelable("Existing_Depicts"); media = bundle.getParcelable("Existing_Depicts");
@ -117,18 +92,22 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
*/ */
private void init() { private void init() {
if (binding == null) {
return;
}
if (media == null) { if (media == null) {
depictsTitle.setText(String.format(getString(R.string.step_count), callback.getIndexInViewFlipper(this) + 1, binding.depictsTitle.setText(String.format(getString(R.string.step_count), callback.getIndexInViewFlipper(this) + 1,
callback.getTotalNumberOfSteps(), getString(R.string.depicts_step_title))); callback.getTotalNumberOfSteps(), getString(R.string.depicts_step_title)));
} else { } else {
depictsTitle.setText(R.string.edit_depictions); binding.depictsTitle.setText(R.string.edit_depictions);
depictsSubTitle.setVisibility(View.GONE); binding.depictsSubtitle.setVisibility(View.GONE);
btnNext.setText(R.string.menu_save_categories); binding.depictsNext.setText(R.string.menu_save_categories);
btnPrevious.setText(R.string.menu_cancel_upload); binding.depictsPrevious.setText(R.string.menu_cancel_upload);
} }
setDepictsSubTitle(); setDepictsSubTitle();
tooltip.setOnClickListener(v -> DialogUtil binding.tooltip.setOnClickListener(v -> DialogUtil
.showAlertDialog(getActivity(), getString(R.string.depicts_step_title), .showAlertDialog(getActivity(), getString(R.string.depicts_step_title),
getString(R.string.depicts_tooltip), getString(android.R.string.ok), null, true)); getString(R.string.depicts_tooltip), getString(android.R.string.ok), null, true));
if (media == null) { if (media == null) {
@ -138,6 +117,9 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
} }
initRecyclerView(); initRecyclerView();
addTextChangeListenerToSearchBox(); addTextChangeListenerToSearchBox();
binding.depictsNext.setOnClickListener(v->onNextButtonClicked());
binding.depictsPrevious.setOnClickListener(v->onPreviousButtonClicked());
} }
/** /**
@ -149,7 +131,7 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
if (activity instanceof UploadActivity) { if (activity instanceof UploadActivity) {
final boolean isMultipleFileSelected = ((UploadActivity) activity).getIsMultipleFilesSelected(); final boolean isMultipleFileSelected = ((UploadActivity) activity).getIsMultipleFilesSelected();
if (!isMultipleFileSelected) { if (!isMultipleFileSelected) {
depictsSubTitle.setVisibility(View.GONE); binding.depictsSubtitle.setVisibility(View.GONE);
} }
} }
} }
@ -169,8 +151,11 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
return Unit.INSTANCE; return Unit.INSTANCE;
}, nearbyPlace); }, nearbyPlace);
} }
depictsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); if (binding == null) {
depictsRecyclerView.setAdapter(adapter); return;
}
binding.depictsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
binding.depictsRecyclerView.setAdapter(adapter);
} }
@Override @Override
@ -221,15 +206,21 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
@Override @Override
public void showProgress(boolean shouldShow) { public void showProgress(boolean shouldShow) {
depictsSearchInProgress.setVisibility(shouldShow ? View.VISIBLE : View.GONE); if (binding == null) {
return;
}
binding.depictsSearchInProgress.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
} }
@Override @Override
public void showError(Boolean value) { public void showError(Boolean value) {
if (binding == null) {
return;
}
if (value) { if (value) {
depictsSearchContainer.setError(getString(R.string.no_depiction_found)); binding.depictsSearchContainer.setError(getString(R.string.no_depiction_found));
} else { } else {
depictsSearchContainer.setErrorEnabled(false); binding.depictsSearchContainer.setErrorEnabled(false);
} }
} }
@ -249,16 +240,19 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
} }
} }
if (binding == null) {
return;
}
// Nested waiting for search result data to load into the depicted item // Nested waiting for search result data to load into the depicted item
// list and smoothly scroll to the top of the search result list. // list and smoothly scroll to the top of the search result list.
depictsRecyclerView.post(new Runnable() { binding.depictsRecyclerView.post(new Runnable() {
@Override @Override
public void run() { public void run() {
depictsRecyclerView.smoothScrollToPosition(0); binding.depictsRecyclerView.smoothScrollToPosition(0);
depictsRecyclerView.post(new Runnable() { binding.depictsRecyclerView.post(new Runnable() {
@Override @Override
public void run() { public void run() {
depictsRecyclerView.smoothScrollToPosition(0); binding.depictsRecyclerView.smoothScrollToPosition(0);
} }
}); });
} }
@ -320,7 +314,6 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
/** /**
* Determines the calling fragment by media nullability and act accordingly * Determines the calling fragment by media nullability and act accordingly
*/ */
@OnClick(R.id.depicts_next)
public void onNextButtonClicked() { public void onNextButtonClicked() {
if(media != null){ if(media != null){
presenter.updateDepictions(media); presenter.updateDepictions(media);
@ -332,7 +325,6 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
/** /**
* Determines the calling fragment by media nullability and act accordingly * Determines the calling fragment by media nullability and act accordingly
*/ */
@OnClick(R.id.depicts_previous)
public void onPreviousButtonClicked() { public void onPreviousButtonClicked() {
if(media != null){ if(media != null){
presenter.clearPreviousSelection(); presenter.clearPreviousSelection();
@ -347,9 +339,9 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
* Text change listener for the edit text view of depicts * Text change listener for the edit text view of depicts
*/ */
private void addTextChangeListenerToSearchBox() { private void addTextChangeListenerToSearchBox() {
subscribe = RxTextView.textChanges(depictsSearch) subscribe = RxTextView.textChanges(binding.depictsSearch)
.doOnEach(v -> depictsSearchContainer.setError(null)) .doOnEach(v -> binding.depictsSearchContainer.setError(null))
.takeUntil(RxView.detaches(depictsSearch)) .takeUntil(RxView.detaches(binding.depictsSearch))
.debounce(500, TimeUnit.MILLISECONDS) .debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(filter -> searchForDepictions(filter.toString()), Timber::e); .subscribe(filter -> searchForDepictions(filter.toString()), Timber::e);
@ -374,9 +366,9 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
super.onResume(); super.onResume();
if (media != null) { if (media != null) {
depictsSearch.setOnKeyListener((v, keyCode, event) -> { binding.depictsSearch.setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK) { if (keyCode == KeyEvent.KEYCODE_BACK) {
depictsSearch.clearFocus(); binding.depictsSearch.clearFocus();
presenter.clearPreviousSelection(); presenter.clearPreviousSelection();
updateDepicts(); updateDepicts();
goBackToPreviousScreen(); goBackToPreviousScreen();
@ -422,4 +414,10 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
.show(); .show();
} }
} }
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
} }

View file

@ -10,10 +10,14 @@ import android.text.style.ClickableSpan;
import android.text.style.URLSpan; import android.text.style.URLSpan;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener; import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -21,10 +25,18 @@ import androidx.annotation.Nullable;
import fr.free.nrw.commons.databinding.FragmentMediaLicenseBinding; import fr.free.nrw.commons.databinding.FragmentMediaLicenseBinding;
import fr.free.nrw.commons.upload.UploadActivity; import fr.free.nrw.commons.upload.UploadActivity;
import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.DialogUtil;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.databinding.FragmentMediaLicenseBinding;
import fr.free.nrw.commons.upload.UploadActivity;
import fr.free.nrw.commons.upload.UploadBaseFragment; import fr.free.nrw.commons.upload.UploadBaseFragment;
import fr.free.nrw.commons.utils.DialogUtil;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import timber.log.Timber; import timber.log.Timber;

View file

@ -7,8 +7,10 @@ import static fr.free.nrw.commons.utils.ImageUtils.getErrorMessageForResult;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcelable;
import android.speech.RecognizerIntent; import android.speech.RecognizerIntent;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -16,25 +18,16 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatImageButton;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.github.chrisbanes.photoview.PhotoView;
import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.camera.CameraPosition;
import fr.free.nrw.commons.LocationPicker.LocationPicker; import fr.free.nrw.commons.LocationPicker.LocationPicker;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.edit.EditActivity;
import fr.free.nrw.commons.contributions.MainActivity; import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.databinding.FragmentUploadMediaDetailFragmentBinding;
import fr.free.nrw.commons.edit.EditActivity;
import fr.free.nrw.commons.filepicker.UploadableFile; import fr.free.nrw.commons.filepicker.UploadableFile;
import fr.free.nrw.commons.kvstore.BasicKvStore; import fr.free.nrw.commons.kvstore.BasicKvStore;
import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.kvstore.JsonKvStore;
@ -61,7 +54,6 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import timber.log.Timber; import timber.log.Timber;
import android.os.Parcelable;
public class UploadMediaDetailFragment extends UploadBaseFragment implements public class UploadMediaDetailFragment extends UploadBaseFragment implements
UploadMediaDetailsContract.View, UploadMediaDetailAdapter.EventListener { UploadMediaDetailsContract.View, UploadMediaDetailAdapter.EventListener {
@ -81,34 +73,9 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
public static final String UPLOADABLE_FILE = "uploadable_file"; public static final String UPLOADABLE_FILE = "uploadable_file";
public static final String UPLOAD_MEDIA_DETAILS = "upload_media_detail_adapter"; public static final String UPLOAD_MEDIA_DETAILS = "upload_media_detail_adapter";
@BindView(R.id.tv_title)
TextView tvTitle;
@BindView(R.id.location_image_view)
ImageView locationImageView;
@BindView(R.id.location_text_view)
TextView locationTextView;
@BindView(R.id.ll_location_status)
LinearLayout llLocationStatus;
@BindView(R.id.ib_expand_collapse)
AppCompatImageButton ibExpandCollapse;
@BindView(R.id.ll_container_media_detail)
LinearLayout llContainerMediaDetail;
@BindView(R.id.rv_descriptions)
RecyclerView rvDescriptions;
@BindView(R.id.backgroundImage)
PhotoView photoViewBackgroundImage;
@BindView(R.id.btn_next)
AppCompatButton btnNext;
@BindView(R.id.btn_previous)
AppCompatButton btnPrevious;
@BindView(R.id.ll_edit_image)
LinearLayout llEditImage;
@BindView(R.id.tooltip)
ImageView tooltip;
private UploadMediaDetailAdapter uploadMediaDetailAdapter; private UploadMediaDetailAdapter uploadMediaDetailAdapter;
@BindView(R.id.btn_copy_subsequent_media)
AppCompatButton btnCopyToSubsequentMedia;
@Inject @Inject
UploadMediaDetailsContract.UserActionListener presenter; UploadMediaDetailsContract.UserActionListener presenter;
@ -154,6 +121,8 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
private UploadMediaDetailFragmentCallback callback; private UploadMediaDetailFragmentCallback callback;
private FragmentUploadMediaDetailFragmentBinding binding;
public void setCallback(UploadMediaDetailFragmentCallback callback) { public void setCallback(UploadMediaDetailFragmentCallback callback) {
this.callback = callback; this.callback = callback;
} }
@ -182,21 +151,21 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_upload_media_detail_fragment, container, false); binding = FragmentUploadMediaDetailFragmentBinding.inflate(inflater, container, false);
return binding.getRoot();
} }
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
if (callback != null) { if (callback != null) {
init(); init();
} }
if(savedInstanceState!=null){ if(savedInstanceState!=null){
if(uploadMediaDetailAdapter.getItems().size()==0){ if(uploadMediaDetailAdapter.getItems().size()==0 && callback != null){
uploadMediaDetailAdapter.setItems(savedInstanceState.getParcelableArrayList(UPLOAD_MEDIA_DETAILS)); uploadMediaDetailAdapter.setItems(savedInstanceState.getParcelableArrayList(UPLOAD_MEDIA_DETAILS));
presenter.setUploadMediaDetails(uploadMediaDetailAdapter.getItems(), callback.getIndexInViewFlipper(this)); presenter.setUploadMediaDetails(uploadMediaDetailAdapter.getItems(), callback.getIndexInViewFlipper(this));
} }
@ -205,43 +174,54 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
} }
private void init() { private void init() {
tvTitle.setText(getString(R.string.step_count, callback.getIndexInViewFlipper(this) + 1, if (binding == null) {
return;
}
binding.tvTitle.setText(getString(R.string.step_count, callback.getIndexInViewFlipper(this) + 1,
callback.getTotalNumberOfSteps(), getString(R.string.media_detail_step_title))); callback.getTotalNumberOfSteps(), getString(R.string.media_detail_step_title)));
tooltip.setOnClickListener( binding.tooltip.setOnClickListener(
v -> showInfoAlert(R.string.media_detail_step_title, R.string.media_details_tooltip)); v -> showInfoAlert(R.string.media_detail_step_title, R.string.media_details_tooltip));
initPresenter(); initPresenter();
presenter.receiveImage(uploadableFile, place, inAppPictureLocation); presenter.receiveImage(uploadableFile, place, inAppPictureLocation);
initRecyclerView(); initRecyclerView();
if (callback.getIndexInViewFlipper(this) == 0) { if (callback.getIndexInViewFlipper(this) == 0) {
btnPrevious.setEnabled(false); binding.btnPrevious.setEnabled(false);
btnPrevious.setAlpha(0.5f); binding.btnPrevious.setAlpha(0.5f);
} else { } else {
btnPrevious.setEnabled(true); binding.btnPrevious.setEnabled(true);
btnPrevious.setAlpha(1.0f); binding.btnPrevious.setAlpha(1.0f);
} }
// If the image EXIF data contains the location, show the map icon with a green tick // If the image EXIF data contains the location, show the map icon with a green tick
if (inAppPictureLocation != null || if (inAppPictureLocation != null ||
(uploadableFile != null && uploadableFile.hasLocation())) { (uploadableFile != null && uploadableFile.hasLocation())) {
Drawable mapTick = getResources().getDrawable(R.drawable.ic_map_available_20dp); Drawable mapTick = getResources().getDrawable(R.drawable.ic_map_available_20dp);
locationImageView.setImageDrawable(mapTick); binding.locationImageView.setImageDrawable(mapTick);
locationTextView.setText(R.string.edit_location); binding.locationTextView.setText(R.string.edit_location);
} else { } else {
// Otherwise, show the map icon with a red question mark // Otherwise, show the map icon with a red question mark
Drawable mapQuestionMark = Drawable mapQuestionMark =
getResources().getDrawable(R.drawable.ic_map_not_available_20dp); getResources().getDrawable(R.drawable.ic_map_not_available_20dp);
locationImageView.setImageDrawable(mapQuestionMark); binding.locationImageView.setImageDrawable(mapQuestionMark);
locationTextView.setText(R.string.add_location); binding.locationTextView.setText(R.string.add_location);
} }
//If this is the last media, we have nothing to copy, lets not show the button //If this is the last media, we have nothing to copy, lets not show the button
if (callback.getIndexInViewFlipper(this) == callback.getTotalNumberOfSteps() - 4) { if (callback.getIndexInViewFlipper(this) == callback.getTotalNumberOfSteps() - 4) {
btnCopyToSubsequentMedia.setVisibility(View.GONE); binding.btnCopySubsequentMedia.setVisibility(View.GONE);
} else { } else {
btnCopyToSubsequentMedia.setVisibility(View.VISIBLE); binding.btnCopySubsequentMedia.setVisibility(View.VISIBLE);
} }
binding.btnNext.setOnClickListener(v -> onNextButtonClicked());
binding.btnPrevious.setOnClickListener(v -> onPreviousButtonClicked());
binding.llEditImage.setOnClickListener(v -> onEditButtonClicked());
binding.llContainerTitle.setOnClickListener(v -> onLlContainerTitleClicked());
binding.llLocationStatus.setOnClickListener(v -> onIbMapClicked());
binding.btnCopySubsequentMedia.setOnClickListener(v -> onButtonCopyTitleDescToSubsequentMedia());
attachImageViewScaleChangeListener(); attachImageViewScaleChangeListener();
} }
@ -249,7 +229,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
* Attaches the scale change listener to the image view * Attaches the scale change listener to the image view
*/ */
private void attachImageViewScaleChangeListener() { private void attachImageViewScaleChangeListener() {
photoViewBackgroundImage.setOnScaleChangeListener( binding.backgroundImage.setOnScaleChangeListener(
(scaleFactor, focusX, focusY) -> { (scaleFactor, focusX, focusY) -> {
//Whenever the uses plays with the image, lets collapse the media detail container //Whenever the uses plays with the image, lets collapse the media detail container
//only if it is not already collapsed, which resolves flickering of arrow //only if it is not already collapsed, which resolves flickering of arrow
@ -274,8 +254,8 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""), recentLanguagesDao); defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""), recentLanguagesDao);
uploadMediaDetailAdapter.setCallback(this::showInfoAlert); uploadMediaDetailAdapter.setCallback(this::showInfoAlert);
uploadMediaDetailAdapter.setEventListener(this); uploadMediaDetailAdapter.setEventListener(this);
rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext())); binding.rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext()));
rvDescriptions.setAdapter(uploadMediaDetailAdapter); binding.rvDescriptions.setAdapter(uploadMediaDetailAdapter);
} }
/** /**
@ -288,8 +268,11 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
getString(messageStringId), getString(android.R.string.ok), null, true); getString(messageStringId), getString(android.R.string.ok), null, true);
} }
@OnClick(R.id.btn_next)
public void onNextButtonClicked() { public void onNextButtonClicked() {
if (callback == null) {
return;
}
boolean isValidUploads = presenter.verifyImageQuality(callback.getIndexInViewFlipper(this), inAppPictureLocation); boolean isValidUploads = presenter.verifyImageQuality(callback.getIndexInViewFlipper(this), inAppPictureLocation);
if (!isValidUploads) { if (!isValidUploads) {
startActivityWithFlags( startActivityWithFlags(
@ -298,12 +281,13 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
} }
} }
@OnClick(R.id.btn_previous)
public void onPreviousButtonClicked() { public void onPreviousButtonClicked() {
if (callback == null) {
return;
}
callback.onPreviousButtonClicked(callback.getIndexInViewFlipper(this)); callback.onPreviousButtonClicked(callback.getIndexInViewFlipper(this));
} }
@OnClick(R.id.ll_edit_image)
public void onEditButtonClicked() { public void onEditButtonClicked() {
presenter.onEditButtonClicked(callback.getIndexInViewFlipper(this)); presenter.onEditButtonClicked(callback.getIndexInViewFlipper(this));
} }
@ -343,7 +327,10 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Override @Override
public void onImageProcessed(UploadItem uploadItem, Place place) { public void onImageProcessed(UploadItem uploadItem, Place place) {
photoViewBackgroundImage.setImageURI(uploadItem.getMediaUri()); if (binding == null) {
return;
}
binding.backgroundImage.setImageURI(uploadItem.getMediaUri());
} }
/** /**
@ -356,12 +343,17 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
nearbyPlace = place; nearbyPlace = place;
this.uploadItem = uploadItem; this.uploadItem = uploadItem;
showNearbyFound = true; showNearbyFound = true;
if (callback == null) {
return;
}
if (callback.getIndexInViewFlipper(this) == 0) { if (callback.getIndexInViewFlipper(this) == 0) {
if (UploadActivity.nearbyPopupAnswers.containsKey(nearbyPlace)) { if (UploadActivity.nearbyPopupAnswers.containsKey(nearbyPlace)) {
final boolean response = UploadActivity.nearbyPopupAnswers.get(nearbyPlace); final boolean response = UploadActivity.nearbyPopupAnswers.get(nearbyPlace);
if (response) { if (response) {
presenter.onUserConfirmedUploadIsOfPlace(nearbyPlace, if (callback != null) {
callback.getIndexInViewFlipper(this)); presenter.onUserConfirmedUploadIsOfPlace(nearbyPlace,
callback.getIndexInViewFlipper(this));
}
} }
} else { } else {
showNearbyPlaceFound(nearbyPlace); showNearbyPlaceFound(nearbyPlace);
@ -397,11 +389,17 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Override @Override
public void showProgress(boolean shouldShow) { public void showProgress(boolean shouldShow) {
if (callback == null) {
return;
}
callback.showProgress(shouldShow); callback.showProgress(shouldShow);
} }
@Override @Override
public void onImageValidationSuccess() { public void onImageValidationSuccess() {
if (callback == null) {
return;
}
callback.onNextButtonClicked(callback.getIndexInViewFlipper(this)); callback.onNextButtonClicked(callback.getIndexInViewFlipper(this));
} }
@ -411,13 +409,18 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Override @Override
protected void onBecameVisible() { protected void onBecameVisible() {
super.onBecameVisible(); super.onBecameVisible();
if (callback == null) {
return;
}
presenter.fetchTitleAndDescription(callback.getIndexInViewFlipper(this)); presenter.fetchTitleAndDescription(callback.getIndexInViewFlipper(this));
if (showNearbyFound) { if (showNearbyFound) {
if (UploadActivity.nearbyPopupAnswers.containsKey(nearbyPlace)) { if (UploadActivity.nearbyPopupAnswers.containsKey(nearbyPlace)) {
final boolean response = UploadActivity.nearbyPopupAnswers.get(nearbyPlace); final boolean response = UploadActivity.nearbyPopupAnswers.get(nearbyPlace);
if (response) { if (response) {
presenter.onUserConfirmedUploadIsOfPlace(nearbyPlace, if (callback != null) {
callback.getIndexInViewFlipper(this)); presenter.onUserConfirmedUploadIsOfPlace(nearbyPlace,
callback.getIndexInViewFlipper(this));
}
} }
} else { } else {
showNearbyPlaceFound(nearbyPlace); showNearbyPlaceFound(nearbyPlace);
@ -621,10 +624,13 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
return; return;
} }
try { try {
photoViewBackgroundImage.setImageURI(Uri.fromFile(new File(result))); if (binding != null){
binding.backgroundImage.setImageURI(Uri.fromFile(new File(result)));
}
editableUploadItem.setContentUri(Uri.fromFile(new File(result))); editableUploadItem.setContentUri(Uri.fromFile(new File(result)));
callback.changeThumbnail(callback.getIndexInViewFlipper(this), if (callback != null) {
result); callback.changeThumbnail(callback.getIndexInViewFlipper(this), result);
}
} catch (Exception e) { } catch (Exception e) {
Timber.e(e); Timber.e(e);
} }
@ -655,8 +661,11 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
// Replace the map icon using the one with a green tick // Replace the map icon using the one with a green tick
Drawable mapTick = getResources().getDrawable(R.drawable.ic_map_available_20dp); Drawable mapTick = getResources().getDrawable(R.drawable.ic_map_available_20dp);
locationImageView.setImageDrawable(mapTick);
locationTextView.setText(R.string.edit_location); if (binding != null) {
binding.locationImageView.setImageDrawable(mapTick);
binding.locationTextView.setText(R.string.edit_location);
}
Toast.makeText(getContext(), "Location Updated", Toast.LENGTH_LONG).show(); Toast.makeText(getContext(), "Location Updated", Toast.LENGTH_LONG).show();
@ -709,6 +718,9 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
} }
private void deleteThisPicture() { private void deleteThisPicture() {
if (callback == null) {
return;
}
callback.deletePictureAtIndex(callback.getIndexInViewFlipper(this)); callback.deletePictureAtIndex(callback.getIndexInViewFlipper(this));
} }
@ -718,7 +730,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
presenter.onDetachView(); presenter.onDetachView();
} }
@OnClick(R.id.ll_container_title)
public void onLlContainerTitleClicked() { public void onLlContainerTitleClicked() {
expandCollapseLlMediaDetail(!isExpanded); expandCollapseLlMediaDetail(!isExpanded);
} }
@ -728,23 +739,32 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
* @param shouldExpand * @param shouldExpand
*/ */
private void expandCollapseLlMediaDetail(boolean shouldExpand){ private void expandCollapseLlMediaDetail(boolean shouldExpand){
llContainerMediaDetail.setVisibility(shouldExpand ? View.VISIBLE : View.GONE); if (binding == null) {
return;
}
binding.llContainerMediaDetail.setVisibility(shouldExpand ? View.VISIBLE : View.GONE);
isExpanded = !isExpanded; isExpanded = !isExpanded;
ibExpandCollapse.setRotation(ibExpandCollapse.getRotation() + 180); binding.ibExpandCollapse.setRotation(binding.ibExpandCollapse.getRotation() + 180);
} }
@OnClick(R.id.ll_location_status) public void onIbMapClicked() { public void onIbMapClicked() {
if (callback == null) {
return;
}
presenter.onMapIconClicked(callback.getIndexInViewFlipper(this)); presenter.onMapIconClicked(callback.getIndexInViewFlipper(this));
} }
@Override @Override
public void onPrimaryCaptionTextChange(boolean isNotEmpty) { public void onPrimaryCaptionTextChange(boolean isNotEmpty) {
btnCopyToSubsequentMedia.setEnabled(isNotEmpty); if (binding == null) {
btnCopyToSubsequentMedia.setClickable(isNotEmpty); return;
btnCopyToSubsequentMedia.setAlpha(isNotEmpty ? 1.0f : 0.5f); }
btnNext.setEnabled(isNotEmpty); binding.btnCopySubsequentMedia.setEnabled(isNotEmpty);
btnNext.setClickable(isNotEmpty); binding.btnCopySubsequentMedia.setClickable(isNotEmpty);
btnNext.setAlpha(isNotEmpty ? 1.0f : 0.5f); binding.btnCopySubsequentMedia.setAlpha(isNotEmpty ? 1.0f : 0.5f);
binding.btnNext.setEnabled(isNotEmpty);
binding.btnNext.setClickable(isNotEmpty);
binding.btnNext.setAlpha(isNotEmpty ? 1.0f : 0.5f);
} }
/** /**
@ -755,7 +775,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
UploadMediaDetail uploadMediaDetail = new UploadMediaDetail(); UploadMediaDetail uploadMediaDetail = new UploadMediaDetail();
uploadMediaDetail.setManuallyAdded(true);//This was manually added by the user uploadMediaDetail.setManuallyAdded(true);//This was manually added by the user
uploadMediaDetailAdapter.addDescription(uploadMediaDetail); uploadMediaDetailAdapter.addDescription(uploadMediaDetail);
rvDescriptions.smoothScrollToPosition(uploadMediaDetailAdapter.getItemCount()-1); binding.rvDescriptions.smoothScrollToPosition(uploadMediaDetailAdapter.getItemCount()-1);
} }
public interface UploadMediaDetailFragmentCallback extends Callback { public interface UploadMediaDetailFragmentCallback extends Callback {
@ -766,8 +786,10 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
} }
@OnClick(R.id.btn_copy_subsequent_media)
public void onButtonCopyTitleDescToSubsequentMedia(){ public void onButtonCopyTitleDescToSubsequentMedia(){
if (callback == null) {
return;
}
presenter.copyTitleAndDescriptionToSubsequentMedia(callback.getIndexInViewFlipper(this)); presenter.copyTitleAndDescriptionToSubsequentMedia(callback.getIndexInViewFlipper(this));
Toast.makeText(getContext(), getResources().getString(R.string.copied_successfully), Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), getResources().getString(R.string.copied_successfully), Toast.LENGTH_SHORT).show();
} }
@ -785,5 +807,9 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
} }
} }
@Override
public void onDestroy() {
super.onDestroy();
binding = null;
}
} }

View file

@ -23,6 +23,7 @@ import fr.free.nrw.commons.OkHttpConnectionFactory
import fr.free.nrw.commons.R import fr.free.nrw.commons.R
import fr.free.nrw.commons.TestCommonsApplication import fr.free.nrw.commons.TestCommonsApplication
import fr.free.nrw.commons.createTestClient import fr.free.nrw.commons.createTestClient
import fr.free.nrw.commons.databinding.UploadCategoriesFragmentBinding
import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText import fr.free.nrw.commons.ui.PasteSensitiveTextInputEditText
import fr.free.nrw.commons.upload.UploadActivity import fr.free.nrw.commons.upload.UploadActivity
import fr.free.nrw.commons.upload.UploadBaseFragment import fr.free.nrw.commons.upload.UploadBaseFragment
@ -51,41 +52,10 @@ class UploadCategoriesFragmentUnitTests {
private lateinit var context: Context private lateinit var context: Context
private lateinit var fragmentManager: FragmentManager private lateinit var fragmentManager: FragmentManager
private lateinit var layoutInflater: LayoutInflater private lateinit var layoutInflater: LayoutInflater
private lateinit var view: View
@Mock @Mock
private lateinit var subscribe: Disposable private lateinit var subscribe: Disposable
@Mock
private lateinit var pbCategories: ProgressBar
@Mock
private lateinit var progressDialog: ProgressDialog
@Mock
private lateinit var tilContainerEtSearch: TextInputLayout
@Mock
private lateinit var etSearch: PasteSensitiveTextInputEditText
@Mock
private lateinit var rvCategories: RecyclerView
@Mock
private lateinit var tvTitle: TextView
@Mock
private lateinit var tvSubTitle: TextView
@Mock
private lateinit var tooltip: ImageView
@Mock
private lateinit var editable: Editable
@Mock
private lateinit var button: Button
@Mock @Mock
private lateinit var adapter: UploadCategoryAdapter private lateinit var adapter: UploadCategoryAdapter
@ -98,6 +68,8 @@ class UploadCategoriesFragmentUnitTests {
@Mock @Mock
private lateinit var media: Media private lateinit var media: Media
private lateinit var binding : UploadCategoriesFragmentBinding
@Before @Before
fun setUp() { fun setUp() {
@ -110,22 +82,13 @@ class UploadCategoriesFragmentUnitTests {
val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction() val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.add(fragment, null) fragmentTransaction.add(fragment, null)
fragmentTransaction.commit() fragmentTransaction.commit()
layoutInflater = LayoutInflater.from(activity) layoutInflater = LayoutInflater.from(activity)
view = LayoutInflater.from(activity) binding = UploadCategoriesFragmentBinding.inflate(layoutInflater)
.inflate(R.layout.upload_categories_fragment, null) as View
Whitebox.setInternalState(fragment, "subscribe", subscribe) Whitebox.setInternalState(fragment, "subscribe", subscribe)
Whitebox.setInternalState(fragment, "pbCategories", pbCategories)
Whitebox.setInternalState(fragment, "tilContainerEtSearch", tilContainerEtSearch)
Whitebox.setInternalState(fragment, "adapter", adapter) Whitebox.setInternalState(fragment, "adapter", adapter)
Whitebox.setInternalState(fragment, "presenter", presenter) Whitebox.setInternalState(fragment, "presenter", presenter)
Whitebox.setInternalState(fragment, "etSearch", etSearch)
Whitebox.setInternalState(fragment, "rvCategories", rvCategories)
Whitebox.setInternalState(fragment, "tvTitle", tvTitle)
Whitebox.setInternalState(fragment, "tooltip", tooltip)
Whitebox.setInternalState(fragment, "tvSubTitle", tvSubTitle)
Whitebox.setInternalState(fragment, "btnNext", button)
Whitebox.setInternalState(fragment, "btnPrevious", button)
Whitebox.setInternalState(fragment, "progressDialog", progressDialog)
Whitebox.setInternalState(fragment, "wikiText", "[[Category:Test]]") Whitebox.setInternalState(fragment, "wikiText", "[[Category:Test]]")
} }
@ -255,7 +218,6 @@ class UploadCategoriesFragmentUnitTests {
fun testShowProgressDialog() { fun testShowProgressDialog() {
Shadows.shadowOf(Looper.getMainLooper()).idle() Shadows.shadowOf(Looper.getMainLooper()).idle()
fragment.showProgressDialog() fragment.showProgressDialog()
verify(progressDialog, times(0)).show()
} }
@Test @Test
@ -263,7 +225,6 @@ class UploadCategoriesFragmentUnitTests {
fun testDismissProgressDialog() { fun testDismissProgressDialog() {
Shadows.shadowOf(Looper.getMainLooper()).idle() Shadows.shadowOf(Looper.getMainLooper()).idle()
fragment.dismissProgressDialog() fragment.dismissProgressDialog()
verify(progressDialog, times(1)).dismiss()
} }
@Test @Test
@ -300,7 +261,6 @@ class UploadCategoriesFragmentUnitTests {
@Throws(Exception::class) @Throws(Exception::class)
fun testOnBecameVisible() { fun testOnBecameVisible() {
Shadows.shadowOf(Looper.getMainLooper()).idle() Shadows.shadowOf(Looper.getMainLooper()).idle()
`when`(etSearch.text).thenReturn(editable)
val method: Method = UploadCategoriesFragment::class.java.getDeclaredMethod( val method: Method = UploadCategoriesFragment::class.java.getDeclaredMethod(
"onBecameVisible" "onBecameVisible"
) )

View file

@ -5,10 +5,6 @@ import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -53,27 +49,6 @@ class DepictsFragmentUnitTests {
@Mock @Mock
private lateinit var savedInstanceState: Bundle private lateinit var savedInstanceState: Bundle
@Mock
private lateinit var textView: TextView
@Mock
private lateinit var imageView: ImageView
@Mock
private lateinit var recyclerView: RecyclerView
@Mock
private lateinit var textInputEditText: PasteSensitiveTextInputEditText
@Mock
private lateinit var progressBar: ProgressBar
@Mock
private lateinit var button: Button
@Mock
private lateinit var textInputLayout: TextInputLayout
@Mock @Mock
private lateinit var callback: UploadBaseFragment.Callback private lateinit var callback: UploadBaseFragment.Callback
@ -110,16 +85,8 @@ class DepictsFragmentUnitTests {
view = LayoutInflater.from(activity) view = LayoutInflater.from(activity)
.inflate(R.layout.upload_depicts_fragment, null) as View .inflate(R.layout.upload_depicts_fragment, null) as View
Whitebox.setInternalState(fragment, "depictsTitle", textView)
Whitebox.setInternalState(fragment, "callback", callback) Whitebox.setInternalState(fragment, "callback", callback)
Whitebox.setInternalState(fragment, "tooltip", imageView)
Whitebox.setInternalState(fragment, "btnNext", button)
Whitebox.setInternalState(fragment, "btnPrevious", button)
Whitebox.setInternalState(fragment, "depictsSubTitle", textView)
Whitebox.setInternalState(fragment, "depictsRecyclerView", recyclerView)
Whitebox.setInternalState(fragment, "depictsSearch", textInputEditText)
Whitebox.setInternalState(fragment, "depictsSearchContainer", textInputLayout)
Whitebox.setInternalState(fragment, "depictsSearchInProgress", progressBar)
Whitebox.setInternalState(fragment, "subscribe", disposable) Whitebox.setInternalState(fragment, "subscribe", disposable)
Whitebox.setInternalState(fragment, "adapter", adapter) Whitebox.setInternalState(fragment, "adapter", adapter)
} }

View file

@ -142,20 +142,7 @@ class UploadMediaDetailFragmentUnitTest {
llContainerMediaDetail = view.findViewById(R.id.ll_container_media_detail) llContainerMediaDetail = view.findViewById(R.id.ll_container_media_detail)
ibExpandCollapse = view.findViewById(R.id.ib_expand_collapse) ibExpandCollapse = view.findViewById(R.id.ib_expand_collapse)
Whitebox.setInternalState(fragment, "tvTitle", tvTitle)
Whitebox.setInternalState(fragment, "tooltip", tooltip)
Whitebox.setInternalState(fragment, "callback", callback)
Whitebox.setInternalState(fragment, "rvDescriptions", rvDescriptions)
Whitebox.setInternalState(fragment, "btnPrevious", btnPrevious)
Whitebox.setInternalState(fragment, "btnNext", btnNext)
Whitebox.setInternalState(fragment, "btnCopyToSubsequentMedia", btnCopyToSubsequentMedia)
Whitebox.setInternalState(fragment, "photoViewBackgroundImage", photoViewBackgroundImage)
Whitebox.setInternalState(fragment, "uploadMediaDetailAdapter", uploadMediaDetailAdapter) Whitebox.setInternalState(fragment, "uploadMediaDetailAdapter", uploadMediaDetailAdapter)
Whitebox.setInternalState(fragment, "llLocationStatus", locationStatusLl)
Whitebox.setInternalState(fragment, "locationImageView", locationImageView)
Whitebox.setInternalState(fragment, "locationTextView", locationTextView)
Whitebox.setInternalState(fragment, "llContainerMediaDetail", llContainerMediaDetail)
Whitebox.setInternalState(fragment, "ibExpandCollapse", ibExpandCollapse)
} }
@Test @Test
@ -388,6 +375,7 @@ class UploadMediaDetailFragmentUnitTest {
val cameraPosition = Mockito.mock(CameraPosition::class.java) val cameraPosition = Mockito.mock(CameraPosition::class.java)
val latLng = Mockito.mock(LatLng::class.java) val latLng = Mockito.mock(LatLng::class.java)
Whitebox.setInternalState(fragment, "callback", callback)
Whitebox.setInternalState(cameraPosition, "target", latLng) Whitebox.setInternalState(cameraPosition, "target", latLng)
Whitebox.setInternalState(fragment, "editableUploadItem", uploadItem) Whitebox.setInternalState(fragment, "editableUploadItem", uploadItem)
Whitebox.setInternalState(fragment,"isMissingLocationDialog",true) Whitebox.setInternalState(fragment,"isMissingLocationDialog",true)