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:
Pierre Monier 2023-11-30 02:07:53 +01:00 committed by GitHub
parent 9028e0ed32
commit e1e4f9329a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 260 additions and 15 deletions

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons.media
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.res.Configuration
import android.os.Bundle
import android.os.Looper
@ -20,6 +21,7 @@ import com.facebook.drawee.generic.GenericDraweeHierarchy
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.soloader.SoLoader
import com.nhaarman.mockitokotlin2.whenever
import com.nhaarman.mockitokotlin2.doReturn
import fr.free.nrw.commons.LocationPicker.LocationPickerActivity
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.R
@ -132,13 +134,19 @@ class MediaDetailFragmentUnitTests {
@Mock
private lateinit var listView: ListView
@Mock
private lateinit var searchView: SearchView
@Mock
private lateinit var intent: Intent
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
fun setUp() {
@ -146,7 +154,6 @@ class MediaDetailFragmentUnitTests {
MockitoAnnotations.openMocks(this)
context = ApplicationProvider.getApplicationContext()
AppAdapter.set(TestAppAdapter())
SoLoader.setInTestMode()
@ -212,6 +219,10 @@ class MediaDetailFragmentUnitTests {
val map = HashMap<String, String>()
map[Locale.getDefault().language] = ""
`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
@ -805,4 +816,30 @@ class MediaDetailFragmentUnitTests {
method.isAccessible = true
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())
}
}

View file

@ -1,24 +1,34 @@
package fr.free.nrw.commons.media
import android.content.Context
import android.graphics.Bitmap
import android.os.Bundle
import android.os.Looper
import android.view.Menu
import android.view.MenuItem
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import androidx.test.core.app.ApplicationProvider
import com.facebook.drawee.backends.pipeline.Fresco
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.TestAppAdapter
import fr.free.nrw.commons.TestCommonsApplication
import fr.free.nrw.commons.auth.SessionManager
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.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@ -30,12 +40,12 @@ import org.robolectric.annotation.LooperMode
import org.wikipedia.AppAdapter
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.util.concurrent.Callable
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [21], application = TestCommonsApplication::class)
@LooperMode(LooperMode.Mode.PAUSED)
class MediaDetailPagerFragmentUnitTests {
private lateinit var fragment: MediaDetailPagerFragment
private lateinit var context: Context
private lateinit var fragmentManager: FragmentManager
@ -49,12 +59,20 @@ class MediaDetailPagerFragmentUnitTests {
@Mock
internal var sessionManager: SessionManager? = null
@InjectMocks
private lateinit var okHttpJsonApiClient: OkHttpJsonApiClient
@Mock
private lateinit var menu: Menu
@Mock
private lateinit var menuItem: MenuItem
@Mock
private lateinit var bitmap: Bitmap
@Before
fun setUp() {
RxAndroidPlugins.setMainThreadSchedulerHandler { Schedulers.trampoline() }
RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
MockitoAnnotations.openMocks(this)
context = ApplicationProvider.getApplicationContext()
@ -67,8 +85,8 @@ class MediaDetailPagerFragmentUnitTests {
val activity = Robolectric.buildActivity(SearchActivity::class.java).create().get()
fragment = MediaDetailPagerFragment.newInstance(false, true);
fragment = MediaDetailPagerFragment.newInstance(false, false);
fragment = MediaDetailPagerFragment.newInstance(false, true)
fragment = MediaDetailPagerFragment.newInstance(false, false)
fragmentManager = activity.supportFragmentManager
val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.add(fragment, null)
@ -78,6 +96,16 @@ class MediaDetailPagerFragmentUnitTests {
SessionManager::class.java.getDeclaredField("context")
fieldContext.isAccessible = true
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
@ -198,4 +226,41 @@ class MediaDetailPagerFragmentUnitTests {
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
}
}