mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
* 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()
This commit is contained in:
parent
047059c490
commit
3c9b7ba7a8
9 changed files with 137 additions and 6 deletions
|
|
@ -47,6 +47,7 @@ public class Media implements Parcelable {
|
|||
protected String filename;
|
||||
protected String description; // monolingual description on input...
|
||||
protected String discussion;
|
||||
protected String caption;
|
||||
protected long dataLength;
|
||||
protected Date dateCreated;
|
||||
protected @Nullable Date dateUploaded;
|
||||
|
|
@ -240,6 +241,22 @@ public class Media implements Parcelable {
|
|||
return imageUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Caption of the file.
|
||||
* @param caption
|
||||
*/
|
||||
public void setCaption(String caption) {
|
||||
this.caption = caption;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file Caption as a string.
|
||||
* @return file Caption as a string
|
||||
*/
|
||||
public String getCaption() {
|
||||
return caption;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the file.
|
||||
* @return file name as a string
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
package fr.free.nrw.commons;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
|
|
@ -20,16 +24,18 @@ public class MediaDataExtractor {
|
|||
private final MediaWikiApi mediaWikiApi;
|
||||
private final OkHttpJsonApiClient okHttpJsonApiClient;
|
||||
|
||||
|
||||
@Inject
|
||||
public MediaDataExtractor(MediaWikiApi mwApi,
|
||||
OkHttpJsonApiClient okHttpJsonApiClient) {
|
||||
this.okHttpJsonApiClient = okHttpJsonApiClient;
|
||||
this.mediaWikiApi = mwApi;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified method to extract all details required to show media details.
|
||||
* It fetches media object, deletion status and talk page for the filename
|
||||
* It fetches media object, deletion status, talk page and caption for the filename
|
||||
* @param filename for which the details are to be fetched
|
||||
* @return full Media object with all details including deletion status and talk page
|
||||
*/
|
||||
|
|
@ -37,8 +43,11 @@ public class MediaDataExtractor {
|
|||
Single<Media> mediaSingle = getMediaFromFileName(filename);
|
||||
Single<Boolean> pageExistsSingle = mediaWikiApi.pageExists("Commons:Deletion_requests/" + filename);
|
||||
Single<String> discussionSingle = getDiscussion(filename);
|
||||
return Single.zip(mediaSingle, pageExistsSingle, discussionSingle, (media, deletionStatus, discussion) -> {
|
||||
Single<String> captionSingle = getCaption(filename);
|
||||
|
||||
return Single.zip(mediaSingle, pageExistsSingle, discussionSingle, captionSingle, (media, deletionStatus, discussion, caption) -> {
|
||||
media.setDiscussion(discussion);
|
||||
media.setCaption(caption);
|
||||
if (deletionStatus) {
|
||||
media.setRequestedDeletion();
|
||||
}
|
||||
|
|
@ -68,5 +77,19 @@ public class MediaDataExtractor {
|
|||
Timber.e(throwable, "Error occurred while fetching discussion");
|
||||
return "";
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch caption from the MediaWiki API
|
||||
* @param filename the filename we will return the caption for
|
||||
* @return a single with caption string (an empty string if no caption)
|
||||
*/
|
||||
private Single<String> getCaption(String filename) {
|
||||
return mediaWikiApi.fetchCaptionByFilename(filename)
|
||||
.onErrorReturn(throwable -> {
|
||||
Timber.e(throwable, "Error occurred while fetching caption");
|
||||
return "";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
|||
SimpleDraweeView image;
|
||||
@BindView(R.id.mediaDetailSpacer)
|
||||
MediaDetailSpacer spacer;
|
||||
@BindView(R.id.mediaDetailCaption)
|
||||
TextView mediaCaption;
|
||||
@BindView(R.id.mediaDetailTitle)
|
||||
TextView title;
|
||||
@BindView(R.id.mediaDetailDesc)
|
||||
|
|
@ -315,6 +317,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
|||
coordinates.setText(prettyCoordinates(media));
|
||||
uploadedDate.setText(prettyUploadedDate(media));
|
||||
mediaDiscussion.setText(prettyDiscussion(media));
|
||||
mediaCaption.setText(prettyCaption(media));
|
||||
|
||||
categoryNames.clear();
|
||||
categoryNames.addAll(media.getCategories());
|
||||
|
|
@ -516,6 +519,16 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
|||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
private String prettyCaption(Media media) {
|
||||
String caption = media.getCaption().trim();
|
||||
if (caption.equals("")) {
|
||||
return getString(R.string.detail_caption_empty);
|
||||
} else {
|
||||
return caption;
|
||||
}
|
||||
}
|
||||
|
||||
private String prettyDiscussion(Media media) {
|
||||
String disc = media.getDiscussion().trim();
|
||||
if (disc.equals("")) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.mwapi;
|
|||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
|
|
@ -303,6 +304,26 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
.getString("/api/flow-parsoid-utils/@content"));
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches the Caption of the file with a given name.
|
||||
* @param filename title of the file
|
||||
* @return a single with media caption
|
||||
*/
|
||||
@Override
|
||||
public Single<String> fetchCaptionByFilename(String filename) {
|
||||
return Single.fromCallable(() -> {
|
||||
CustomApiResult apiResult = api.action("wbgetentities")
|
||||
.param("sites", "commonswiki")
|
||||
.param("titles", filename)
|
||||
.param("props", "labels")
|
||||
.param("format", "xml")
|
||||
.param("languages", Locale.getDefault().getLanguage())
|
||||
.param("languagefallback", "1")
|
||||
.get();
|
||||
return apiResult.getString("/api/entities/entity/labels/label/@value");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Single<MediaResult> fetchMediaByFilename(String filename) {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ public interface MediaWikiApi {
|
|||
|
||||
Single<String> parseWikicode(String source);
|
||||
|
||||
Single<String> fetchCaptionByFilename(String filename);
|
||||
|
||||
@NonNull
|
||||
Single<MediaResult> fetchMediaByFilename(String filename);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,34 @@
|
|||
android:orientation="vertical"
|
||||
android:padding="@dimen/standard_gap">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/subBackground"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/standard_gap">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/tiny_gap"
|
||||
android:text="@string/media_detail_caption"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/normal_text"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mediaDetailCaption"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:background="?attr/subBackground"
|
||||
android:padding="@dimen/small_gap"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="@dimen/description_text_size"
|
||||
tools:text="Captions of the media" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@
|
|||
<string name="detail_panel_cats_none">None selected</string>
|
||||
<string name="detail_description_empty">No description</string>
|
||||
<string name="detail_discussion_empty">No discussion</string>
|
||||
<string name="detail_caption_empty">No caption</string>
|
||||
<string name="detail_license_empty">Unknown license</string>
|
||||
<string name="menu_refresh">Refresh</string>
|
||||
<string name="storage_permission_title">Requesting Storage Permission</string>
|
||||
|
|
@ -173,6 +174,7 @@
|
|||
<string name="upload_image_duplicate">This file already exists on Commons. Are you sure you want to proceed?</string>
|
||||
<string name="yes">Yes</string>
|
||||
<string name="no">No</string>
|
||||
<string name="media_detail_caption">Caption</string>
|
||||
<string name="media_detail_title">Title</string>
|
||||
<string name="media_detail_description">Description</string>
|
||||
<string name="media_detail_discussion">Discussion</string>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,9 @@ import io.reactivex.Single
|
|||
import junit.framework.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentMatchers
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.Mock
|
||||
import org.mockito.*
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
/**
|
||||
* Test methods in media data extractor
|
||||
|
|
@ -45,6 +42,8 @@ class MediaDataExtractorTest {
|
|||
`when`(okHttpJsonApiClient?.getMedia(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean()))
|
||||
.thenReturn(Single.just(mock(Media::class.java)))
|
||||
|
||||
Mockito.`when`(mwApi?.fetchCaptionByFilename(ArgumentMatchers.anyString())).thenReturn(Single.just("test caption"))
|
||||
|
||||
`when`(mwApi?.pageExists(ArgumentMatchers.anyString()))
|
||||
.thenReturn(Single.just(true))
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import fr.free.nrw.commons.BuildConfig
|
|||
import fr.free.nrw.commons.TestCommonsApplication
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore
|
||||
import fr.free.nrw.commons.utils.ConfigUtils
|
||||
import io.reactivex.observers.TestObserver
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
|
|
@ -23,6 +24,7 @@ import org.wikipedia.util.DateUtil
|
|||
import java.net.URLDecoder
|
||||
import java.util.*
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(constants = BuildConfig::class, sdk = intArrayOf(21), application = TestCommonsApplication::class)
|
||||
class ApacheHttpClientMediaWikiApiTest {
|
||||
|
|
@ -240,6 +242,30 @@ class ApacheHttpClientMediaWikiApiTest {
|
|||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fetchCaptionByFilename() {
|
||||
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>"))
|
||||
|
||||
val result = testObject.fetchCaptionByFilename("File:foo")
|
||||
val testObserver = TestObserver<String>()
|
||||
result.subscribe(testObserver)
|
||||
assertBasicRequestParameters(server, "GET").let { request ->
|
||||
parseQueryParams(request).let { params ->
|
||||
assertEquals("xml", params["format"])
|
||||
assertEquals("wbgetentities", params["action"])
|
||||
assertEquals("commonswiki", params["sites"])
|
||||
assertEquals("File:foo", params["titles"])
|
||||
assertEquals("labels", params["props"])
|
||||
assertEquals(Locale.getDefault().getLanguage(), params["languages"])
|
||||
assertEquals("1", params["languagefallback"])
|
||||
}
|
||||
}
|
||||
|
||||
testObserver.assertResult("Test")
|
||||
testObserver.assertNoErrors()
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isUserBlockedFromCommonsForInfinitelyBlockedUser() {
|
||||
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>"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue