Skip to content

Commit 3c9b7ba

Browse files
neslihanturanashishkumar468
authored andcommitted
Fixes commons-app#2337 - Show captions of image in media details (conflicts fixed) (commons-app#2933)
* Api call * added captions * final commit * some minor changes * sigular * test for captions * mock fetchCaptionbyFileName * corrected method name * * used ? instead of !! (unsafe call on nullable) * updated unit test for fetchCaptionByFilename()
1 parent 047059c commit 3c9b7ba

File tree

9 files changed

+137
-6
lines changed

9 files changed

+137
-6
lines changed

app/src/main/java/fr/free/nrw/commons/Media.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public Media[] newArray(int i) {
4747
protected String filename;
4848
protected String description; // monolingual description on input...
4949
protected String discussion;
50+
protected String caption;
5051
protected long dataLength;
5152
protected Date dateCreated;
5253
protected @Nullable Date dateUploaded;
@@ -240,6 +241,22 @@ public String getImageUrl() {
240241
return imageUrl;
241242
}
242243

244+
/**
245+
* Sets the Caption of the file.
246+
* @param caption
247+
*/
248+
public void setCaption(String caption) {
249+
this.caption = caption;
250+
}
251+
252+
/**
253+
* Gets the file Caption as a string.
254+
* @return file Caption as a string
255+
*/
256+
public String getCaption() {
257+
return caption;
258+
}
259+
243260
/**
244261
* Gets the name of the file.
245262
* @return file name as a string

app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package fr.free.nrw.commons;
22

3+
import android.util.Log;
4+
5+
import java.io.IOException;
6+
37
import javax.inject.Inject;
48
import javax.inject.Singleton;
59

@@ -20,25 +24,30 @@ public class MediaDataExtractor {
2024
private final MediaWikiApi mediaWikiApi;
2125
private final OkHttpJsonApiClient okHttpJsonApiClient;
2226

27+
2328
@Inject
2429
public MediaDataExtractor(MediaWikiApi mwApi,
2530
OkHttpJsonApiClient okHttpJsonApiClient) {
2631
this.okHttpJsonApiClient = okHttpJsonApiClient;
2732
this.mediaWikiApi = mwApi;
33+
2834
}
2935

3036
/**
3137
* Simplified method to extract all details required to show media details.
32-
* It fetches media object, deletion status and talk page for the filename
38+
* It fetches media object, deletion status, talk page and caption for the filename
3339
* @param filename for which the details are to be fetched
3440
* @return full Media object with all details including deletion status and talk page
3541
*/
3642
public Single<Media> fetchMediaDetails(String filename) {
3743
Single<Media> mediaSingle = getMediaFromFileName(filename);
3844
Single<Boolean> pageExistsSingle = mediaWikiApi.pageExists("Commons:Deletion_requests/" + filename);
3945
Single<String> discussionSingle = getDiscussion(filename);
40-
return Single.zip(mediaSingle, pageExistsSingle, discussionSingle, (media, deletionStatus, discussion) -> {
46+
Single<String> captionSingle = getCaption(filename);
47+
48+
return Single.zip(mediaSingle, pageExistsSingle, discussionSingle, captionSingle, (media, deletionStatus, discussion, caption) -> {
4149
media.setDiscussion(discussion);
50+
media.setCaption(caption);
4251
if (deletionStatus) {
4352
media.setRequestedDeletion();
4453
}
@@ -68,5 +77,19 @@ private Single<String> getDiscussion(String filename) {
6877
Timber.e(throwable, "Error occurred while fetching discussion");
6978
return "";
7079
});
80+
81+
}
82+
83+
/**
84+
* Fetch caption from the MediaWiki API
85+
* @param filename the filename we will return the caption for
86+
* @return a single with caption string (an empty string if no caption)
87+
*/
88+
private Single<String> getCaption(String filename) {
89+
return mediaWikiApi.fetchCaptionByFilename(filename)
90+
.onErrorReturn(throwable -> {
91+
Timber.e(throwable, "Error occurred while fetching caption");
92+
return "";
93+
});
7194
}
7295
}

app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ public static MediaDetailFragment forMedia(int index, boolean editable, boolean
101101
SimpleDraweeView image;
102102
@BindView(R.id.mediaDetailSpacer)
103103
MediaDetailSpacer spacer;
104+
@BindView(R.id.mediaDetailCaption)
105+
TextView mediaCaption;
104106
@BindView(R.id.mediaDetailTitle)
105107
TextView title;
106108
@BindView(R.id.mediaDetailDesc)
@@ -315,6 +317,7 @@ private void setTextFields(Media media) {
315317
coordinates.setText(prettyCoordinates(media));
316318
uploadedDate.setText(prettyUploadedDate(media));
317319
mediaDiscussion.setText(prettyDiscussion(media));
320+
mediaCaption.setText(prettyCaption(media));
318321

319322
categoryNames.clear();
320323
categoryNames.addAll(media.getCategories());
@@ -516,6 +519,16 @@ private String prettyDescription(Media media) {
516519
return desc;
517520
}
518521
}
522+
523+
private String prettyCaption(Media media) {
524+
String caption = media.getCaption().trim();
525+
if (caption.equals("")) {
526+
return getString(R.string.detail_caption_empty);
527+
} else {
528+
return caption;
529+
}
530+
}
531+
519532
private String prettyDiscussion(Media media) {
520533
String disc = media.getDiscussion().trim();
521534
if (disc.equals("")) {

app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.content.Context;
44
import android.net.Uri;
55
import android.text.TextUtils;
6+
import android.util.Log;
67

78
import com.google.gson.Gson;
89

@@ -303,6 +304,26 @@ public Single<String> parseWikicode(String source) {
303304
.getString("/api/flow-parsoid-utils/@content"));
304305
}
305306

307+
/**
308+
* fetches the Caption of the file with a given name.
309+
* @param filename title of the file
310+
* @return a single with media caption
311+
*/
312+
@Override
313+
public Single<String> fetchCaptionByFilename(String filename) {
314+
return Single.fromCallable(() -> {
315+
CustomApiResult apiResult = api.action("wbgetentities")
316+
.param("sites", "commonswiki")
317+
.param("titles", filename)
318+
.param("props", "labels")
319+
.param("format", "xml")
320+
.param("languages", Locale.getDefault().getLanguage())
321+
.param("languagefallback", "1")
322+
.get();
323+
return apiResult.getString("/api/entities/entity/labels/label/@value");
324+
});
325+
}
326+
306327
@Override
307328
@NonNull
308329
public Single<MediaResult> fetchMediaByFilename(String filename) {

app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ Single<UploadResult> uploadFileFinalize(String filename, String filekey,
6666

6767
Single<String> parseWikicode(String source);
6868

69+
Single<String> fetchCaptionByFilename(String filename);
70+
6971
@NonNull
7072
Single<MediaResult> fetchMediaByFilename(String filename);
7173

app/src/main/res/layout/fragment_media_detail.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,34 @@
5252
android:orientation="vertical"
5353
android:padding="@dimen/standard_gap">
5454

55+
<LinearLayout
56+
android:layout_width="match_parent"
57+
android:layout_height="wrap_content"
58+
android:background="?attr/subBackground"
59+
android:orientation="vertical"
60+
android:padding="@dimen/standard_gap">
61+
62+
<TextView
63+
android:layout_width="match_parent"
64+
android:layout_height="wrap_content"
65+
android:paddingBottom="@dimen/tiny_gap"
66+
android:text="@string/media_detail_caption"
67+
android:textColor="@android:color/white"
68+
android:textSize="@dimen/normal_text"
69+
android:textStyle="bold" />
70+
71+
<TextView
72+
android:id="@+id/mediaDetailCaption"
73+
android:layout_width="match_parent"
74+
android:layout_height="wrap_content"
75+
android:layout_gravity="start"
76+
android:background="?attr/subBackground"
77+
android:padding="@dimen/small_gap"
78+
android:textColor="@android:color/white"
79+
android:textSize="@dimen/description_text_size"
80+
tools:text="Captions of the media" />
81+
</LinearLayout>
82+
5583
<LinearLayout
5684
android:layout_width="match_parent"
5785
android:layout_height="wrap_content"

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
<string name="detail_panel_cats_none">None selected</string>
161161
<string name="detail_description_empty">No description</string>
162162
<string name="detail_discussion_empty">No discussion</string>
163+
<string name="detail_caption_empty">No caption</string>
163164
<string name="detail_license_empty">Unknown license</string>
164165
<string name="menu_refresh">Refresh</string>
165166
<string name="storage_permission_title">Requesting Storage Permission</string>
@@ -173,6 +174,7 @@
173174
<string name="upload_image_duplicate">This file already exists on Commons. Are you sure you want to proceed?</string>
174175
<string name="yes">Yes</string>
175176
<string name="no">No</string>
177+
<string name="media_detail_caption">Caption</string>
176178
<string name="media_detail_title">Title</string>
177179
<string name="media_detail_description">Description</string>
178180
<string name="media_detail_discussion">Discussion</string>

app/src/test/kotlin/fr/free/nrw/commons/MediaDataExtractorTest.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@ import io.reactivex.Single
77
import junit.framework.Assert.assertTrue
88
import org.junit.Before
99
import org.junit.Test
10-
import org.mockito.ArgumentMatchers
11-
import org.mockito.InjectMocks
12-
import org.mockito.Mock
10+
import org.mockito.*
1311
import org.mockito.Mockito.`when`
1412
import org.mockito.Mockito.mock
15-
import org.mockito.MockitoAnnotations
1613

1714
/**
1815
* Test methods in media data extractor
@@ -45,6 +42,8 @@ class MediaDataExtractorTest {
4542
`when`(okHttpJsonApiClient?.getMedia(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean()))
4643
.thenReturn(Single.just(mock(Media::class.java)))
4744

45+
Mockito.`when`(mwApi?.fetchCaptionByFilename(ArgumentMatchers.anyString())).thenReturn(Single.just("test caption"))
46+
4847
`when`(mwApi?.pageExists(ArgumentMatchers.anyString()))
4948
.thenReturn(Single.just(true))
5049

app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import fr.free.nrw.commons.BuildConfig
66
import fr.free.nrw.commons.TestCommonsApplication
77
import fr.free.nrw.commons.kvstore.JsonKvStore
88
import fr.free.nrw.commons.utils.ConfigUtils
9+
import io.reactivex.observers.TestObserver
910
import okhttp3.OkHttpClient
1011
import okhttp3.mockwebserver.MockResponse
1112
import okhttp3.mockwebserver.MockWebServer
@@ -23,6 +24,7 @@ import org.wikipedia.util.DateUtil
2324
import java.net.URLDecoder
2425
import java.util.*
2526

27+
2628
@RunWith(RobolectricTestRunner::class)
2729
@Config(constants = BuildConfig::class, sdk = intArrayOf(21), application = TestCommonsApplication::class)
2830
class ApacheHttpClientMediaWikiApiTest {
@@ -240,6 +242,30 @@ class ApacheHttpClientMediaWikiApiTest {
240242
assertFalse(result)
241243
}
242244

245+
@Test
246+
fun fetchCaptionByFilename() {
247+
server.enqueue(MockResponse().setBody("<?xml version=\"1.0\"?><api success=\"1\"><entities><entity type=\"mediainfo\" id=\"M77157483\"><labels><label language=\"it\" value=\"Test\" /></labels><statements /></entity></entities></api>"))
248+
249+
val result = testObject.fetchCaptionByFilename("File:foo")
250+
val testObserver = TestObserver<String>()
251+
result.subscribe(testObserver)
252+
assertBasicRequestParameters(server, "GET").let { request ->
253+
parseQueryParams(request).let { params ->
254+
assertEquals("xml", params["format"])
255+
assertEquals("wbgetentities", params["action"])
256+
assertEquals("commonswiki", params["sites"])
257+
assertEquals("File:foo", params["titles"])
258+
assertEquals("labels", params["props"])
259+
assertEquals(Locale.getDefault().getLanguage(), params["languages"])
260+
assertEquals("1", params["languagefallback"])
261+
}
262+
}
263+
264+
testObserver.assertResult("Test")
265+
testObserver.assertNoErrors()
266+
267+
}
268+
243269
@Test
244270
fun isUserBlockedFromCommonsForInfinitelyBlockedUser() {
245271
server.enqueue(MockResponse().setBody("<?xml version=\"1.0\"?><api><query><userinfo id=\"1000\" name=\"testusername\" blockid=\"3000\" blockedby=\"blockerusername\" blockedbyid=\"1001\" blockreason=\"testing\" blockedtimestamp=\"2018-05-24T15:32:09Z\" blockexpiry=\"infinite\"></userinfo></query></api>"))

0 commit comments

Comments
 (0)