diff --git a/app/src/main/java/fr/free/nrw/commons/description/DescriptionEditActivity.kt b/app/src/main/java/fr/free/nrw/commons/description/DescriptionEditActivity.kt
index d2231e416..ac0139880 100644
--- a/app/src/main/java/fr/free/nrw/commons/description/DescriptionEditActivity.kt
+++ b/app/src/main/java/fr/free/nrw/commons/description/DescriptionEditActivity.kt
@@ -73,7 +73,6 @@ class DescriptionEditActivity : BaseActivity(), UploadMediaDetailAdapter.EventLi
savedLanguageValue = bundle.getString(Prefs.DESCRIPTION_LANGUAGE)!!
initRecyclerView(descriptionAndCaptions)
- binding.btnAddDescription.setOnClickListener(::onButtonAddDescriptionClicked)
binding.btnEditSubmit.setOnClickListener(::onSubmitButtonClicked)
binding.toolbarBackButton.setOnClickListener(::onBackButtonClicked)
}
@@ -112,17 +111,20 @@ class DescriptionEditActivity : BaseActivity(), UploadMediaDetailAdapter.EventLi
override fun onPrimaryCaptionTextChange(isNotEmpty: Boolean) {}
- private fun onBackButtonClicked(view: View) {
- onBackPressed()
- }
-
- private fun onButtonAddDescriptionClicked(view: View) {
+ /**
+ * Adds new language item to RecyclerView
+ */
+ override fun addLanguage() {
val uploadMediaDetail = UploadMediaDetail()
uploadMediaDetail.isManuallyAdded = true //This was manually added by the user
uploadMediaDetailAdapter.addDescription(uploadMediaDetail)
rvDescriptions!!.smoothScrollToPosition(uploadMediaDetailAdapter.itemCount - 1)
}
+ private fun onBackButtonClicked(view: View) {
+ onBackPressed()
+ }
+
private fun onSubmitButtonClicked(view: View) {
showLoggingProgressBar()
val uploadMediaDetails = uploadMediaDetailAdapter.items
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 70901fba9..2669e426e 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
@@ -15,12 +15,14 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
@@ -190,6 +192,7 @@ public class UploadMediaDetailAdapter extends
}
notifyItemRemoved(position);
notifyItemRangeChanged(position, uploadMediaDetails.size() - position);
+ updateAddButtonVisibility();
}
public class ViewHolder extends RecyclerView.ViewHolder {
@@ -213,6 +216,12 @@ public class UploadMediaDetailAdapter extends
@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;
@@ -292,6 +301,17 @@ public class UploadMediaDetailAdapter extends
descItemEditText.addTextChangedListener(descriptionListener);
initLanguage(position, uploadMediaDetail);
+ if (fragment != null) {
+ FrameLayout.LayoutParams newLayoutParams = (FrameLayout.LayoutParams) clParent.getLayoutParams();
+ newLayoutParams.topMargin = 0;
+ newLayoutParams.leftMargin = 0;
+ newLayoutParams.rightMargin = 0;
+ newLayoutParams.bottomMargin = 0;
+ clParent.setLayoutParams(newLayoutParams);
+ }
+ updateAddButtonVisibility();
+ addButton.setOnClickListener(v -> eventListener.addLanguage());
+
//If the description was manually added by the user, it deserves focus, if not, let the user decide
if (uploadMediaDetail.isManuallyAdded()) {
captionItemEditText.requestFocus();
@@ -557,6 +577,55 @@ public class UploadMediaDetailAdapter extends
}
+ /**
+ * Hides the visibility of the "Add" button for all items in the RecyclerView except
+ * the last item in RecyclerView
+ */
+ private void updateAddButtonVisibility() {
+ int lastItemPosition = getItemCount() - 1;
+ // Hide Add Button for all items
+ for (int i = 0; i < getItemCount(); i++) {
+ if (fragment != null) {
+ if (fragment.getView() != null) {
+ ViewHolder holder = (ViewHolder) ((RecyclerView) fragment.getView()
+ .findViewById(R.id.rv_descriptions)).findViewHolderForAdapterPosition(i);
+ if (holder != null) {
+ holder.addButton.setVisibility(View.GONE);
+ }
+ }
+ } else {
+ if (this.activity != null) {
+ ViewHolder holder = (ViewHolder) ((RecyclerView) activity.findViewById(
+ R.id.rv_descriptions_captions)).findViewHolderForAdapterPosition(i);
+ if (holder != null) {
+ holder.addButton.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+
+ // Show Add Button for the last item
+ if (fragment != null) {
+ if (fragment.getView() != null) {
+ ViewHolder lastItemHolder = (ViewHolder) ((RecyclerView) fragment.getView()
+ .findViewById(R.id.rv_descriptions)).findViewHolderForAdapterPosition(
+ lastItemPosition);
+ if (lastItemHolder != null) {
+ lastItemHolder.addButton.setVisibility(View.VISIBLE);
+ }
+ }
+ } else {
+ if (this.activity != null) {
+ ViewHolder lastItemHolder = (ViewHolder) ((RecyclerView) activity
+ .findViewById(R.id.rv_descriptions_captions)).findViewHolderForAdapterPosition(
+ lastItemPosition);
+ if (lastItemHolder != null) {
+ lastItemHolder.addButton.setVisibility(View.VISIBLE);
+ }
+ }
+ }
+ }
+
public interface Callback {
void showAlert(int mediaDetailDescription, int descriptionInfo);
@@ -565,6 +634,8 @@ public class UploadMediaDetailAdapter extends
public interface EventListener {
void onPrimaryCaptionTextChange(boolean isNotEmpty);
+
+ void addLanguage();
}
enum SelectedVoiceIcon {
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 a3e58ac67..3ac100719 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
@@ -76,8 +76,12 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
public static final String LAST_ZOOM = "last_zoom_level_while_uploading";
@BindView(R.id.tv_title)
TextView tvTitle;
- @BindView(R.id.ib_map)
- AppCompatImageButton ibMap;
+ @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)
@@ -90,8 +94,8 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
AppCompatButton btnNext;
@BindView(R.id.btn_previous)
AppCompatButton btnPrevious;
- @BindView(R.id.edit_image)
- AppCompatButton editImage;
+ @BindView(R.id.ll_edit_image)
+ LinearLayout llEditImage;
@BindView(R.id.tooltip)
ImageView tooltip;
@@ -195,13 +199,15 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
// 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_tick_white_24dp);
- ibMap.setImageDrawable(mapTick);
+ Drawable mapTick = getResources().getDrawable(R.drawable.ic_map_available_20dp);
+ locationImageView.setImageDrawable(mapTick);
+ 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_question_white_24dp);
- ibMap.setImageDrawable(mapQuestionMark);
+ getResources().getDrawable(R.drawable.ic_map_not_available_20dp);
+ locationImageView.setImageDrawable(mapQuestionMark);
+ locationTextView.setText(R.string.add_location);
}
//If this is the last media, we have nothing to copy, lets not show the button
@@ -269,15 +275,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
callback.onPreviousButtonClicked(callback.getIndexInViewFlipper(this));
}
- @OnClick(R.id.btn_add_description)
- public void onButtonAddDescriptionClicked() {
- UploadMediaDetail uploadMediaDetail = new UploadMediaDetail();
- uploadMediaDetail.setManuallyAdded(true);//This was manually added by the user
- uploadMediaDetailAdapter.addDescription(uploadMediaDetail);
- rvDescriptions.smoothScrollToPosition(uploadMediaDetailAdapter.getItemCount()-1);
- }
-
- @OnClick(R.id.edit_image)
+ @OnClick(R.id.ll_edit_image)
public void onEditButtonClicked() {
presenter.onEditButtonClicked(callback.getIndexInViewFlipper(this));
}
@@ -619,8 +617,9 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
editableUploadItem.getGpsCoords().setZoomLevel(zoom);
// Replace the map icon using the one with a green tick
- Drawable mapTick = getResources().getDrawable(R.drawable.ic_map_tick_white_24dp);
- ibMap.setImageDrawable(mapTick);
+ Drawable mapTick = getResources().getDrawable(R.drawable.ic_map_available_20dp);
+ locationImageView.setImageDrawable(mapTick);
+ locationTextView.setText(R.string.edit_location);
Toast.makeText(getContext(), "Location Updated", Toast.LENGTH_LONG).show();
@@ -682,8 +681,8 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
presenter.onDetachView();
}
- @OnClick(R.id.rl_container_title)
- public void onRlContainerTitleClicked() {
+ @OnClick(R.id.ll_container_title)
+ public void onLlContainerTitleClicked() {
expandCollapseLlMediaDetail(!isExpanded);
}
@@ -697,7 +696,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
ibExpandCollapse.setRotation(ibExpandCollapse.getRotation() + 180);
}
- @OnClick(R.id.ib_map) public void onIbMapClicked() {
+ @OnClick(R.id.ll_location_status) public void onIbMapClicked() {
presenter.onMapIconClicked(callback.getIndexInViewFlipper(this));
}
@@ -711,6 +710,17 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
btnNext.setAlpha(isNotEmpty ? 1.0f : 0.5f);
}
+ /**
+ * Adds new language item to RecyclerView
+ */
+ @Override
+ public void addLanguage() {
+ UploadMediaDetail uploadMediaDetail = new UploadMediaDetail();
+ uploadMediaDetail.setManuallyAdded(true);//This was manually added by the user
+ uploadMediaDetailAdapter.addDescription(uploadMediaDetail);
+ rvDescriptions.smoothScrollToPosition(uploadMediaDetailAdapter.getItemCount()-1);
+ }
+
public interface UploadMediaDetailFragmentCallback extends Callback {
void deletePictureAtIndex(int index);
diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml
new file mode 100644
index 000000000..4549ee4e2
--- /dev/null
+++ b/app/src/main/res/drawable/ic_add.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_arrow_16dp.xml b/app/src/main/res/drawable/ic_arrow_16dp.xml
new file mode 100644
index 000000000..d99c0b5e4
--- /dev/null
+++ b/app/src/main/res/drawable/ic_arrow_16dp.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_image_24dp.xml b/app/src/main/res/drawable/ic_image_24dp.xml
new file mode 100644
index 000000000..516e1b37b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_image_24dp.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_map_available_20dp.xml b/app/src/main/res/drawable/ic_map_available_20dp.xml
new file mode 100644
index 000000000..1ddde0082
--- /dev/null
+++ b/app/src/main/res/drawable/ic_map_available_20dp.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_map_not_available_20dp.xml b/app/src/main/res/drawable/ic_map_not_available_20dp.xml
new file mode 100644
index 000000000..36b1eba91
--- /dev/null
+++ b/app/src/main/res/drawable/ic_map_not_available_20dp.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/app/src/main/res/layout/activity_description_edit.xml b/app/src/main/res/layout/activity_description_edit.xml
index 1544eef6a..ed50193a2 100644
--- a/app/src/main/res/layout/activity_description_edit.xml
+++ b/app/src/main/res/layout/activity_description_edit.xml
@@ -65,14 +65,6 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
-
-
-
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
+
+
+ android:layout_width="18dp"
+ android:layout_height="18dp"
+ android:src="@drawable/maplibre_info_icon_default" />
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -109,8 +176,8 @@
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/copy_image_caption_description"
android:padding="@dimen/miniscule_margin"
+ android:text="@string/copy_image_caption_description"
android:textAlignment="textEnd"
android:textColor="@color/button_blue"
android:visibility="gone"
@@ -120,21 +187,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
-
-
@@ -147,16 +206,6 @@
android:layout_marginRight="@dimen/standard_gap"
android:layout_toLeftOf="@+id/btn_next"
android:text="@string/previous" />
-
diff --git a/app/src/main/res/layout/row_item_description.xml b/app/src/main/res/layout/row_item_description.xml
index 064448541..66cb4005c 100644
--- a/app/src/main/res/layout/row_item_description.xml
+++ b/app/src/main/res/layout/row_item_description.xml
@@ -1,6 +1,7 @@
+
+
Learn how to write a useful description
Learn how to write a useful caption
See your achievements
+ Edit Image
+ Edit Location
Thank the author
Error sending thanks to author.
diff --git a/app/src/test/kotlin/fr/free/nrw/commons/description/DescriptionEditActivityUnitTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/description/DescriptionEditActivityUnitTest.kt
index c83e5ff86..b2a33bc23 100644
--- a/app/src/test/kotlin/fr/free/nrw/commons/description/DescriptionEditActivityUnitTest.kt
+++ b/app/src/test/kotlin/fr/free/nrw/commons/description/DescriptionEditActivityUnitTest.kt
@@ -124,18 +124,6 @@ class DescriptionEditActivityUnitTest {
assertEquals(activity.isFinishing, true)
}
- @Test
- @Throws(Exception::class)
- fun testOnButtonAddDescriptionClicked() {
- Shadows.shadowOf(Looper.getMainLooper()).idle()
- val method: Method = DescriptionEditActivity::class.java.getDeclaredMethod(
- "onButtonAddDescriptionClicked", View::class.java
- )
- method.isAccessible = true
- method.invoke(activity, null)
- verify(uploadMediaDetailAdapter).addDescription(UploadMediaDetail())
- }
-
@Test
@Throws(Exception::class)
fun testOnBackButtonClicked() {
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 e8373c3ea..91b77d927 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
@@ -72,7 +72,9 @@ class UploadMediaDetailFragmentUnitTest {
private lateinit var btnNext: AppCompatButton
private lateinit var btnCopyToSubsequentMedia: AppCompatButton
private lateinit var photoViewBackgroundImage: PhotoView
- private lateinit var ibMap: AppCompatImageButton
+ private lateinit var locationStatusLl: LinearLayout
+ private lateinit var locationImageView : ImageView
+ private lateinit var locationTextView : TextView
private lateinit var llContainerMediaDetail: LinearLayout
private lateinit var ibExpandCollapse: AppCompatImageButton
@@ -134,7 +136,9 @@ class UploadMediaDetailFragmentUnitTest {
btnNext = view.findViewById(R.id.btn_next)
btnCopyToSubsequentMedia = view.findViewById(R.id.btn_copy_subsequent_media)
photoViewBackgroundImage = view.findViewById(R.id.backgroundImage)
- ibMap = view.findViewById(R.id.ib_map)
+ locationStatusLl = view.findViewById(R.id.ll_location_status)
+ locationImageView = view.findViewById(R.id.location_image_view)
+ locationTextView = view.findViewById(R.id.location_text_view)
llContainerMediaDetail = view.findViewById(R.id.ll_container_media_detail)
ibExpandCollapse = view.findViewById(R.id.ib_expand_collapse)
@@ -147,7 +151,9 @@ class UploadMediaDetailFragmentUnitTest {
Whitebox.setInternalState(fragment, "btnCopyToSubsequentMedia", btnCopyToSubsequentMedia)
Whitebox.setInternalState(fragment, "photoViewBackgroundImage", photoViewBackgroundImage)
Whitebox.setInternalState(fragment, "uploadMediaDetailAdapter", uploadMediaDetailAdapter)
- Whitebox.setInternalState(fragment, "ibMap", ibMap)
+ 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)
}
@@ -245,13 +251,6 @@ class UploadMediaDetailFragmentUnitTest {
fragment.onPreviousButtonClicked()
}
- @Test
- @Throws(Exception::class)
- fun testOnButtonAddDescriptionClicked() {
- Shadows.shadowOf(Looper.getMainLooper()).idle()
- fragment.onButtonAddDescriptionClicked()
- }
-
@Test
@Throws(Exception::class)
fun testShowSimilarImageFragment() {
@@ -429,9 +428,9 @@ class UploadMediaDetailFragmentUnitTest {
@Test
@Throws(Exception::class)
- fun testOnRlContainerTitleClicked() {
+ fun testOnLlContainerTitleClicked() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
- fragment.onRlContainerTitleClicked()
+ fragment.onLlContainerTitleClicked()
}
@Test