Brion VIBBER has submitted this change and it was merged. Change subject: Add User Contributions page ......................................................................
Add User Contributions page Activated by tapping on user name when logged in. - Need to find alternate location for logout Change-Id: I34cb52277dd1929b64f0f19fc74bdd83cd10418f --- A wikipedia-it/src/main/java/org/wikipedia/test/FetchUserContribsTaskTest.java M wikipedia/AndroidManifest.xml A wikipedia/res/layout/activity_user_contribs.xml M wikipedia/res/layout/fragment_navdrawer.xml A wikipedia/res/layout/group_load_more.xml A wikipedia/res/layout/item_usercontribs_entry.xml M wikipedia/res/values-qq/strings.xml M wikipedia/res/values/strings.xml M wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java M wikipedia/src/main/java/org/wikipedia/PageTitle.java A wikipedia/src/main/java/org/wikipedia/pagehistory/PageHistoryItem.java A wikipedia/src/main/java/org/wikipedia/pagehistory/usercontributions/FetchUserContribsTask.java A wikipedia/src/main/java/org/wikipedia/pagehistory/usercontributions/UserContribsActivity.java 13 files changed, 452 insertions(+), 1 deletion(-) Approvals: Brion VIBBER: Verified; Looks good to me, approved diff --git a/wikipedia-it/src/main/java/org/wikipedia/test/FetchUserContribsTaskTest.java b/wikipedia-it/src/main/java/org/wikipedia/test/FetchUserContribsTaskTest.java new file mode 100644 index 0000000..ebb9050 --- /dev/null +++ b/wikipedia-it/src/main/java/org/wikipedia/test/FetchUserContribsTaskTest.java @@ -0,0 +1,36 @@ +package org.wikipedia.test; + +import android.content.*; +import android.test.*; +import org.wikipedia.*; +import org.wikipedia.pagehistory.usercontributions.*; + +import java.util.concurrent.*; + +public class FetchUserContribsTaskTest extends ActivityUnitTestCase<TestDummyActivity> { + private static final int TASK_COMPLETION_TIMEOUT = 20000; + + public FetchUserContribsTaskTest() { + super(TestDummyActivity.class); + } + + public void testUserContributionsFetch() throws Throwable { + final CountDownLatch completionLatch = new CountDownLatch(1); + startActivity(new Intent(), null, null); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + new FetchUserContribsTask(getInstrumentation().getTargetContext(), new Site("test.wikipedia.org"), "yuvipanda", 10, null) { + @Override + public void onFinish(FetchUserContribsTask.UserContributionsList result) { + assertNotNull(result); + assertNotNull(result.getQueryContinue()); + assertFalse(result.getContribs().size() < 10); + completionLatch.countDown(); + } + }.execute(); + } + }); + assertTrue(completionLatch.await(TASK_COMPLETION_TIMEOUT, TimeUnit.MILLISECONDS)); + } +} diff --git a/wikipedia/AndroidManifest.xml b/wikipedia/AndroidManifest.xml index a3c8abf..6f78e5d 100644 --- a/wikipedia/AndroidManifest.xml +++ b/wikipedia/AndroidManifest.xml @@ -68,6 +68,8 @@ android:label="@string/create_account_activity_title" android:windowSoftInputMode="stateVisible|adjustResize" /> + <activity android:name=".pagehistory.usercontributions.UserContribsActivity" + android:label="@string/activity_my_contributions_title"/> <provider android:authorities="org.wikipedia.history" diff --git a/wikipedia/res/layout/activity_user_contribs.xml b/wikipedia/res/layout/activity_user_contribs.xml new file mode 100644 index 0000000..fe9d28a --- /dev/null +++ b/wikipedia/res/layout/activity_user_contribs.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <ListView android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/user_contribs_list" + /> +</LinearLayout> \ No newline at end of file diff --git a/wikipedia/res/layout/fragment_navdrawer.xml b/wikipedia/res/layout/fragment_navdrawer.xml index 22f1f6b..99b4ab1 100644 --- a/wikipedia/res/layout/fragment_navdrawer.xml +++ b/wikipedia/res/layout/fragment_navdrawer.xml @@ -78,6 +78,7 @@ android:layout_gravity="center_vertical" android:text="@string/nav_item_tap_to_logout" style="?android:textAppearanceSmallInverse" + android:visibility="gone" /> </LinearLayout> </LinearLayout> diff --git a/wikipedia/res/layout/group_load_more.xml b/wikipedia/res/layout/group_load_more.xml new file mode 100644 index 0000000..debf472 --- /dev/null +++ b/wikipedia/res/layout/group_load_more.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="8dp" + android:background="?android:selectableItemBackground" + android:id="@+id/load_more_container" + > + <org.wikipedia.styledviews.StyledTextView + android:id="@+id/load_more_text" + android:layout_width="wrap_content" + android:layout_height="32dp" + android:layout_gravity="center" + android:gravity="center" + style="?android:textAppearanceMedium" + android:text="@string/user_contribs_more_action" + /> + + <ProgressBar + android:id="@+id/load_more_progress" + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_gravity="center" + android:indeterminate="true" + style="?android:progressBarStyleSmall" + android:visibility="gone" + /> + +</FrameLayout> diff --git a/wikipedia/res/layout/item_usercontribs_entry.xml b/wikipedia/res/layout/item_usercontribs_entry.xml new file mode 100644 index 0000000..5919376 --- /dev/null +++ b/wikipedia/res/layout/item_usercontribs_entry.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="8dp" + > + <org.wikipedia.styledviews.StyledTextView + android:layout_width="match_parent" android:layout_height="wrap_content" + android:id="@+id/user_contrib_item_page_name" + style="?android:textAppearanceMedium" + android:textStyle="bold" + /> + + <org.wikipedia.styledviews.StyledTextView + android:layout_width="match_parent" android:layout_height="wrap_content" + android:id="@+id/user_contrib_item_edit_summary" + style="?android:textAppearanceSmall" + /> + + <org.wikipedia.styledviews.StyledTextView + android:layout_width="match_parent" android:layout_height="wrap_content" + android:id="@+id/user_contrib_item_time_ago" + style="?android:textAppearanceSmall" + /> +</LinearLayout> \ No newline at end of file diff --git a/wikipedia/res/values-qq/strings.xml b/wikipedia/res/values-qq/strings.xml index 9c8cb4d..73aef6e 100644 --- a/wikipedia/res/values-qq/strings.xml +++ b/wikipedia/res/values-qq/strings.xml @@ -64,4 +64,6 @@ <string name="zero_settings_devmode_summary">Prerelease explanation text explaining that Wikipedia Zero Devmode on means that Wikipedia Zero detection will be turned on</string> <string name="random_progress">Message shown in progress popup dialog while waiting for a random article to be fetched</string> <string name="create_account_account_created_toast">Message shown in a small toast when account creation is successful.</string> + <string name="user_contribs_more_action">Text shown as a button at the end of lists that let the user load more items.</string> + <string name="activity_my_contributions_title">Title for screen showing list of edits by current user.</string> </resources> diff --git a/wikipedia/res/values/strings.xml b/wikipedia/res/values/strings.xml index 1e7c468..d8ba0db 100644 --- a/wikipedia/res/values/strings.xml +++ b/wikipedia/res/values/strings.xml @@ -120,4 +120,6 @@ <string name="nav_item_login_benefits">If you Log in, your edits will be associated with your username and your IP address will not be publicly visible.</string> <string name="nav_item_tap_to_logout">Tap to log out</string> <string name="create_account_account_created_toast">Account created!</string> + <string name="user_contribs_more_action">Load more</string> + <string name="activity_my_contributions_title">My Contributions</string> </resources> diff --git a/wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java b/wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java index b00b405..1abd875 100644 --- a/wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java +++ b/wikipedia/src/main/java/org/wikipedia/NavDrawerFragment.java @@ -9,6 +9,7 @@ import android.widget.*; import org.wikipedia.history.*; import org.wikipedia.login.*; +import org.wikipedia.pagehistory.usercontributions.*; import org.wikipedia.random.*; import org.wikipedia.savedpages.*; import org.wikipedia.settings.*; @@ -132,7 +133,8 @@ randomHandler.doVistRandomArticle(); break; case R.id.nav_item_username: - doLogout(); + intent.setClass(this.getActivity(), UserContribsActivity.class); + startActivity(intent); break; case R.id.nav_item_send_feedback: // Will be stripped out in prod builds diff --git a/wikipedia/src/main/java/org/wikipedia/PageTitle.java b/wikipedia/src/main/java/org/wikipedia/PageTitle.java index 9d94d31..84b4c3e 100644 --- a/wikipedia/src/main/java/org/wikipedia/PageTitle.java +++ b/wikipedia/src/main/java/org/wikipedia/PageTitle.java @@ -1,10 +1,12 @@ package org.wikipedia; import android.os.*; +import android.text.*; import org.json.*; import java.io.*; import java.net.*; +import java.util.*; /** * Immutable value object representing the text of a page. @@ -29,6 +31,33 @@ this(namespace, text, null, site); } + public PageTitle(final String text, final Site site) { + // FIXME: Does not handle mainspace articles with a colon in the title well at all + String parts[]; + if (text.indexOf("#") != -1) { + try { + this.fragment = URLDecoder.decode(text.split("#")[1], "utf-8"); + parts = text.split("#")[0].split(":"); + } catch (UnsupportedEncodingException e) { + // STUPID STUPID JAVA + throw new RuntimeException(e); + } + } else { + this.fragment = null; + parts = text.split(":"); + } + + if (parts.length > 1) { + this.namespace = parts[0]; + this.text = TextUtils.join(":", Arrays.copyOfRange(parts, 1, parts.length)); + } else { + this.namespace = null; + this.text = parts[0]; + } + + this.site = site; + } + public String getNamespace() { return namespace; } diff --git a/wikipedia/src/main/java/org/wikipedia/pagehistory/PageHistoryItem.java b/wikipedia/src/main/java/org/wikipedia/pagehistory/PageHistoryItem.java new file mode 100644 index 0000000..bb3b5ce --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/pagehistory/PageHistoryItem.java @@ -0,0 +1,75 @@ +package org.wikipedia.pagehistory; + +import android.os.*; +import org.wikipedia.*; + +import java.util.*; + +public class PageHistoryItem implements Parcelable { + private final String username; + private final Date timestamp; + private final String summary; + private final int sizeDiff; + private final PageTitle title; + + public String getUsername() { + return username; + } + + public Date getTimestamp() { + return timestamp; + } + + public String getSummary() { + return summary; + } + + public int getSizeDiff() { + return sizeDiff; + } + + public PageTitle getTitle() { + return title; + } + + public PageHistoryItem(String username, Date timestamp, String summary, int sizeDiff, PageTitle title) { + this.username = username; + this.timestamp = timestamp; + this.summary = summary; + this.sizeDiff = sizeDiff; + this.title = title; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(username); + parcel.writeSerializable(timestamp); + parcel.writeString(summary); + parcel.writeInt(sizeDiff); + parcel.writeParcelable(title, flags); + } + + private PageHistoryItem(Parcel in) { + this.username = in.readString(); + this.timestamp = (Date) in.readSerializable(); + this.summary = in.readString(); + this.sizeDiff = in.readInt(); + this.title = in.readParcelable(PageTitle.class.getClassLoader()); + } + + public static final Parcelable.Creator<PageHistoryItem> CREATOR + = new Parcelable.Creator<PageHistoryItem>() { + public PageHistoryItem createFromParcel(Parcel in) { + return new PageHistoryItem(in); + } + + public PageHistoryItem[] newArray(int size) { + return new PageHistoryItem[size]; + } + }; +} diff --git a/wikipedia/src/main/java/org/wikipedia/pagehistory/usercontributions/FetchUserContribsTask.java b/wikipedia/src/main/java/org/wikipedia/pagehistory/usercontributions/FetchUserContribsTask.java new file mode 100644 index 0000000..631e929 --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/pagehistory/usercontributions/FetchUserContribsTask.java @@ -0,0 +1,84 @@ +package org.wikipedia.pagehistory.usercontributions; + +import android.content.*; +import org.json.*; +import org.mediawiki.api.json.*; +import org.wikipedia.*; +import org.wikipedia.pagehistory.*; + +import java.util.*; + +public class FetchUserContribsTask extends ApiTask<FetchUserContribsTask.UserContributionsList> { + private final WikipediaApp app; + private final Site site; + private final String username; + private final int numberToFetch; + private final String queryContinue; + + public FetchUserContribsTask(Context context, Site site, String username, int numberToFetch, String queryContinue) { + super( + 1, + ((WikipediaApp)context.getApplicationContext()).getAPIForSite(site) + ); + app = (WikipediaApp)context.getApplicationContext(); + this.site = site; + this.username = username; + this.numberToFetch = numberToFetch; + this.queryContinue = queryContinue; + } + + @Override + public RequestBuilder buildRequest(Api api) { + RequestBuilder builder = api.action("query") + .param("list", "usercontribs") + .param("uclimit", String.valueOf(numberToFetch)) + .param("ucuser", username) + .param("ucprop", "title|timestamp|comment|sizediff"); + if (queryContinue != null) { + builder.param("ucstart", queryContinue); + } + return builder; + } + + @Override + public UserContributionsList processResult(ApiResult result) throws Throwable { + String continueString = null; + if (result.asObject().has("query-continue")) { + continueString = result.asObject().optJSONObject("query-continue").optJSONObject("usercontribs").optString("ucstart"); + } + JSONArray contribsJSON = result.asObject().optJSONObject("query").optJSONArray("usercontribs"); + + ArrayList<PageHistoryItem> contribs = new ArrayList<PageHistoryItem>(contribsJSON.length()); + + for (int i = 0; i < contribsJSON.length(); i++) { + JSONObject contribJSON = contribsJSON.optJSONObject(i); + contribs.add(new PageHistoryItem( + contribJSON.optString("user"), + Utils.parseMWDate(contribJSON.optString("timestamp")), + contribJSON.optString("comment"), + contribJSON.optInt("sizeDiff"), + new PageTitle(contribJSON.optString("title"), site) + )); + } + + return new UserContributionsList(contribs, continueString); + } + + public static class UserContributionsList { + private final ArrayList<PageHistoryItem> contribs; + private final String queryContinue; + + public UserContributionsList(ArrayList<PageHistoryItem> contribs, String queryContinue) { + this.contribs = contribs; + this.queryContinue = queryContinue; + } + + public ArrayList<PageHistoryItem> getContribs() { + return contribs; + } + + public String getQueryContinue() { + return queryContinue; + } + } +} diff --git a/wikipedia/src/main/java/org/wikipedia/pagehistory/usercontributions/UserContribsActivity.java b/wikipedia/src/main/java/org/wikipedia/pagehistory/usercontributions/UserContribsActivity.java new file mode 100644 index 0000000..c8bad3b --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/pagehistory/usercontributions/UserContribsActivity.java @@ -0,0 +1,149 @@ +package org.wikipedia.pagehistory.usercontributions; + +import android.os.*; +import android.support.v7.app.*; +import android.view.*; +import android.widget.*; +import org.wikipedia.*; +import org.wikipedia.pagehistory.*; + +import java.util.*; + +public class UserContribsActivity extends ActionBarActivity { + private ListView userContribsList; + private View moreContainer; + private TextView moreText; + private ProgressBar moreProgress; + + private String lastContinue = null; + private ArrayList<PageHistoryItem> contribs = new ArrayList<PageHistoryItem>(); + + private UserContribsAdapter adapter; + + private WikipediaApp app; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_user_contribs); + + app = (WikipediaApp)getApplicationContext(); + + userContribsList = (ListView)findViewById(R.id.user_contribs_list); + moreContainer = getLayoutInflater().inflate(R.layout.group_load_more, null, false); + moreText = (TextView) moreContainer.findViewById(R.id.load_more_text); + moreProgress = (ProgressBar) moreContainer.findViewById(R.id.load_more_progress); + + moreContainer.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + fetchMore(); + } + }); + + adapter = new UserContribsAdapter(); + userContribsList.setAdapter(adapter); + + userContribsList.addFooterView(moreContainer); + + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + if (savedInstanceState != null) { + lastContinue = savedInstanceState.getString("lastContinue"); + contribs = savedInstanceState.getParcelableArrayList("contribs"); + adapter.notifyDataSetChanged(); + } else { + fetchMore(); + } + } + + private boolean isFetching = false; + private void fetchMore() { + if (isFetching) { + return; + } + new FetchUserContribsTask(this, app.getPrimarySite(), app.getUserInfoStorage().getUser().getUsername(), 24, lastContinue) { + @Override + public void onBeforeExecute() { + isFetching = true; + moreProgress.setVisibility(View.VISIBLE); + moreText.setVisibility(View.GONE); + } + + @Override + public void onFinish(UserContributionsList result) { + lastContinue = result.getQueryContinue(); + contribs.addAll(result.getContribs()); + adapter.notifyDataSetChanged(); + isFetching = false; + + moreProgress.setVisibility(View.GONE); + moreText.setVisibility(View.VISIBLE); + + if (lastContinue == null) { + // We got no continue back, so that means we have loaded all the things! + moreContainer.setVisibility(View.GONE); + } + } + }.execute(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + } + + return false; + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString("lastContinue", lastContinue); + outState.putParcelableArrayList("contribs", contribs); + } + + private class UserContribsAdapter extends BaseAdapter{ + + @Override + public int getCount() { + return contribs.size(); + } + + @Override + public Object getItem(int i) { + return contribs.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int pos, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = getLayoutInflater().inflate(R.layout.item_usercontribs_entry, parent, false); + } + + TextView titleText = (TextView) convertView.findViewById(R.id.user_contrib_item_page_name); + TextView summaryText = (TextView) convertView.findViewById(R.id.user_contrib_item_edit_summary); + TextView timeAgoText = (TextView) convertView.findViewById(R.id.user_contrib_item_time_ago); + + PageHistoryItem item = (PageHistoryItem) getItem(pos); + titleText.setText(item.getTitle().getDisplayText()); + summaryText.setText(item.getSummary()); + timeAgoText.setText(Utils.formatDateRelative(item.getTimestamp())); + + if (summaryText.getText().length() == 0) { + summaryText.setVisibility(View.GONE); + } else { + summaryText.setVisibility(View.VISIBLE); + } + + return convertView; + } + } +} \ No newline at end of file -- To view, visit https://gerrit.wikimedia.org/r/119800 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I34cb52277dd1929b64f0f19fc74bdd83cd10418f Gerrit-PatchSet: 8 Gerrit-Project: apps/android/wikipedia Gerrit-Branch: master Gerrit-Owner: Yuvipanda <yuvipa...@gmail.com> Gerrit-Reviewer: Brion VIBBER <br...@wikimedia.org> Gerrit-Reviewer: Siebrand <siebr...@kitano.nl> Gerrit-Reviewer: Yuvipanda <yuvipa...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits