mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
Add background color option for media detail page (#5394)
* feat: add backgroundColor property on media * feat: add optional menu items for media backgroundColor * fix: test pass when running in batch * refactor: remove backgroundColor from media * refactor: add string for background color menu * chore: remove useless change * feat: change media image background color * feat: pass backgroundColor to ZoomableActivity * chore: remove extra space
This commit is contained in:
parent
9028e0ed32
commit
e1e4f9329a
7 changed files with 260 additions and 15 deletions
|
|
@ -17,6 +17,7 @@ import android.annotation.SuppressLint;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.drawable.Animatable;
|
import android.graphics.drawable.Animatable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
@ -78,6 +79,7 @@ import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
|
||||||
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
|
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
|
||||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||||
|
import fr.free.nrw.commons.media.ZoomableActivity.ZoomableActivityConstants;
|
||||||
import fr.free.nrw.commons.profile.ProfileActivity;
|
import fr.free.nrw.commons.profile.ProfileActivity;
|
||||||
import fr.free.nrw.commons.settings.Prefs;
|
import fr.free.nrw.commons.settings.Prefs;
|
||||||
import fr.free.nrw.commons.ui.widget.HtmlTextView;
|
import fr.free.nrw.commons.ui.widget.HtmlTextView;
|
||||||
|
|
@ -111,8 +113,11 @@ import timber.log.Timber;
|
||||||
public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
||||||
CategoryEditHelper.Callback {
|
CategoryEditHelper.Callback {
|
||||||
|
|
||||||
private static final int REQUEST_CODE = 1001 ;
|
private static final int REQUEST_CODE = 1001;
|
||||||
private static final int REQUEST_CODE_EDIT_DESCRIPTION = 1002 ;
|
private static final int REQUEST_CODE_EDIT_DESCRIPTION = 1002;
|
||||||
|
private static final String IMAGE_BACKGROUND_COLOR = "image_background_color";
|
||||||
|
static final int DEFAULT_IMAGE_BACKGROUND_COLOR = 0;
|
||||||
|
|
||||||
private boolean editable;
|
private boolean editable;
|
||||||
private boolean isCategoryImage;
|
private boolean isCategoryImage;
|
||||||
private MediaDetailPagerFragment.MediaDetailProvider detailProvider;
|
private MediaDetailPagerFragment.MediaDetailProvider detailProvider;
|
||||||
|
|
@ -388,6 +393,15 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
||||||
zoomableIntent.setData(Uri.parse(media.getImageUrl()));
|
zoomableIntent.setData(Uri.parse(media.getImageUrl()));
|
||||||
zoomableIntent.putExtra(
|
zoomableIntent.putExtra(
|
||||||
ZoomableActivity.ZoomableActivityConstants.ORIGIN, "MediaDetails");
|
ZoomableActivity.ZoomableActivityConstants.ORIGIN, "MediaDetails");
|
||||||
|
|
||||||
|
int backgroundColor = getImageBackgroundColor();
|
||||||
|
if (backgroundColor != DEFAULT_IMAGE_BACKGROUND_COLOR) {
|
||||||
|
zoomableIntent.putExtra(
|
||||||
|
ZoomableActivity.ZoomableActivityConstants.PHOTO_BACKGROUND_COLOR,
|
||||||
|
backgroundColor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ctx.startActivity(
|
ctx.startActivity(
|
||||||
zoomableIntent
|
zoomableIntent
|
||||||
);
|
);
|
||||||
|
|
@ -599,6 +613,10 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
||||||
* - when the high resolution image is available, it replaces the low resolution image
|
* - when the high resolution image is available, it replaces the low resolution image
|
||||||
*/
|
*/
|
||||||
private void setupImageView() {
|
private void setupImageView() {
|
||||||
|
int imageBackgroundColor = getImageBackgroundColor();
|
||||||
|
if (imageBackgroundColor != DEFAULT_IMAGE_BACKGROUND_COLOR) {
|
||||||
|
image.setBackgroundColor(imageBackgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
image.getHierarchy().setPlaceholderImage(R.drawable.image_placeholder);
|
image.getHierarchy().setPlaceholderImage(R.drawable.image_placeholder);
|
||||||
image.getHierarchy().setFailureImage(R.drawable.image_placeholder);
|
image.getHierarchy().setFailureImage(R.drawable.image_placeholder);
|
||||||
|
|
@ -1472,4 +1490,28 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
void nominatingForDeletion(int index);
|
void nominatingForDeletion(int index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the image background color is changed.
|
||||||
|
* You should pass a useable color, not a resource id.
|
||||||
|
* @param color
|
||||||
|
*/
|
||||||
|
public void onImageBackgroundChanged(int color) {
|
||||||
|
int currentColor = getImageBackgroundColor();
|
||||||
|
if (currentColor == color) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
image.setBackgroundColor(color);
|
||||||
|
getImageBackgroundColorPref().edit().putInt(IMAGE_BACKGROUND_COLOR, color).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private SharedPreferences getImageBackgroundColorPref() {
|
||||||
|
return getContext().getSharedPreferences(IMAGE_BACKGROUND_COLOR + media.getPageId(), Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getImageBackgroundColor() {
|
||||||
|
SharedPreferences imageBackgroundColorPref = this.getImageBackgroundColorPref();
|
||||||
|
return imageBackgroundColorPref.getInt(IMAGE_BACKGROUND_COLOR, DEFAULT_IMAGE_BACKGROUND_COLOR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import static fr.free.nrw.commons.Utils.handleWebUrl;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
|
@ -18,6 +20,7 @@ import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||||
|
|
@ -41,9 +44,16 @@ import fr.free.nrw.commons.utils.DownloadUtils;
|
||||||
import fr.free.nrw.commons.utils.ImageUtils;
|
import fr.free.nrw.commons.utils.ImageUtils;
|
||||||
import fr.free.nrw.commons.utils.NetworkUtils;
|
import fr.free.nrw.commons.utils.NetworkUtils;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
|
@ -190,6 +200,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
}
|
}
|
||||||
|
|
||||||
Media m = provider.getMediaAtPosition(pager.getCurrentItem());
|
Media m = provider.getMediaAtPosition(pager.getCurrentItem());
|
||||||
|
MediaDetailFragment mediaDetailFragment = this.adapter.getCurrentMediaDetailFragment();
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_bookmark_current_image:
|
case R.id.menu_bookmark_current_image:
|
||||||
boolean bookmarkExists = bookmarkDao.updateBookmark(bookmark);
|
boolean bookmarkExists = bookmarkDao.updateBookmark(bookmark);
|
||||||
|
|
@ -243,6 +254,16 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_view_report:
|
case R.id.menu_view_report:
|
||||||
showReportDialog(m);
|
showReportDialog(m);
|
||||||
|
case R.id.menu_view_set_white_background:
|
||||||
|
if (mediaDetailFragment != null) {
|
||||||
|
mediaDetailFragment.onImageBackgroundChanged(ContextCompat.getColor(getContext(), R.color.white));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case R.id.menu_view_set_black_background:
|
||||||
|
if (mediaDetailFragment != null) {
|
||||||
|
mediaDetailFragment.onImageBackgroundChanged(ContextCompat.getColor(getContext(), R.color.black));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
@ -372,6 +393,17 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
if (m.getUser() != null) {
|
if (m.getUser() != null) {
|
||||||
menu.findItem(R.id.menu_view_user_page).setEnabled(true).setVisible(true);
|
menu.findItem(R.id.menu_view_user_page).setEnabled(true).setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
URL mediaUrl = new URL(m.getImageUrl());
|
||||||
|
this.handleBackgroundColorMenuItems(
|
||||||
|
() -> BitmapFactory.decodeStream(mediaUrl.openConnection().getInputStream()),
|
||||||
|
menu
|
||||||
|
);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Timber.e("Cant detect media transparency");
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize bookmark object
|
// Initialize bookmark object
|
||||||
bookmark = new Bookmark(
|
bookmark = new Bookmark(
|
||||||
m.getFilename(),
|
m.getFilename(),
|
||||||
|
|
@ -422,6 +454,25 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decide wether or not we should display the background color menu items
|
||||||
|
* We display them if the image is transparent
|
||||||
|
* @param getBitmap
|
||||||
|
* @param menu
|
||||||
|
*/
|
||||||
|
private void handleBackgroundColorMenuItems(Callable<Bitmap> getBitmap, Menu menu) {
|
||||||
|
Observable.fromCallable(
|
||||||
|
getBitmap
|
||||||
|
).subscribeOn(Schedulers.newThread())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(image -> {
|
||||||
|
if (image.hasAlpha()) {
|
||||||
|
menu.findItem(R.id.menu_view_set_white_background).setVisible(true).setEnabled(true);
|
||||||
|
menu.findItem(R.id.menu_view_set_black_background).setVisible(true).setEnabled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void updateBookmarkState(MenuItem item) {
|
private void updateBookmarkState(MenuItem item) {
|
||||||
boolean isBookmarked = bookmarkDao.findBookmark(bookmark);
|
boolean isBookmarked = bookmarkDao.findBookmark(bookmark);
|
||||||
if(isBookmarked) {
|
if(isBookmarked) {
|
||||||
|
|
@ -567,6 +618,18 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
return mCurrentFragment;
|
return mCurrentFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If current fragment is of type MediaDetailFragment, return it, otherwise return null.
|
||||||
|
* @return MediaDetailFragment
|
||||||
|
*/
|
||||||
|
public MediaDetailFragment getCurrentMediaDetailFragment() {
|
||||||
|
if (mCurrentFragment instanceof MediaDetailFragment) {
|
||||||
|
return (MediaDetailFragment) mCurrentFragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to inform the adapter of which item is currently considered to be the "primary",
|
* Called to inform the adapter of which item is currently considered to be the "primary",
|
||||||
* that is the one show to the user as the current page.
|
* that is the one show to the user as the current page.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import android.widget.Button
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
|
|
@ -70,6 +71,8 @@ class ZoomableActivity : BaseActivity() {
|
||||||
@BindView(R.id.zoomable)
|
@BindView(R.id.zoomable)
|
||||||
var photo: ZoomableDraweeView? = null
|
var photo: ZoomableDraweeView? = null
|
||||||
|
|
||||||
|
var photoBackgroundColor: Int? = null
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
@BindView(R.id.zoom_progress_bar)
|
@BindView(R.id.zoom_progress_bar)
|
||||||
var spinner: ProgressBar? = null
|
var spinner: ProgressBar? = null
|
||||||
|
|
@ -180,6 +183,13 @@ class ZoomableActivity : BaseActivity() {
|
||||||
).apply()
|
).apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val backgroundColor = intent.getIntExtra(ZoomableActivityConstants.PHOTO_BACKGROUND_COLOR,
|
||||||
|
MediaDetailFragment.DEFAULT_IMAGE_BACKGROUND_COLOR);
|
||||||
|
|
||||||
|
if (backgroundColor != MediaDetailFragment.DEFAULT_IMAGE_BACKGROUND_COLOR) {
|
||||||
|
photoBackgroundColor = backgroundColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -196,7 +206,7 @@ class ZoomableActivity : BaseActivity() {
|
||||||
/**
|
/**
|
||||||
* Handle view model result.
|
* Handle view model result.
|
||||||
*/
|
*/
|
||||||
private fun handleResult(result: Result){
|
private fun handleResult(result: Result) {
|
||||||
if(result.status is CallbackStatus.SUCCESS){
|
if(result.status is CallbackStatus.SUCCESS){
|
||||||
val images = result.images
|
val images = result.images
|
||||||
if(images.isNotEmpty()) {
|
if(images.isNotEmpty()) {
|
||||||
|
|
@ -609,6 +619,10 @@ class ZoomableActivity : BaseActivity() {
|
||||||
.build()
|
.build()
|
||||||
photo!!.controller = controller
|
photo!!.controller = controller
|
||||||
|
|
||||||
|
if (photoBackgroundColor != null) {
|
||||||
|
photo!!.setBackgroundColor(photoBackgroundColor!!)
|
||||||
|
}
|
||||||
|
|
||||||
if (!images.isNullOrEmpty()) {
|
if (!images.isNullOrEmpty()) {
|
||||||
val selectedIndex = getImagePosition(selectedImages, images!![position])
|
val selectedIndex = getImagePosition(selectedImages, images!![position])
|
||||||
val isSelected = selectedIndex != -1
|
val isSelected = selectedIndex != -1
|
||||||
|
|
@ -667,5 +681,7 @@ class ZoomableActivity : BaseActivity() {
|
||||||
* the custom picker.
|
* the custom picker.
|
||||||
*/
|
*/
|
||||||
const val ORIGIN = "Origin";
|
const val ORIGIN = "Origin";
|
||||||
|
|
||||||
|
const val PHOTO_BACKGROUND_COLOR = "photo_background_color"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,5 +38,25 @@
|
||||||
android:id="@+id/menu_view_report"
|
android:id="@+id/menu_view_report"
|
||||||
android:title="@string/menu_view_report"
|
android:title="@string/menu_view_report"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
<!--
|
||||||
|
Setting visible and enabled to false as default because
|
||||||
|
we only want to show it in a very specific case
|
||||||
|
-->
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_view_set_white_background"
|
||||||
|
android:title="@string/menu_view_set_white_background"
|
||||||
|
android:visible="false"
|
||||||
|
android:enabled="false"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<!--
|
||||||
|
Setting visible and enabled to false as default because
|
||||||
|
we only want to show it in a very specific case
|
||||||
|
-->
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_view_set_black_background"
|
||||||
|
android:title="@string/menu_view_set_black_background"
|
||||||
|
android:visible="false"
|
||||||
|
android:enabled="false"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|
@ -770,6 +770,8 @@ Upload your first media by tapping on the add button.</string>
|
||||||
<string name="image_selected">Image selected</string>
|
<string name="image_selected">Image selected</string>
|
||||||
<string name="image_marked_as_not_for_upload">Image marked as not for upload</string>
|
<string name="image_marked_as_not_for_upload">Image marked as not for upload</string>
|
||||||
<string name="menu_view_report">Report</string>
|
<string name="menu_view_report">Report</string>
|
||||||
|
<string name="menu_view_set_white_background">Set white background</string>
|
||||||
|
<string name="menu_view_set_black_background">Set black background</string>
|
||||||
<string name="report_violation">Report violation</string>
|
<string name="report_violation">Report violation</string>
|
||||||
<string name="report_user">Report this user</string>
|
<string name="report_user">Report this user</string>
|
||||||
<string name="report_content">Report this content</string>
|
<string name="report_content">Report this content</string>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.media
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
|
@ -20,6 +21,7 @@ import com.facebook.drawee.generic.GenericDraweeHierarchy
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
import com.facebook.drawee.view.SimpleDraweeView
|
||||||
import com.facebook.soloader.SoLoader
|
import com.facebook.soloader.SoLoader
|
||||||
import com.nhaarman.mockitokotlin2.whenever
|
import com.nhaarman.mockitokotlin2.whenever
|
||||||
|
import com.nhaarman.mockitokotlin2.doReturn
|
||||||
import fr.free.nrw.commons.LocationPicker.LocationPickerActivity
|
import fr.free.nrw.commons.LocationPicker.LocationPickerActivity
|
||||||
import fr.free.nrw.commons.Media
|
import fr.free.nrw.commons.Media
|
||||||
import fr.free.nrw.commons.R
|
import fr.free.nrw.commons.R
|
||||||
|
|
@ -132,21 +134,26 @@ class MediaDetailFragmentUnitTests {
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var listView: ListView
|
private lateinit var listView: ListView
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var searchView: SearchView
|
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var intent: Intent
|
private lateinit var intent: Intent
|
||||||
|
|
||||||
private lateinit var activity: SearchActivity
|
private lateinit var activity: SearchActivity
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private lateinit var mockContext: Context
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private lateinit var mockSharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private lateinit var mockSharedPreferencesEditor: SharedPreferences.Editor
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
|
|
||||||
MockitoAnnotations.openMocks(this)
|
MockitoAnnotations.openMocks(this)
|
||||||
|
|
||||||
context = ApplicationProvider.getApplicationContext()
|
context = ApplicationProvider.getApplicationContext()
|
||||||
|
|
||||||
AppAdapter.set(TestAppAdapter())
|
AppAdapter.set(TestAppAdapter())
|
||||||
|
|
||||||
SoLoader.setInTestMode()
|
SoLoader.setInTestMode()
|
||||||
|
|
@ -212,6 +219,10 @@ class MediaDetailFragmentUnitTests {
|
||||||
val map = HashMap<String, String>()
|
val map = HashMap<String, String>()
|
||||||
map[Locale.getDefault().language] = ""
|
map[Locale.getDefault().language] = ""
|
||||||
`when`(media.descriptions).thenReturn(map)
|
`when`(media.descriptions).thenReturn(map)
|
||||||
|
|
||||||
|
doReturn(mockSharedPreferences).`when`(mockContext).getSharedPreferences(anyString(), anyInt())
|
||||||
|
doReturn(mockSharedPreferencesEditor).`when`(mockSharedPreferences).edit()
|
||||||
|
doReturn(mockSharedPreferencesEditor).`when`(mockSharedPreferencesEditor).putInt(anyString(), anyInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -805,4 +816,30 @@ class MediaDetailFragmentUnitTests {
|
||||||
method.isAccessible = true
|
method.isAccessible = true
|
||||||
method.invoke(fragment, media)
|
method.invoke(fragment, media)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnImageBackgroundChangedWithDifferentColor() {
|
||||||
|
val spyFragment = spy(fragment)
|
||||||
|
val color = 0xffffff
|
||||||
|
doReturn(mockContext).`when`(spyFragment).context
|
||||||
|
doReturn(-1).`when`(mockSharedPreferences).getInt(anyString(), anyInt())
|
||||||
|
|
||||||
|
spyFragment.onImageBackgroundChanged(color)
|
||||||
|
|
||||||
|
verify(simpleDraweeView, times(1)).setBackgroundColor(color)
|
||||||
|
verify(mockSharedPreferencesEditor, times(1)).putInt(anyString(), anyInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOnImageBackgroundChangedWithSameColor() {
|
||||||
|
val spyFragment = spy(fragment)
|
||||||
|
val color = 0
|
||||||
|
doReturn(mockContext).`when`(spyFragment).context
|
||||||
|
doReturn(color).`when`(mockSharedPreferences).getInt(anyString(), anyInt())
|
||||||
|
|
||||||
|
spyFragment.onImageBackgroundChanged(color)
|
||||||
|
verify(simpleDraweeView, never()).setBackgroundColor(anyInt())
|
||||||
|
verify(mockSharedPreferencesEditor, never()).putInt(anyString(), anyInt())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,34 @@
|
||||||
package fr.free.nrw.commons.media
|
package fr.free.nrw.commons.media
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Bitmap
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.fragment.app.FragmentTransaction
|
import androidx.fragment.app.FragmentTransaction
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
import com.facebook.drawee.backends.pipeline.Fresco
|
||||||
import com.facebook.soloader.SoLoader
|
import com.facebook.soloader.SoLoader
|
||||||
|
import com.nhaarman.mockitokotlin2.any
|
||||||
|
import com.nhaarman.mockitokotlin2.doReturn
|
||||||
|
import com.nhaarman.mockitokotlin2.never
|
||||||
|
import com.nhaarman.mockitokotlin2.times
|
||||||
|
import com.nhaarman.mockitokotlin2.verify
|
||||||
import fr.free.nrw.commons.Media
|
import fr.free.nrw.commons.Media
|
||||||
import fr.free.nrw.commons.TestAppAdapter
|
import fr.free.nrw.commons.TestAppAdapter
|
||||||
import fr.free.nrw.commons.TestCommonsApplication
|
import fr.free.nrw.commons.TestCommonsApplication
|
||||||
import fr.free.nrw.commons.auth.SessionManager
|
import fr.free.nrw.commons.auth.SessionManager
|
||||||
import fr.free.nrw.commons.explore.SearchActivity
|
import fr.free.nrw.commons.explore.SearchActivity
|
||||||
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
|
import io.reactivex.android.plugins.RxAndroidPlugins
|
||||||
|
import io.reactivex.plugins.RxJavaPlugins
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import org.junit.After
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.InjectMocks
|
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.`when`
|
import org.mockito.Mockito.`when`
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
@ -30,12 +40,12 @@ import org.robolectric.annotation.LooperMode
|
||||||
import org.wikipedia.AppAdapter
|
import org.wikipedia.AppAdapter
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner::class)
|
@RunWith(RobolectricTestRunner::class)
|
||||||
@Config(sdk = [21], application = TestCommonsApplication::class)
|
@Config(sdk = [21], application = TestCommonsApplication::class)
|
||||||
@LooperMode(LooperMode.Mode.PAUSED)
|
@LooperMode(LooperMode.Mode.PAUSED)
|
||||||
class MediaDetailPagerFragmentUnitTests {
|
class MediaDetailPagerFragmentUnitTests {
|
||||||
|
|
||||||
private lateinit var fragment: MediaDetailPagerFragment
|
private lateinit var fragment: MediaDetailPagerFragment
|
||||||
private lateinit var context: Context
|
private lateinit var context: Context
|
||||||
private lateinit var fragmentManager: FragmentManager
|
private lateinit var fragmentManager: FragmentManager
|
||||||
|
|
@ -49,11 +59,19 @@ class MediaDetailPagerFragmentUnitTests {
|
||||||
@Mock
|
@Mock
|
||||||
internal var sessionManager: SessionManager? = null
|
internal var sessionManager: SessionManager? = null
|
||||||
|
|
||||||
@InjectMocks
|
@Mock
|
||||||
private lateinit var okHttpJsonApiClient: OkHttpJsonApiClient
|
private lateinit var menu: Menu
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private lateinit var menuItem: MenuItem
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private lateinit var bitmap: Bitmap
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
|
RxAndroidPlugins.setMainThreadSchedulerHandler { Schedulers.trampoline() }
|
||||||
|
RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
|
||||||
|
|
||||||
MockitoAnnotations.openMocks(this)
|
MockitoAnnotations.openMocks(this)
|
||||||
|
|
||||||
|
|
@ -67,8 +85,8 @@ class MediaDetailPagerFragmentUnitTests {
|
||||||
|
|
||||||
val activity = Robolectric.buildActivity(SearchActivity::class.java).create().get()
|
val activity = Robolectric.buildActivity(SearchActivity::class.java).create().get()
|
||||||
|
|
||||||
fragment = MediaDetailPagerFragment.newInstance(false, true);
|
fragment = MediaDetailPagerFragment.newInstance(false, true)
|
||||||
fragment = MediaDetailPagerFragment.newInstance(false, false);
|
fragment = MediaDetailPagerFragment.newInstance(false, false)
|
||||||
fragmentManager = activity.supportFragmentManager
|
fragmentManager = activity.supportFragmentManager
|
||||||
val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
|
val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
|
||||||
fragmentTransaction.add(fragment, null)
|
fragmentTransaction.add(fragment, null)
|
||||||
|
|
@ -78,6 +96,16 @@ class MediaDetailPagerFragmentUnitTests {
|
||||||
SessionManager::class.java.getDeclaredField("context")
|
SessionManager::class.java.getDeclaredField("context")
|
||||||
fieldContext.isAccessible = true
|
fieldContext.isAccessible = true
|
||||||
fieldContext.set(sessionManager, context)
|
fieldContext.set(sessionManager, context)
|
||||||
|
|
||||||
|
doReturn(menuItem).`when`(menu).findItem(any())
|
||||||
|
doReturn(menuItem).`when`(menuItem).isEnabled = any()
|
||||||
|
doReturn(menuItem).`when`(menuItem).isVisible = any()
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
RxAndroidPlugins.reset()
|
||||||
|
RxJavaPlugins.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -198,4 +226,41 @@ class MediaDetailPagerFragmentUnitTests {
|
||||||
fragment.onDataSetChanged()
|
fragment.onDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun invokeHandleBackgroundColorMenuItems(getBitmap: Callable<Bitmap>) {
|
||||||
|
val method: Method = MediaDetailPagerFragment::class.java.getDeclaredMethod(
|
||||||
|
"handleBackgroundColorMenuItems",
|
||||||
|
Callable::class.java,
|
||||||
|
Menu::class.java
|
||||||
|
)
|
||||||
|
method.isAccessible = true
|
||||||
|
method.invoke(fragment, getBitmap, menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testShouldDisplayBackgroundColorMenuWithTransparentMedia() {
|
||||||
|
doReturn(true).`when`(bitmap).hasAlpha()
|
||||||
|
|
||||||
|
invokeHandleBackgroundColorMenuItems {
|
||||||
|
bitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
verify(bitmap, times(1)).hasAlpha()
|
||||||
|
verify(menu, times(2)).findItem(any())
|
||||||
|
verify(menuItem, times(2)).isEnabled = true
|
||||||
|
verify(menuItem, times(2)).isVisible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testShouldNotDisplayBackgroundColorMenuWithOpaqueMedia() {
|
||||||
|
doReturn(false).`when`(bitmap).hasAlpha()
|
||||||
|
|
||||||
|
invokeHandleBackgroundColorMenuItems {
|
||||||
|
bitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
verify(bitmap, times(1)).hasAlpha()
|
||||||
|
verify(menu, never()).findItem(any())
|
||||||
|
verify(menuItem, never()).isEnabled = true
|
||||||
|
verify(menuItem, never()).isVisible = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue