diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageDialogFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageDialogFragment.java index 2491fad2b..c1db2fd4f 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageDialogFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageDialogFragment.java @@ -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; + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ThumbnailsAdapter.java b/app/src/main/java/fr/free/nrw/commons/upload/ThumbnailsAdapter.java index acd63c7a7..fb9ed5514 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ThumbnailsAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ThumbnailsAdapter.java @@ -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 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(); @@ -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 diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadBaseFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadBaseFragment.java index 845f7fbb4..0219c10cf 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadBaseFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadBaseFragment.java @@ -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; /** diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java index b8b2f4d82..d7fe5ffd5 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java @@ -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); + } } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt index 53553bf6d..836541716 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.kt @@ -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 = (repository.selectedCategories.map { it.name }.toMutableList() diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoriesFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoriesFragment.java index 8e771e654..688a9969e 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoriesFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/UploadCategoriesFragment.java @@ -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; + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java index 99542635c..d227b2d95 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java @@ -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; + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.java index 8204aeb0e..18f6297f0 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.java @@ -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; diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java index 85ce3b78b..27386a802 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java @@ -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; + } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/categories/UploadCategoriesFragmentUnitTests.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/categories/UploadCategoriesFragmentUnitTests.kt index 4137b5de0..ff7eb6625 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/categories/UploadCategoriesFragmentUnitTests.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/categories/UploadCategoriesFragmentUnitTests.kt @@ -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" ) diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/depicts/DepictsFragmentUnitTests.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/depicts/DepictsFragmentUnitTests.kt index af851b3e3..54f1edc68 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/depicts/DepictsFragmentUnitTests.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/depicts/DepictsFragmentUnitTests.kt @@ -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() } -} \ No newline at end of file +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragmentUnitTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragmentUnitTest.kt index 9fbeda6d3..791f4ace8 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragmentUnitTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragmentUnitTest.kt @@ -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) } -} \ No newline at end of file +}