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.ViewGroup;
import android.view.Window;
import android.widget.Button;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
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.view.SimpleDraweeView;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.databinding.FragmentSimilarImageDialogBinding;
import java.io.File;
/**
@ -26,17 +22,11 @@ import java.io.File;
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
Boolean gotResponse = false;
private FragmentSimilarImageDialogBinding binding;
public SimilarImageDialogFragment() {
}
public interface Callback {
@ -51,17 +41,17 @@ public class SimilarImageDialogFragment extends DialogFragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_similar_image_dialog, container, false);
ButterKnife.bind(this,view);
binding = FragmentSimilarImageDialogBinding.inflate(inflater, container, false);
originalImage.setHierarchy(GenericDraweeHierarchyBuilder
binding.orginalImage.setHierarchy(GenericDraweeHierarchyBuilder
.newInstance(getResources())
.setPlaceholderImage(VectorDrawableCompat.create(getResources(),
R.drawable.ic_image_black_24dp,getContext().getTheme()))
.setFailureImage(VectorDrawableCompat.create(getResources(),
R.drawable.ic_error_outline_black_24dp, getContext().getTheme()))
.build());
possibleImage.setHierarchy(GenericDraweeHierarchyBuilder
binding.possibleImage.setHierarchy(GenericDraweeHierarchyBuilder
.newInstance(getResources())
.setPlaceholderImage(VectorDrawableCompat.create(getResources(),
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()))
.build());
originalImage.setImageURI(Uri.fromFile(new File(getArguments().getString("originalImagePath"))));
possibleImage.setImageURI(Uri.fromFile(new File(getArguments().getString("possibleImagePath"))));
binding.orginalImage.setImageURI(Uri.fromFile(new File(getArguments().getString("originalImagePath"))));
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
@ -96,17 +89,21 @@ public class SimilarImageDialogFragment extends DialogFragment {
super.onDismiss(dialog);
}
@OnClick(R.id.negative_button)
public void onNegativeButtonClicked() {
callback.onNegativeResponse();
gotResponse = true;
dismiss();
}
@OnClick(R.id.postive_button)
public void onPositiveButtonClicked() {
callback.onPositiveResponse();
gotResponse = true;
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.widget.ImageView;
import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
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.util.ArrayList;
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.
*/
@ -33,6 +28,8 @@ class ThumbnailsAdapter extends RecyclerView.Adapter<ThumbnailsAdapter.ViewHolde
List<UploadableFile> uploadableFiles;
private Callback callback;
private ItemUploadThumbnailBinding binding;
public ThumbnailsAdapter(Callback callback) {
this.uploadableFiles = new ArrayList<>();
this.callback = callback;
@ -51,8 +48,8 @@ class ThumbnailsAdapter extends RecyclerView.Adapter<ThumbnailsAdapter.ViewHolde
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new ViewHolder(LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.item_upload_thumbnail, viewGroup, false));
binding = ItemUploadThumbnailBinding.inflate(LayoutInflater.from(viewGroup.getContext()), viewGroup, false);
return new ViewHolder(binding.getRoot());
}
@Override
@ -67,16 +64,16 @@ class ThumbnailsAdapter extends RecyclerView.Adapter<ThumbnailsAdapter.ViewHolde
public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.rl_container)
RelativeLayout rlContainer;
@BindView(R.id.iv_thumbnail)
SimpleDraweeView background;
@BindView(R.id.iv_error)
ImageView ivError;
public ViewHolder(@NonNull View 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.util.DisplayMetrics;
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.cardview.widget.CardView;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.work.ExistingWorkPolicy;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.auth.SessionManager;
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.UploadableFile;
import fr.free.nrw.commons.kvstore.BasicKvStore;
@ -93,28 +86,6 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Inject
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 CompositeDisposable compositeDisposable;
@ -169,12 +140,15 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
*/
private boolean isFragmentsSaved = false;
private ActivityUploadBinding binding;
@SuppressLint("CheckResult")
@Override
protected void onCreate(Bundle 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
@ -190,7 +164,6 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
}
ButterKnife.bind(this);
compositeDisposable = new CompositeDisposable();
init();
nearbyPopupAnswers = new HashMap<>();
@ -223,17 +196,17 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
}
private void initThumbnailsRecyclerView() {
rvThumbnails.setLayoutManager(new LinearLayoutManager(this,
binding.rvThumbnails.setLayoutManager(new LinearLayoutManager(this,
LinearLayoutManager.HORIZONTAL, false));
thumbnailsAdapter = new ThumbnailsAdapter(() -> currentSelectedPosition);
rvThumbnails.setAdapter(thumbnailsAdapter);
binding.rvThumbnails.setAdapter(thumbnailsAdapter);
}
private void initViewPager() {
uploadImagesAdapter = new UploadImageAdapter(getSupportFragmentManager());
vpUpload.setAdapter(uploadImagesAdapter);
vpUpload.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
binding.vpUpload.setAdapter(uploadImagesAdapter);
binding.vpUpload.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
@ -244,10 +217,10 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
public void onPageSelected(int position) {
currentSelectedPosition = position;
if (position >= uploadableFiles.size()) {
cvContainerTopCard.setVisibility(View.GONE);
binding.cvContainerTopCard.setVisibility(View.GONE);
} else {
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) {
// All required permissions are granted, so enable UI elements and perform actions
receiveSharedItems();
cvContainerTopCard.setVisibility(View.VISIBLE);
binding.cvContainerTopCard.setVisibility(View.VISIBLE);
} else {
// Permissions are missing
cvContainerTopCard.setVisibility(View.INVISIBLE);
binding.cvContainerTopCard.setVisibility(View.INVISIBLE);
if(showPermissionsDialog){
checkPermissionsAndPerformAction(this,
() -> {
cvContainerTopCard.setVisibility(View.VISIBLE);
binding.cvContainerTopCard.setVisibility(View.VISIBLE);
this.receiveSharedItems();
},() -> {
this.showPermissionsDialog = true;
@ -379,7 +352,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override
public void showHideTopCard(boolean shouldShow) {
llContainerTopCard.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
binding.llContainerTopCard.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
}
@Override
@ -392,7 +365,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override
public void updateTopCardTitle() {
tvTopCardTitle.setText(getResources()
binding.tvTopCardTitle.setText(getResources()
.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
thumbnailsAdapter.setUploadableFiles(uploadableFiles);
} 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()));
@ -568,7 +541,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
public void changeThumbnail(int index, String filepath) {
uploadableFiles.remove(index);
uploadableFiles.add(index, new UploadableFile(new File(filepath)));
rvThumbnails.getAdapter().notifyDataSetChanged();
binding.rvThumbnails.getAdapter().notifyDataSetChanged();
}
@Override
@ -642,9 +615,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override
public void onNextButtonClicked(int index) {
if (index < fragments.size() - 1) {
vpUpload.setCurrentItem(index + 1, false);
binding.vpUpload.setCurrentItem(index + 1, false);
fragments.get(index + 1).onBecameVisible();
((LinearLayoutManager) rvThumbnails.getLayoutManager())
((LinearLayoutManager) binding.rvThumbnails.getLayoutManager())
.scrollToPositionWithOffset((index > 0) ? index-1 : 0, 0);
} else {
presenter.handleSubmit();
@ -654,9 +627,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override
public void onPreviousButtonClicked(int index) {
if (index != 0) {
vpUpload.setCurrentItem(index - 1, true);
binding.vpUpload.setCurrentItem(index - 1, true);
fragments.get(index - 1).onBecameVisible();
((LinearLayoutManager) rvThumbnails.getLayoutManager())
((LinearLayoutManager) binding.rvThumbnails.getLayoutManager())
.scrollToPositionWithOffset((index > 3) ? index-2 : 0, 0);
}
}
@ -691,7 +664,7 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
}
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
public void highlightNextImageOnCancelledImage(int index, int maxSize) {
if (vpUpload != null && index < (maxSize)) {
vpUpload.setCurrentItem(index + 1, false);
vpUpload.setCurrentItem(index, false);
if (binding.vpUpload != null && index < (maxSize)) {
binding.vpUpload.setCurrentItem(index + 1, false);
binding.vpUpload.setCurrentItem(index, false);
}
}
@ -810,9 +783,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override
public void onNextButtonClicked(int index) {
if (index < fragments.size() - 1) {
vpUpload.setCurrentItem(index + 1, false);
binding.vpUpload.setCurrentItem(index + 1, false);
fragments.get(index + 1).onBecameVisible();
((LinearLayoutManager) rvThumbnails.getLayoutManager())
((LinearLayoutManager) binding.rvThumbnails.getLayoutManager())
.scrollToPositionWithOffset((index > 0) ? index-1 : 0, 0);
} else {
presenter.handleSubmit();
@ -822,9 +795,9 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
@Override
public void onPreviousButtonClicked(int index) {
if (index != 0) {
vpUpload.setCurrentItem(index - 1, true);
binding.vpUpload.setCurrentItem(index - 1, true);
fragments.get(index - 1).onBecameVisible();
((LinearLayoutManager) rvThumbnails.getLayoutManager())
((LinearLayoutManager) binding.rvThumbnails.getLayoutManager())
.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)
public void onRlContainerTitleClicked() {
rvThumbnails.setVisibility(isTitleExpanded ? View.GONE : View.VISIBLE);
binding.rvThumbnails.setVisibility(isTitleExpanded ? View.GONE : View.VISIBLE);
isTitleExpanded = !isTitleExpanded;
ibToggleTopCard.setRotation(ibToggleTopCard.getRotation() + 180);
binding.ibToggleTopCard.setRotation(binding.ibToggleTopCard.getRotation() + 180);
}
@Override

View file

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

View file

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

View file

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

View file

@ -12,28 +12,19 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
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 androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
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.widget.RxTextView;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.category.CategoryItem;
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.ui.PasteSensitiveTextInputEditText;
import fr.free.nrw.commons.upload.UploadActivity;
import fr.free.nrw.commons.upload.UploadBaseFragment;
import fr.free.nrw.commons.utils.DialogUtil;
@ -48,25 +39,6 @@ import timber.log.Timber;
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
CategoriesContract.UserActionListener presenter;
private UploadCategoryAdapter adapter;
@ -85,17 +57,19 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
private String wikiText;
private String nearbyPlaceCategory;
private UploadCategoriesFragmentBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.upload_categories_fragment, container, false);
binding = UploadCategoriesFragmentBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
final Bundle bundle = getArguments();
if (bundle != null) {
media = bundle.getParcelable("Existing_Categories");
@ -108,20 +82,23 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
}
private void init() {
if (binding == null) {
return;
}
if (media == 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)));
}
} else {
tvTitle.setText(R.string.edit_categories);
tvSubTitle.setVisibility(View.GONE);
btnNext.setText(R.string.menu_save_categories);
btnPrevious.setText(R.string.menu_cancel_upload);
binding.tvTitle.setText(R.string.edit_categories);
binding.tvSubtitle.setVisibility(View.GONE);
binding.btnNext.setText(R.string.menu_save_categories);
binding.btnPrevious.setText(R.string.menu_cancel_upload);
}
setTvSubTitle();
tooltip.setOnClickListener(new OnClickListener() {
binding.tooltip.setOnClickListener(new OnClickListener() {
@Override
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);
@ -132,14 +109,20 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
} else {
presenter.onAttachViewWithMedia(this, media);
}
binding.btnNext.setOnClickListener(v -> onNextButtonClicked());
binding.btnPrevious.setOnClickListener(v -> onPreviousButtonClicked());
initRecyclerView();
addTextChangeListenerToEtSearch();
}
private void addTextChangeListenerToEtSearch() {
subscribe = RxTextView.textChanges(etSearch)
.doOnEach(v -> tilContainerEtSearch.setError(null))
.takeUntil(RxView.detaches(etSearch))
if (binding == null) {
return;
}
subscribe = RxTextView.textChanges(binding.etSearch)
.doOnEach(v -> binding.tilContainerSearch.setError(null))
.takeUntil(RxView.detaches(binding.etSearch))
.debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(filter -> searchForCategory(filter.toString()), Timber::e);
@ -154,7 +137,7 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
if (activity instanceof UploadActivity) {
final boolean isMultipleFileSelected = ((UploadActivity) activity).getIsMultipleFilesSelected();
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);
return Unit.INSTANCE;
}, nearbyPlaceCategory);
rvCategories.setLayoutManager(new LinearLayoutManager(getContext()));
rvCategories.setAdapter(adapter);
if (binding!=null) {
binding.rvCategories.setLayoutManager(new LinearLayoutManager(getContext()));
binding.rvCategories.setAdapter(adapter);
}
}
@Override
@ -181,17 +167,23 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
@Override
public void showProgress(boolean shouldShow) {
pbCategories.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
if (binding != null) {
binding.pbCategories.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
}
}
@Override
public void showError(String error) {
tilContainerEtSearch.setError(error);
if (binding != null) {
binding.tilContainerSearch.setError(error);
}
}
@Override
public void showError(int stringResourceId) {
tilContainerEtSearch.setError(getString(stringResourceId));
if (binding != null) {
binding.tilContainerSearch.setError(getString(stringResourceId));
}
}
@Override
@ -203,16 +195,20 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
}
adapter.notifyDataSetChanged();
if (binding == null) {
return;
}
// Nested waiting for search result data to load into the category
// list and smoothly scroll to the top of the search result list.
rvCategories.post(new Runnable() {
binding.rvCategories.post(new Runnable() {
@Override
public void run() {
rvCategories.smoothScrollToPosition(0);
rvCategories.post(new Runnable() {
binding.rvCategories.smoothScrollToPosition(0);
binding.rvCategories.post(new Runnable() {
@Override
public void run() {
rvCategories.smoothScrollToPosition(0);
binding.rvCategories.smoothScrollToPosition(0);
}
});
}
@ -284,7 +280,9 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
*/
@Override
public void dismissProgressDialog() {
progressDialog.dismiss();
if (progressDialog != null) {
progressDialog.dismiss();
}
}
/**
@ -297,7 +295,6 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
mediaDetailFragment.updateCategories();
}
@OnClick(R.id.btn_next)
public void onNextButtonClicked() {
if (media != null) {
presenter.updateCategories(media, wikiText);
@ -306,7 +303,6 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
}
}
@OnClick(R.id.btn_previous)
public void onPreviousButtonClicked() {
if (media != null) {
presenter.clearPreviousSelection();
@ -325,8 +321,11 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
@Override
protected void onBecameVisible() {
super.onBecameVisible();
if (binding == null) {
return;
}
presenter.selectCategories();
final Editable text = etSearch.getText();
final Editable text = binding.etSearch.getText();
if (text != null) {
presenter.searchForCategories(text.toString());
}
@ -340,9 +339,9 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
super.onResume();
if (media != null) {
etSearch.setOnKeyListener((v, keyCode, event) -> {
binding.etSearch.setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK) {
etSearch.clearFocus();
binding.etSearch.clearFocus();
presenter.clearPreviousSelection();
final MediaDetailFragment mediaDetailFragment = (MediaDetailFragment) getParentFragment();
assert mediaDetailFragment != null;
@ -392,4 +391,10 @@ public class UploadCategoriesFragment extends UploadBaseFragment implements Cate
.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.View;
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 androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
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.widget.RxTextView;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
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.media.MediaDetailFragment;
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.UploadBaseFragment;
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 {
@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
@Named("default_preferences")
public
@ -88,18 +61,20 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
private int count;
private Place nearbyPlace;
private UploadDepictsFragmentBinding binding;
@Nullable
@Override
public android.view.View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.upload_depicts_fragment, container, false);
binding = UploadDepictsFragmentBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull android.view.View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
Bundle bundle = getArguments();
if (bundle != null) {
media = bundle.getParcelable("Existing_Depicts");
@ -117,18 +92,22 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
*/
private void init() {
if (binding == null) {
return;
}
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)));
} else {
depictsTitle.setText(R.string.edit_depictions);
depictsSubTitle.setVisibility(View.GONE);
btnNext.setText(R.string.menu_save_categories);
btnPrevious.setText(R.string.menu_cancel_upload);
binding.depictsTitle.setText(R.string.edit_depictions);
binding.depictsSubtitle.setVisibility(View.GONE);
binding.depictsNext.setText(R.string.menu_save_categories);
binding.depictsPrevious.setText(R.string.menu_cancel_upload);
}
setDepictsSubTitle();
tooltip.setOnClickListener(v -> DialogUtil
binding.tooltip.setOnClickListener(v -> DialogUtil
.showAlertDialog(getActivity(), getString(R.string.depicts_step_title),
getString(R.string.depicts_tooltip), getString(android.R.string.ok), null, true));
if (media == null) {
@ -138,6 +117,9 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
}
initRecyclerView();
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) {
final boolean isMultipleFileSelected = ((UploadActivity) activity).getIsMultipleFilesSelected();
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;
}, nearbyPlace);
}
depictsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
depictsRecyclerView.setAdapter(adapter);
if (binding == null) {
return;
}
binding.depictsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
binding.depictsRecyclerView.setAdapter(adapter);
}
@Override
@ -221,15 +206,21 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
@Override
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
public void showError(Boolean value) {
if (binding == null) {
return;
}
if (value) {
depictsSearchContainer.setError(getString(R.string.no_depiction_found));
binding.depictsSearchContainer.setError(getString(R.string.no_depiction_found));
} 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
// list and smoothly scroll to the top of the search result list.
depictsRecyclerView.post(new Runnable() {
binding.depictsRecyclerView.post(new Runnable() {
@Override
public void run() {
depictsRecyclerView.smoothScrollToPosition(0);
depictsRecyclerView.post(new Runnable() {
binding.depictsRecyclerView.smoothScrollToPosition(0);
binding.depictsRecyclerView.post(new Runnable() {
@Override
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
*/
@OnClick(R.id.depicts_next)
public void onNextButtonClicked() {
if(media != null){
presenter.updateDepictions(media);
@ -332,7 +325,6 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
/**
* Determines the calling fragment by media nullability and act accordingly
*/
@OnClick(R.id.depicts_previous)
public void onPreviousButtonClicked() {
if(media != null){
presenter.clearPreviousSelection();
@ -347,9 +339,9 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
* Text change listener for the edit text view of depicts
*/
private void addTextChangeListenerToSearchBox() {
subscribe = RxTextView.textChanges(depictsSearch)
.doOnEach(v -> depictsSearchContainer.setError(null))
.takeUntil(RxView.detaches(depictsSearch))
subscribe = RxTextView.textChanges(binding.depictsSearch)
.doOnEach(v -> binding.depictsSearchContainer.setError(null))
.takeUntil(RxView.detaches(binding.depictsSearch))
.debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(filter -> searchForDepictions(filter.toString()), Timber::e);
@ -374,9 +366,9 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
super.onResume();
if (media != null) {
depictsSearch.setOnKeyListener((v, keyCode, event) -> {
binding.depictsSearch.setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK) {
depictsSearch.clearFocus();
binding.depictsSearch.clearFocus();
presenter.clearPreviousSelection();
updateDepicts();
goBackToPreviousScreen();
@ -422,4 +414,10 @@ public class DepictsFragment extends UploadBaseFragment implements DepictsContra
.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.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -21,10 +25,18 @@ import androidx.annotation.Nullable;
import fr.free.nrw.commons.databinding.FragmentMediaLicenseBinding;
import fr.free.nrw.commons.upload.UploadActivity;
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.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.utils.DialogUtil;
import java.util.List;
import javax.inject.Inject;
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.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.speech.RecognizerIntent;
import android.text.TextUtils;
import android.view.LayoutInflater;
@ -16,25 +18,16 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatImageButton;
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 fr.free.nrw.commons.LocationPicker.LocationPicker;
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.databinding.FragmentUploadMediaDetailFragmentBinding;
import fr.free.nrw.commons.edit.EditActivity;
import fr.free.nrw.commons.filepicker.UploadableFile;
import fr.free.nrw.commons.kvstore.BasicKvStore;
import fr.free.nrw.commons.kvstore.JsonKvStore;
@ -61,7 +54,6 @@ import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import timber.log.Timber;
import android.os.Parcelable;
public class UploadMediaDetailFragment extends UploadBaseFragment implements
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 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;
@BindView(R.id.btn_copy_subsequent_media)
AppCompatButton btnCopyToSubsequentMedia;
@Inject
UploadMediaDetailsContract.UserActionListener presenter;
@ -154,6 +121,8 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
private UploadMediaDetailFragmentCallback callback;
private FragmentUploadMediaDetailFragmentBinding binding;
public void setCallback(UploadMediaDetailFragmentCallback callback) {
this.callback = callback;
}
@ -182,21 +151,21 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@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
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
if (callback != null) {
init();
}
if(savedInstanceState!=null){
if(uploadMediaDetailAdapter.getItems().size()==0){
if(uploadMediaDetailAdapter.getItems().size()==0 && callback != null){
uploadMediaDetailAdapter.setItems(savedInstanceState.getParcelableArrayList(UPLOAD_MEDIA_DETAILS));
presenter.setUploadMediaDetails(uploadMediaDetailAdapter.getItems(), callback.getIndexInViewFlipper(this));
}
@ -205,43 +174,54 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
}
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)));
tooltip.setOnClickListener(
binding.tooltip.setOnClickListener(
v -> showInfoAlert(R.string.media_detail_step_title, R.string.media_details_tooltip));
initPresenter();
presenter.receiveImage(uploadableFile, place, inAppPictureLocation);
initRecyclerView();
if (callback.getIndexInViewFlipper(this) == 0) {
btnPrevious.setEnabled(false);
btnPrevious.setAlpha(0.5f);
binding.btnPrevious.setEnabled(false);
binding.btnPrevious.setAlpha(0.5f);
} else {
btnPrevious.setEnabled(true);
btnPrevious.setAlpha(1.0f);
binding.btnPrevious.setEnabled(true);
binding.btnPrevious.setAlpha(1.0f);
}
// If the image EXIF data contains the location, show the map icon with a green tick
if (inAppPictureLocation != null ||
(uploadableFile != null && uploadableFile.hasLocation())) {
Drawable mapTick = getResources().getDrawable(R.drawable.ic_map_available_20dp);
locationImageView.setImageDrawable(mapTick);
locationTextView.setText(R.string.edit_location);
binding.locationImageView.setImageDrawable(mapTick);
binding.locationTextView.setText(R.string.edit_location);
} else {
// Otherwise, show the map icon with a red question mark
Drawable mapQuestionMark =
getResources().getDrawable(R.drawable.ic_map_not_available_20dp);
locationImageView.setImageDrawable(mapQuestionMark);
locationTextView.setText(R.string.add_location);
binding.locationImageView.setImageDrawable(mapQuestionMark);
binding.locationTextView.setText(R.string.add_location);
}
//If this is the last media, we have nothing to copy, lets not show the button
if (callback.getIndexInViewFlipper(this) == callback.getTotalNumberOfSteps() - 4) {
btnCopyToSubsequentMedia.setVisibility(View.GONE);
binding.btnCopySubsequentMedia.setVisibility(View.GONE);
} 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();
}
@ -249,7 +229,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
* Attaches the scale change listener to the image view
*/
private void attachImageViewScaleChangeListener() {
photoViewBackgroundImage.setOnScaleChangeListener(
binding.backgroundImage.setOnScaleChangeListener(
(scaleFactor, focusX, focusY) -> {
//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
@ -274,8 +254,8 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""), recentLanguagesDao);
uploadMediaDetailAdapter.setCallback(this::showInfoAlert);
uploadMediaDetailAdapter.setEventListener(this);
rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext()));
rvDescriptions.setAdapter(uploadMediaDetailAdapter);
binding.rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext()));
binding.rvDescriptions.setAdapter(uploadMediaDetailAdapter);
}
/**
@ -288,8 +268,11 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
getString(messageStringId), getString(android.R.string.ok), null, true);
}
@OnClick(R.id.btn_next)
public void onNextButtonClicked() {
if (callback == null) {
return;
}
boolean isValidUploads = presenter.verifyImageQuality(callback.getIndexInViewFlipper(this), inAppPictureLocation);
if (!isValidUploads) {
startActivityWithFlags(
@ -298,12 +281,13 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
}
}
@OnClick(R.id.btn_previous)
public void onPreviousButtonClicked() {
if (callback == null) {
return;
}
callback.onPreviousButtonClicked(callback.getIndexInViewFlipper(this));
}
@OnClick(R.id.ll_edit_image)
public void onEditButtonClicked() {
presenter.onEditButtonClicked(callback.getIndexInViewFlipper(this));
}
@ -343,7 +327,10 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Override
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;
this.uploadItem = uploadItem;
showNearbyFound = true;
if (callback == null) {
return;
}
if (callback.getIndexInViewFlipper(this) == 0) {
if (UploadActivity.nearbyPopupAnswers.containsKey(nearbyPlace)) {
final boolean response = UploadActivity.nearbyPopupAnswers.get(nearbyPlace);
if (response) {
presenter.onUserConfirmedUploadIsOfPlace(nearbyPlace,
callback.getIndexInViewFlipper(this));
if (callback != null) {
presenter.onUserConfirmedUploadIsOfPlace(nearbyPlace,
callback.getIndexInViewFlipper(this));
}
}
} else {
showNearbyPlaceFound(nearbyPlace);
@ -397,11 +389,17 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Override
public void showProgress(boolean shouldShow) {
if (callback == null) {
return;
}
callback.showProgress(shouldShow);
}
@Override
public void onImageValidationSuccess() {
if (callback == null) {
return;
}
callback.onNextButtonClicked(callback.getIndexInViewFlipper(this));
}
@ -411,13 +409,18 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
@Override
protected void onBecameVisible() {
super.onBecameVisible();
if (callback == null) {
return;
}
presenter.fetchTitleAndDescription(callback.getIndexInViewFlipper(this));
if (showNearbyFound) {
if (UploadActivity.nearbyPopupAnswers.containsKey(nearbyPlace)) {
final boolean response = UploadActivity.nearbyPopupAnswers.get(nearbyPlace);
if (response) {
presenter.onUserConfirmedUploadIsOfPlace(nearbyPlace,
callback.getIndexInViewFlipper(this));
if (callback != null) {
presenter.onUserConfirmedUploadIsOfPlace(nearbyPlace,
callback.getIndexInViewFlipper(this));
}
}
} else {
showNearbyPlaceFound(nearbyPlace);
@ -621,10 +624,13 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
return;
}
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)));
callback.changeThumbnail(callback.getIndexInViewFlipper(this),
result);
if (callback != null) {
callback.changeThumbnail(callback.getIndexInViewFlipper(this), result);
}
} catch (Exception 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
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();
@ -709,6 +718,9 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
}
private void deleteThisPicture() {
if (callback == null) {
return;
}
callback.deletePictureAtIndex(callback.getIndexInViewFlipper(this));
}
@ -718,7 +730,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
presenter.onDetachView();
}
@OnClick(R.id.ll_container_title)
public void onLlContainerTitleClicked() {
expandCollapseLlMediaDetail(!isExpanded);
}
@ -728,23 +739,32 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
* @param 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;
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));
}
@Override
public void onPrimaryCaptionTextChange(boolean isNotEmpty) {
btnCopyToSubsequentMedia.setEnabled(isNotEmpty);
btnCopyToSubsequentMedia.setClickable(isNotEmpty);
btnCopyToSubsequentMedia.setAlpha(isNotEmpty ? 1.0f : 0.5f);
btnNext.setEnabled(isNotEmpty);
btnNext.setClickable(isNotEmpty);
btnNext.setAlpha(isNotEmpty ? 1.0f : 0.5f);
if (binding == null) {
return;
}
binding.btnCopySubsequentMedia.setEnabled(isNotEmpty);
binding.btnCopySubsequentMedia.setClickable(isNotEmpty);
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.setManuallyAdded(true);//This was manually added by the user
uploadMediaDetailAdapter.addDescription(uploadMediaDetail);
rvDescriptions.smoothScrollToPosition(uploadMediaDetailAdapter.getItemCount()-1);
binding.rvDescriptions.smoothScrollToPosition(uploadMediaDetailAdapter.getItemCount()-1);
}
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(){
if (callback == null) {
return;
}
presenter.copyTitleAndDescriptionToSubsequentMedia(callback.getIndexInViewFlipper(this));
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.TestCommonsApplication
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.upload.UploadActivity
import fr.free.nrw.commons.upload.UploadBaseFragment
@ -51,41 +52,10 @@ class UploadCategoriesFragmentUnitTests {
private lateinit var context: Context
private lateinit var fragmentManager: FragmentManager
private lateinit var layoutInflater: LayoutInflater
private lateinit var view: View
@Mock
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
private lateinit var adapter: UploadCategoryAdapter
@ -98,6 +68,8 @@ class UploadCategoriesFragmentUnitTests {
@Mock
private lateinit var media: Media
private lateinit var binding : UploadCategoriesFragmentBinding
@Before
fun setUp() {
@ -110,22 +82,13 @@ class UploadCategoriesFragmentUnitTests {
val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.add(fragment, null)
fragmentTransaction.commit()
layoutInflater = LayoutInflater.from(activity)
view = LayoutInflater.from(activity)
.inflate(R.layout.upload_categories_fragment, null) as View
binding = UploadCategoriesFragmentBinding.inflate(layoutInflater)
Whitebox.setInternalState(fragment, "subscribe", subscribe)
Whitebox.setInternalState(fragment, "pbCategories", pbCategories)
Whitebox.setInternalState(fragment, "tilContainerEtSearch", tilContainerEtSearch)
Whitebox.setInternalState(fragment, "adapter", adapter)
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]]")
}
@ -255,7 +218,6 @@ class UploadCategoriesFragmentUnitTests {
fun testShowProgressDialog() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
fragment.showProgressDialog()
verify(progressDialog, times(0)).show()
}
@Test
@ -263,7 +225,6 @@ class UploadCategoriesFragmentUnitTests {
fun testDismissProgressDialog() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
fragment.dismissProgressDialog()
verify(progressDialog, times(1)).dismiss()
}
@Test
@ -300,7 +261,6 @@ class UploadCategoriesFragmentUnitTests {
@Throws(Exception::class)
fun testOnBecameVisible() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
`when`(etSearch.text).thenReturn(editable)
val method: Method = UploadCategoriesFragment::class.java.getDeclaredMethod(
"onBecameVisible"
)

View file

@ -5,10 +5,6 @@ import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
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.FragmentTransaction
import androidx.recyclerview.widget.RecyclerView
@ -53,27 +49,6 @@ class DepictsFragmentUnitTests {
@Mock
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
private lateinit var callback: UploadBaseFragment.Callback
@ -110,16 +85,8 @@ class DepictsFragmentUnitTests {
view = LayoutInflater.from(activity)
.inflate(R.layout.upload_depicts_fragment, null) as View
Whitebox.setInternalState(fragment, "depictsTitle", textView)
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, "adapter", adapter)
}
@ -309,4 +276,4 @@ class DepictsFragmentUnitTests {
Whitebox.setInternalState(fragment, "progressDialog", progressDialog)
fragment.dismissProgressDialog()
}
}
}

View file

@ -142,20 +142,7 @@ class UploadMediaDetailFragmentUnitTest {
llContainerMediaDetail = view.findViewById(R.id.ll_container_media_detail)
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, "llLocationStatus", locationStatusLl)
Whitebox.setInternalState(fragment, "locationImageView", locationImageView)
Whitebox.setInternalState(fragment, "locationTextView", locationTextView)
Whitebox.setInternalState(fragment, "llContainerMediaDetail", llContainerMediaDetail)
Whitebox.setInternalState(fragment, "ibExpandCollapse", ibExpandCollapse)
}
@Test
@ -388,6 +375,7 @@ class UploadMediaDetailFragmentUnitTest {
val cameraPosition = Mockito.mock(CameraPosition::class.java)
val latLng = Mockito.mock(LatLng::class.java)
Whitebox.setInternalState(fragment, "callback", callback)
Whitebox.setInternalState(cameraPosition, "target", latLng)
Whitebox.setInternalState(fragment, "editableUploadItem", uploadItem)
Whitebox.setInternalState(fragment,"isMissingLocationDialog",true)
@ -497,4 +485,4 @@ class UploadMediaDetailFragmentUnitTest {
Assert.assertEquals(shadowIntent.intentClass, LocationPickerActivity::class.java)
}
}
}