BearND has uploaded a new change for review. https://gerrit.wikimedia.org/r/171512
Change subject: Disambiguation and page issues dialog comes up from bottom ...................................................................... Disambiguation and page issues dialog comes up from bottom Change-Id: If216e2b73cfc94184fca64c384575a5d1d903add --- M wikipedia/assets/bundle.js M wikipedia/assets/preview.js A wikipedia/res/layout/dialog_page_info.xml M wikipedia/res/layout/item_issue.xml M wikipedia/res/values/colors.xml M wikipedia/res/values/strings.xml M wikipedia/res/values/styles.xml A wikipedia/src/main/java/org/wikipedia/page/BottomDialog.java D wikipedia/src/main/java/org/wikipedia/page/DisambigHandler.java A wikipedia/src/main/java/org/wikipedia/page/DisambigListAdapter.java D wikipedia/src/main/java/org/wikipedia/page/IssuesHandler.java A wikipedia/src/main/java/org/wikipedia/page/IssuesListAdapter.java A wikipedia/src/main/java/org/wikipedia/page/PageInfo.java A wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java A wikipedia/src/main/java/org/wikipedia/page/PageInfoHandler.java M wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java M wikipedia/src/main/java/org/wikipedia/page/ReferenceDialog.java M www/js/actions.js 18 files changed, 578 insertions(+), 356 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia refs/changes/12/171512/1 diff --git a/wikipedia/assets/bundle.js b/wikipedia/assets/bundle.js index 04b7957..bf925e2 100644 --- a/wikipedia/assets/bundle.js +++ b/wikipedia/assets/bundle.js @@ -66,30 +66,6 @@ curNode = curNode.parentNode; } - function collectIssues( sourceNode ) { - var res = []; - var issues = sourceNode.parentNode.querySelectorAll( 'table.ambox' ); - var i = 0, - len = issues.length; - for (; i < len; i++) { - // .ambox- is used e.g. on eswiki - res.push( issues[i].querySelector( '.mbox-text, .ambox-text' ).innerHTML ); - } - - bridge.sendMessage( 'issuesClicked', { "issues": res } ); - } - - function handleDisambig( sourceNode ) { - var res = []; - var hatnotes = sourceNode.parentNode.querySelectorAll( 'div.hatnote' ); - var i = 0, - len = hatnotes.length; - for (; i < len; i++) { - res.push( hatnotes[i].innerHTML ); - } - bridge.sendMessage( 'disambigClicked', { "hatnotes": res } ); - } - if (sourceNode) { if ( sourceNode.hasAttribute( "data-action" ) ) { var action = sourceNode.getAttribute( "data-action" ); @@ -101,10 +77,10 @@ var href = sourceNode.getAttribute( "href" ); if ( href[0] === "#" ) { var targetId = href.slice(1); - if ("issues" === targetId) { - collectIssues(sourceNode); - } else if ("disambig" === targetId) { - handleDisambig(sourceNode); + if ( "issues" === targetId ) { + issuesClicked( sourceNode ); + } else if ( "disambig" === targetId ) { + disambigClicked( sourceNode ); } else { handleReference( targetId, ancestorContainsClass( sourceNode, "mw-cite-backlink" ) ); } @@ -116,6 +92,41 @@ } }; +function issuesClicked( sourceNode ) { + var issues = collectIssues( sourceNode.parentNode ); + var disambig = collectDisambig( document ); // the other node is not a child of sourceNode + bridge.sendMessage( 'issuesClicked', { "hatnotes": disambig, "issues": issues } ); +} + +function disambigClicked( sourceNode ) { + var disambig = collectDisambig( sourceNode.parentNode ); + var issues = collectIssues( document ); // the other node is not a child of sourceNode + bridge.sendMessage( 'disambigClicked', { "hatnotes": disambig, "issues": issues } ); +} + +function collectDisambig( sourceNode ) { + var res = []; + var hatnotes = sourceNode.querySelectorAll( 'div.hatnote' ); + var i = 0, + len = hatnotes.length; + for (; i < len; i++) { + res.push( hatnotes[i].innerHTML ); + } + return res; +} + +function collectIssues( sourceNode ) { + var res = []; + var issues = sourceNode.querySelectorAll( 'table.ambox' ); + var i = 0, + len = issues.length; + for (; i < len; i++) { + // .ambox- is used e.g. on eswiki + res.push( issues[i].querySelector( '.mbox-text, .ambox-text' ).innerHTML ); + } + return res; +} + module.exports = new ActionsHandler(); },{"./bridge":2}],2:[function(require,module,exports){ diff --git a/wikipedia/assets/preview.js b/wikipedia/assets/preview.js index d173794..4c2d353 100644 --- a/wikipedia/assets/preview.js +++ b/wikipedia/assets/preview.js @@ -66,30 +66,6 @@ curNode = curNode.parentNode; } - function collectIssues( sourceNode ) { - var res = []; - var issues = sourceNode.parentNode.querySelectorAll( 'table.ambox' ); - var i = 0, - len = issues.length; - for (; i < len; i++) { - // .ambox- is used e.g. on eswiki - res.push( issues[i].querySelector( '.mbox-text, .ambox-text' ).innerHTML ); - } - - bridge.sendMessage( 'issuesClicked', { "issues": res } ); - } - - function handleDisambig( sourceNode ) { - var res = []; - var hatnotes = sourceNode.parentNode.querySelectorAll( 'div.hatnote' ); - var i = 0, - len = hatnotes.length; - for (; i < len; i++) { - res.push( hatnotes[i].innerHTML ); - } - bridge.sendMessage( 'disambigClicked', { "hatnotes": res } ); - } - if (sourceNode) { if ( sourceNode.hasAttribute( "data-action" ) ) { var action = sourceNode.getAttribute( "data-action" ); @@ -101,10 +77,10 @@ var href = sourceNode.getAttribute( "href" ); if ( href[0] === "#" ) { var targetId = href.slice(1); - if ("issues" === targetId) { - collectIssues(sourceNode); - } else if ("disambig" === targetId) { - handleDisambig(sourceNode); + if ( "issues" === targetId ) { + issuesClicked( sourceNode ); + } else if ( "disambig" === targetId ) { + disambigClicked( sourceNode ); } else { handleReference( targetId, ancestorContainsClass( sourceNode, "mw-cite-backlink" ) ); } @@ -116,6 +92,41 @@ } }; +function issuesClicked( sourceNode ) { + var issues = collectIssues( sourceNode.parentNode ); + var disambig = collectDisambig( document ); // the other node is not a child of sourceNode + bridge.sendMessage( 'issuesClicked', { "hatnotes": disambig, "issues": issues } ); +} + +function disambigClicked( sourceNode ) { + var disambig = collectDisambig( sourceNode.parentNode ); + var issues = collectIssues( document ); // the other node is not a child of sourceNode + bridge.sendMessage( 'disambigClicked', { "hatnotes": disambig, "issues": issues } ); +} + +function collectDisambig( sourceNode ) { + var res = []; + var hatnotes = sourceNode.querySelectorAll( 'div.hatnote' ); + var i = 0, + len = hatnotes.length; + for (; i < len; i++) { + res.push( hatnotes[i].innerHTML ); + } + return res; +} + +function collectIssues( sourceNode ) { + var res = []; + var issues = sourceNode.querySelectorAll( 'table.ambox' ); + var i = 0, + len = issues.length; + for (; i < len; i++) { + // .ambox- is used e.g. on eswiki + res.push( issues[i].querySelector( '.mbox-text, .ambox-text' ).innerHTML ); + } + return res; +} + module.exports = new ActionsHandler(); },{"./bridge":2}],2:[function(require,module,exports){ diff --git a/wikipedia/res/layout/dialog_page_info.xml b/wikipedia/res/layout/dialog_page_info.xml new file mode 100644 index 0000000..40faa47 --- /dev/null +++ b/wikipedia/res/layout/dialog_page_info.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:background="?attr/page_background_color" + > + + <View + android:layout_width="match_parent" + android:layout_height="0.5dp" + android:background="@color/nav_border" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="8dp" + > + + <TextView + android:id="@+id/page_info_similar_titles_heading" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="8dp" + style="@style/text_heading_gray" + android:text="@string/page_similar_titles" /> + + <TextView + android:id="@+id/page_info_heading_separator" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp" + android:layout_marginLeft="7dp" + android:layout_marginRight="7dp" + style="@style/text_heading_gray" + android:text="|" + tools:ignore="HardcodedText" /> + + <TextView + android:id="@+id/page_info_page_issues_heading" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="8dp" + style="@style/text_heading_gray" + android:text="@string/dialog_page_issues" /> + + </LinearLayout> + + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?android:listDivider" /> + + <ListView + android:id="@+id/page_info_list" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="start" + android:paddingBottom="0dp" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:paddingTop="0dp" + /> + +</LinearLayout> diff --git a/wikipedia/res/layout/item_issue.xml b/wikipedia/res/layout/item_issue.xml index cc92f7b..029802d 100644 --- a/wikipedia/res/layout/item_issue.xml +++ b/wikipedia/res/layout/item_issue.xml @@ -11,7 +11,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:layout_marginLeft="8dp" android:src="@drawable/ic_flag" /> <LinearLayout @@ -21,17 +20,17 @@ android:padding="8dp"> <TextView android:id="@+id/issue_text" - style="?android:textAppearanceMedium" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center" /> - <TextView - android:id="@+id/issue_subtext" - style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_marginTop="8dp" + android:textSize="16sp" /> + <TextView + android:id="@+id/issue_subtext" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginTop="2dp" + android:textSize="12sp" android:textColor="@color/issues_subtext" android:textAllCaps="true"/> diff --git a/wikipedia/res/values/colors.xml b/wikipedia/res/values/colors.xml index 1159f25..be9d50d 100644 --- a/wikipedia/res/values/colors.xml +++ b/wikipedia/res/values/colors.xml @@ -28,6 +28,7 @@ <color name="fulltext_search_highlight">#00AF89</color> <color name="announcement_background">#0C0C0C</color> <color name="announcement_text">#AAAAAA</color> + <color name="page_info_heading">#555555</color> <color name="link_light">#ff347BFF</color> <color name="button_light">#ff777777</color> diff --git a/wikipedia/res/values/strings.xml b/wikipedia/res/values/strings.xml index f5d84cf..2843485 100644 --- a/wikipedia/res/values/strings.xml +++ b/wikipedia/res/values/strings.xml @@ -239,7 +239,7 @@ <string name="color_theme_select">Theme</string> <string name="color_theme_light">Light</string> <string name="color_theme_dark">Dark</string> - <string name="page_similar_titles">Similar pages</string> + <string name="page_similar_titles">Other meanings</string> <string name="search_within_pages">Search within pages…</string> <string name="search_no_results">No results found for \"%s\".</string> <string name="search_did_you_mean">Did you mean \"%s\"?</string> diff --git a/wikipedia/res/values/styles.xml b/wikipedia/res/values/styles.xml index 87fc704..582a0b4 100644 --- a/wikipedia/res/values/styles.xml +++ b/wikipedia/res/values/styles.xml @@ -33,4 +33,9 @@ <item name="android:background">@drawable/button_selector_gray</item> </style> + <style name="text_heading_gray" parent="@android:style/TextAppearance.Medium"> + <item name="android:textSize">16sp</item> + <item name="android:textColor">@color/page_info_heading</item> + </style> + </resources> diff --git a/wikipedia/src/main/java/org/wikipedia/page/BottomDialog.java b/wikipedia/src/main/java/org/wikipedia/page/BottomDialog.java new file mode 100644 index 0000000..6002864 --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/page/BottomDialog.java @@ -0,0 +1,42 @@ +package org.wikipedia.page; + +import android.app.Dialog; +import android.content.Context; +import android.os.Build; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +/** + * A dialog that appears at the bottom of the page. + */ +public class BottomDialog extends Dialog { + private View dialogLayout; + + public BottomDialog(Context context, int dialogLayoutResId) { + super(context); + + LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + dialogLayout = inflater.inflate(dialogLayoutResId, null); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + getWindow().setDimAmount(0.0f); + } + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(dialogLayout); + + getWindow().setBackgroundDrawable(null); + WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); + lp.copyFrom(getWindow().getAttributes()); + lp.width = WindowManager.LayoutParams.MATCH_PARENT; + lp.height = WindowManager.LayoutParams.WRAP_CONTENT; + lp.gravity = Gravity.BOTTOM; + getWindow().setAttributes(lp); + } + + protected View getDialogLayout() { + return dialogLayout; + } +} diff --git a/wikipedia/src/main/java/org/wikipedia/page/DisambigHandler.java b/wikipedia/src/main/java/org/wikipedia/page/DisambigHandler.java deleted file mode 100644 index 8c2d507..0000000 --- a/wikipedia/src/main/java/org/wikipedia/page/DisambigHandler.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.wikipedia.page; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.text.Html; -import android.text.Spannable; -import android.text.TextPaint; -import android.text.style.URLSpan; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.ListAdapter; -import android.widget.TextView; -import org.json.JSONException; -import org.json.JSONObject; -import org.wikipedia.R; -import org.wikipedia.Utils; -import org.wikipedia.WikipediaApp; -import org.wikipedia.bridge.CommunicationBridge; - -/** - * Handles the #disambig links coming from a {@link org.wikipedia.page.PageViewFragment}. - * Automatically goes to the disambiguation page for the selected item. - */ -public abstract class DisambigHandler implements CommunicationBridge.JSEventListener { - private final Activity activity; - private Dialog dlg; - - public DisambigHandler(Activity activity, CommunicationBridge bridge) { - this.activity = activity; - bridge.addListener("disambigClicked", this); - } - - // message from JS bridge: - @Override - public void onMessage(String messageType, JSONObject messagePayload) { - try { - show(Utils.jsonArrayToStringArray(messagePayload.getJSONArray("hatnotes"))); - } catch (JSONException e) { - throw new RuntimeException(e); - } - } - - public void show(final String[] items) { - final WikipediaApp app = (WikipediaApp) activity.getApplicationContext(); - - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - ListAdapter adapter = new ArrayAdapter<String>(activity, 0, items) { - private ViewHolder holder; - - class ViewHolder { - private ImageView icon; - private TextView text; - } - - @Override - public boolean isEnabled(int position) { - return false; // don't make it appear clickable - } - - public View getView(int position, View convertView, ViewGroup parent) { - LayoutInflater inflater = activity.getLayoutInflater(); - if (convertView == null) { - convertView = inflater.inflate(R.layout.item_disambig, null); - holder = new ViewHolder(); - holder.icon = (ImageView) convertView.findViewById(R.id.disambig_icon); - holder.text = (TextView) convertView.findViewById(R.id.disambig_text); - convertView.setTag(holder); - } else { - // view already defined, retrieve view holder - holder = (ViewHolder) convertView.getTag(); - } - - holder.text.setText(Html.fromHtml(items[position])); - holder.text.setMovementMethod(new LinkMovementMethodExt(getLinkHandler()) { - @Override - public boolean onTouchEvent(final TextView widget, final Spannable buffer, final MotionEvent event) { - boolean ret = super.onTouchEvent(widget, buffer, event); - if (ret && event.getAction() == MotionEvent.ACTION_UP && dlg != null) { - dlg.dismiss(); - } - return ret; - } - }); - stripUnderlines(holder.text); - app.adjustLinkDrawableToTheme(holder.icon.getDrawable()); - return convertView; - } - - private void stripUnderlines(TextView textView) { - Spannable s = (Spannable)textView.getText(); - URLSpan[] spans = s.getSpans(0, s.length(), URLSpan.class); - for (URLSpan span: spans) { - int start = s.getSpanStart(span); - int end = s.getSpanEnd(span); - s.removeSpan(span); - span = new URLSpan(span.getURL()) { - @Override - public void updateDrawState(TextPaint ds) { - super.updateDrawState(ds); - ds.setUnderlineText(false); - } - }; - s.setSpan(span, start, end, 0); - } - textView.setText(s); - } - }; - - builder.setAdapter(adapter, null); - builder.setTitle(R.string.page_similar_titles); - dlg = builder.create(); - dlg.show(); - } - - public abstract LinkHandler getLinkHandler(); - -} diff --git a/wikipedia/src/main/java/org/wikipedia/page/DisambigListAdapter.java b/wikipedia/src/main/java/org/wikipedia/page/DisambigListAdapter.java new file mode 100644 index 0000000..ed27f5b --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/page/DisambigListAdapter.java @@ -0,0 +1,87 @@ +package org.wikipedia.page; + +import org.wikipedia.R; +import org.wikipedia.WikipediaApp; +import android.app.Activity; +import android.text.Html; +import android.text.Spannable; +import android.text.TextPaint; +import android.text.style.URLSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +/** + * + */ +class DisambigListAdapter extends ArrayAdapter<String> { + private final Activity activity; + private final String[] items; + private LinkMovementMethodExt movementMethod; + + /** + * Constructor + * @param activity The current activity. + * @param items The objects to represent in the ListView. + */ + public DisambigListAdapter(Activity activity, String[] items, LinkMovementMethodExt movementMethod) { + super(activity, 0, items); + this.activity = activity; + this.items = items; + this.movementMethod = movementMethod; + } + + class ViewHolder { + private ImageView icon; + private TextView text; + } + + @Override + public boolean isEnabled(int position) { + return false; // don't make it appear clickable + } + + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = activity.getLayoutInflater(); + ViewHolder holder; + if (convertView == null) { + convertView = inflater.inflate(R.layout.item_disambig, null); + holder = new ViewHolder(); + holder.icon = (ImageView) convertView.findViewById(R.id.disambig_icon); + holder.text = (TextView) convertView.findViewById(R.id.disambig_text); + convertView.setTag(holder); + } else { + // view already defined, retrieve view holder + holder = (ViewHolder) convertView.getTag(); + } + + holder.text.setText(Html.fromHtml(items[position])); + holder.text.setMovementMethod(movementMethod); + stripUnderlines(holder.text); + final WikipediaApp app = (WikipediaApp) activity.getApplicationContext(); + app.adjustLinkDrawableToTheme(holder.icon.getDrawable()); + return convertView; + } + + private void stripUnderlines(TextView textView) { + Spannable s = (Spannable)textView.getText(); + URLSpan[] spans = s.getSpans(0, s.length(), URLSpan.class); + for (URLSpan span: spans) { + int start = s.getSpanStart(span); + int end = s.getSpanEnd(span); + s.removeSpan(span); + span = new URLSpan(span.getURL()) { + @Override + public void updateDrawState(TextPaint ds) { + super.updateDrawState(ds); + ds.setUnderlineText(false); + } + }; + s.setSpan(span, start, end, 0); + } + textView.setText(s); + } +} diff --git a/wikipedia/src/main/java/org/wikipedia/page/IssuesHandler.java b/wikipedia/src/main/java/org/wikipedia/page/IssuesHandler.java deleted file mode 100644 index 6e5747d..0000000 --- a/wikipedia/src/main/java/org/wikipedia/page/IssuesHandler.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.wikipedia.page; - -import android.app.Activity; -import android.app.AlertDialog; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.ListAdapter; -import android.widget.TextView; -import org.json.JSONException; -import org.json.JSONObject; -import org.wikipedia.R; -import org.wikipedia.Utils; -import org.wikipedia.WikipediaApp; -import org.wikipedia.bridge.CommunicationBridge; - -/** - * Handles the #issues links coming from a {@link org.wikipedia.page.PageViewFragment}. - * Shows a dialog with a list of issues when the issues link is clicked. - */ -public class IssuesHandler implements CommunicationBridge.JSEventListener { - private static final String SEPARATOR = "<small><i>("; - private static final String SEPARATOR_END = ")</i></small>"; - - private final Activity activity; - - public IssuesHandler(final Activity activity, CommunicationBridge bridge) { - this.activity = activity; - bridge.addListener("issuesClicked", this); - } - - // message from JS bridge: - @Override - public void onMessage(String messageType, JSONObject messagePayload) { - try { - show(Utils.jsonArrayToStringArray(messagePayload.getJSONArray("issues"))); - } catch (JSONException e) { - throw new RuntimeException(e); - } - } - - public void show(final String[] items) { - final WikipediaApp app = (WikipediaApp) activity.getApplicationContext(); - - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - ListAdapter adapter = new ArrayAdapter<String>(activity, 0, items) { - private ViewHolder holder; - - class ViewHolder { - private ImageView icon; - private TextView text; - private TextView subText; - } - - @Override - public boolean isEnabled(int position) { - return false; // don't make it appear clickable - } - - public View getView(int position, View convertView, ViewGroup parent) { - LayoutInflater inflater = activity.getLayoutInflater(); - if (convertView == null) { - convertView = inflater.inflate(R.layout.item_issue, null); - holder = new ViewHolder(); - holder.icon = (ImageView) convertView.findViewById(R.id.issue_icon); - holder.text = (TextView) convertView.findViewById(R.id.issue_text); - holder.subText = (TextView) convertView.findViewById(R.id.issue_subtext); - convertView.setTag(holder); - } else { - // view already defined, retrieve view holder - holder = (ViewHolder) convertView.getTag(); - } - - updateText(position); - app.adjustLinkDrawableToTheme(holder.icon.getDrawable()); - return convertView; - } - - private void updateText(int position) { - String fullText = items[position].replaceAll(" href\\s*=", " x="); // disable links - int end = fullText.lastIndexOf(SEPARATOR_END); - int start = fullText.lastIndexOf(SEPARATOR, end); - if (start != -1 && end != -1) { - String text1 = fullText.substring(0, start); - String text2 = fullText.substring(start + SEPARATOR.length(), end); - holder.text.setText(Html.fromHtml(text1)); - holder.subText.setText(Html.fromHtml(text2)); - holder.subText.setVisibility(View.VISIBLE); - } else { - holder.text.setText(Html.fromHtml(fullText)); - holder.subText.setVisibility(View.GONE); - } - } - }; - - builder.setAdapter(adapter, null); - builder.setTitle(R.string.dialog_page_issues); - - builder.create().show(); - } -} diff --git a/wikipedia/src/main/java/org/wikipedia/page/IssuesListAdapter.java b/wikipedia/src/main/java/org/wikipedia/page/IssuesListAdapter.java new file mode 100644 index 0000000..624dff3 --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/page/IssuesListAdapter.java @@ -0,0 +1,81 @@ +package org.wikipedia.page; + +import org.wikipedia.R; +import org.wikipedia.WikipediaApp; +import android.app.Activity; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +/** + * + */ +class IssuesListAdapter extends ArrayAdapter<String> { + private static final String SEPARATOR = "<small><i>("; + private static final String SEPARATOR_END = ")</i></small>"; + private final Activity activity; + private final String[] items; + + private ViewHolder holder; + + /** + * Constructor + * @param activity The current activity. + * @param items The objects to represent in the ListView. + */ + public IssuesListAdapter(Activity activity, String[] items) { + super(activity, 0, items); + this.activity = activity; + this.items = items; + } + + class ViewHolder { + private ImageView icon; + private TextView text; + private TextView subText; + } + + @Override + public boolean isEnabled(int position) { + return false; // don't make it appear clickable + } + + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = activity.getLayoutInflater(); + if (convertView == null) { + convertView = inflater.inflate(R.layout.item_issue, null); + holder = new ViewHolder(); + holder.icon = (ImageView) convertView.findViewById(R.id.issue_icon); + holder.text = (TextView) convertView.findViewById(R.id.issue_text); + holder.subText = (TextView) convertView.findViewById(R.id.issue_subtext); + convertView.setTag(holder); + } else { + // view already defined, retrieve view holder + holder = (ViewHolder) convertView.getTag(); + } + + updateText(position); + ((WikipediaApp) activity.getApplicationContext()).adjustLinkDrawableToTheme(holder.icon.getDrawable()); + return convertView; + } + + private void updateText(int position) { + String fullText = items[position].replaceAll(" href\\s*=", " x="); // disable links + int end = fullText.lastIndexOf(SEPARATOR_END); + int start = fullText.lastIndexOf(SEPARATOR, end); + if (start != -1 && end != -1) { + String text1 = fullText.substring(0, start); + String text2 = fullText.substring(start + SEPARATOR.length(), end); + holder.text.setText(Html.fromHtml(text1)); + holder.subText.setText(Html.fromHtml(text2)); + holder.subText.setVisibility(View.VISIBLE); + } else { + holder.text.setText(Html.fromHtml(fullText)); + holder.subText.setVisibility(View.GONE); + } + } +} diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageInfo.java b/wikipedia/src/main/java/org/wikipedia/page/PageInfo.java new file mode 100644 index 0000000..31f12c7 --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/page/PageInfo.java @@ -0,0 +1,22 @@ +package org.wikipedia.page; + +/** + * + */ +public class PageInfo { + private final String[] disambigs; + private final String[] issues; + + public PageInfo(String[] disambigs, String[] issues) { + this.disambigs = disambigs; + this.issues = issues; + } + + public String[] getDisambigs() { + return disambigs; + } + + public String[] getIssues() { + return issues; + } +} diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java b/wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java new file mode 100644 index 0000000..eddb743 --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/page/PageInfoDialog.java @@ -0,0 +1,69 @@ +package org.wikipedia.page; + +import org.wikipedia.R; +import android.app.Activity; +import android.graphics.Typeface; +import android.view.View; +import android.widget.ListView; +import android.widget.TextView; + +/** + * A dialog to host page issues and disambig information. + */ +class PageInfoDialog extends BottomDialog { + private final Activity activity; + private final PageInfo info; + private final LinkMovementMethodExt movementMethod; + private ListView list; + private TextView disambigHeading; + private TextView issuesHeading; + + PageInfoDialog(Activity activity, PageInfo pageInfo, int height, LinkMovementMethodExt movementMethod) { + super(activity, R.layout.dialog_page_info); + this.activity = activity; + info = pageInfo; + this.movementMethod = movementMethod; + + View parentView = getDialogLayout(); + list = (ListView) parentView.findViewById(R.id.page_info_list); + disambigHeading = (TextView) parentView.findViewById(R.id.page_info_similar_titles_heading); + issuesHeading = (TextView) parentView.findViewById(R.id.page_info_page_issues_heading); + View separatorHeading = parentView.findViewById(R.id.page_info_heading_separator); + + parentView.setMinimumHeight(height); + if (pageInfo.getDisambigs().length > 0) { + disambigHeading.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showDisambig(); + } + }); + } else { + disambigHeading.setVisibility(View.GONE); + separatorHeading.setVisibility(View.GONE); + } + if (pageInfo.getIssues().length > 0) { + issuesHeading.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showIssues(); + } + }); + } else { + issuesHeading.setVisibility(View.GONE); + separatorHeading.setVisibility(View.GONE); + } + } + + void showDisambig() { + list.setAdapter(new DisambigListAdapter(activity, info.getDisambigs(), movementMethod)); + disambigHeading.setTypeface(null, Typeface.BOLD); + issuesHeading.setTypeface(null, Typeface.NORMAL); + } + + void showIssues() { + list.setAdapter(new IssuesListAdapter(activity, info.getIssues())); + disambigHeading.setTypeface(null, Typeface.NORMAL); + issuesHeading.setTypeface(null, Typeface.BOLD); + } +} diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageInfoHandler.java b/wikipedia/src/main/java/org/wikipedia/page/PageInfoHandler.java new file mode 100644 index 0000000..ece0850 --- /dev/null +++ b/wikipedia/src/main/java/org/wikipedia/page/PageInfoHandler.java @@ -0,0 +1,59 @@ +package org.wikipedia.page; + +import org.wikipedia.Utils; +import org.wikipedia.bridge.CommunicationBridge; +import org.json.JSONException; +import org.json.JSONObject; +import android.app.Activity; +import android.text.Spannable; +import android.view.MotionEvent; +import android.widget.TextView; + +/** + * A handler for both disambiguation and page issues information. + * It listens to disambig and page issues link clicks from the WebView. + * When clicked it shows the PageInfoDialog with the respective list. + */ +abstract class PageInfoHandler implements CommunicationBridge.JSEventListener { + private final Activity activity; + private PageInfoDialog dialog; + + PageInfoHandler(Activity activity, CommunicationBridge bridge) { + this.activity = activity; + bridge.addListener("disambigClicked", this); + bridge.addListener("issuesClicked", this); + } + + private LinkMovementMethodExt movementMethod = new LinkMovementMethodExt(getLinkHandler()) { + @Override + public boolean onTouchEvent(final TextView widget, final Spannable buffer, final MotionEvent event) { + boolean ret = super.onTouchEvent(widget, buffer, event); + if (ret && event.getAction() == MotionEvent.ACTION_UP) { + dialog.dismiss(); + } + return ret; + } + }; + + // message from JS bridge: + @Override + public void onMessage(String messageType, JSONObject messagePayload) { + try { + PageInfo info = new PageInfo(Utils.jsonArrayToStringArray(messagePayload.getJSONArray("hatnotes")), + Utils.jsonArrayToStringArray(messagePayload.getJSONArray("issues"))); + dialog = new PageInfoDialog(activity, info, getDialogHeight(), movementMethod); + dialog.show(); + if ("disambigClicked".equals(messageType)) { + dialog.showDisambig(); + } else if ("issuesClicked".equals(messageType)) { + dialog.showIssues(); + } + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + abstract LinkHandler getLinkHandler(); + + abstract int getDialogHeight(); +} diff --git a/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java b/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java index d2e03bd..0d48321 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java +++ b/wikipedia/src/main/java/org/wikipedia/page/PageViewFragmentInternal.java @@ -105,6 +105,7 @@ private PageTitle title; private PageTitle titleOriginal; private View contentsContainer; + private ViewGroup imagesContainer; private LeadImagesHandler leadImagesHandler; private ObservableWebView webView; private View networkError; @@ -346,12 +347,16 @@ } }; - new IssuesHandler(getActivity(), bridge); - - new DisambigHandler(getActivity(), bridge){ + new PageInfoHandler(getActivity(), bridge) { @Override - public LinkHandler getLinkHandler() { + LinkHandler getLinkHandler() { return linkHandler; + } + + @Override + int getDialogHeight() { + // could have scrolled up a bit but the page info links must still be visible else they couldn't have been clicked + return webView.getHeight() + webView.getScrollY() - imagesContainer.getHeight(); } }; @@ -379,8 +384,8 @@ editHandler = new EditHandler(parentFragment, bridge); new SearchBarHideHandler(webView, getActivity()); - leadImagesHandler = new LeadImagesHandler(parentFragment, bridge, webView, - (ViewGroup)parentFragment.getView().findViewById(R.id.page_images_container)); + imagesContainer = (ViewGroup) parentFragment.getView().findViewById(R.id.page_images_container); + leadImagesHandler = new LeadImagesHandler(parentFragment, bridge, webView, imagesContainer); //is this page in cache?? if (PAGE_CACHE.has(titleOriginal)) { diff --git a/wikipedia/src/main/java/org/wikipedia/page/ReferenceDialog.java b/wikipedia/src/main/java/org/wikipedia/page/ReferenceDialog.java index 58b639a..e9ad170 100644 --- a/wikipedia/src/main/java/org/wikipedia/page/ReferenceDialog.java +++ b/wikipedia/src/main/java/org/wikipedia/page/ReferenceDialog.java @@ -1,45 +1,22 @@ package org.wikipedia.page; -import android.app.Dialog; +import org.wikipedia.R; import android.content.Context; -import android.os.Build; import android.text.Html; import android.text.Spanned; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; import android.widget.TextView; -import org.wikipedia.R; -/** Display the currently clicked reference */ -public class ReferenceDialog extends Dialog { +/** + * A dialog that displays the currently clicked reference. + */ +public class ReferenceDialog extends BottomDialog { private final LinkHandler linkHandler; private final TextView referenceText; public ReferenceDialog(Context context, LinkHandler linkHandler) { - super(context); + super(context, R.layout.dialog_reference); this.linkHandler = linkHandler; - - LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View dlgLayout = inflater.inflate(R.layout.dialog_reference, null); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - getWindow().setDimAmount(0.0f); - } - requestWindowFeature(Window.FEATURE_NO_TITLE); - setContentView(dlgLayout); - - getWindow().setBackgroundDrawable(null); - WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); - lp.copyFrom(getWindow().getAttributes()); - lp.width = WindowManager.LayoutParams.MATCH_PARENT; - lp.height = WindowManager.LayoutParams.WRAP_CONTENT; - lp.gravity = Gravity.BOTTOM; - getWindow().setAttributes(lp); - - referenceText = (TextView) dlgLayout.findViewById(R.id.reference_text); + referenceText = (TextView) getDialogLayout().findViewById(R.id.reference_text); } void updateReference(String refHtml) { diff --git a/www/js/actions.js b/www/js/actions.js index cb1a786..1ba8269 100644 --- a/www/js/actions.js +++ b/www/js/actions.js @@ -65,30 +65,6 @@ curNode = curNode.parentNode; } - function collectIssues( sourceNode ) { - var res = []; - var issues = sourceNode.parentNode.querySelectorAll( 'table.ambox' ); - var i = 0, - len = issues.length; - for (; i < len; i++) { - // .ambox- is used e.g. on eswiki - res.push( issues[i].querySelector( '.mbox-text, .ambox-text' ).innerHTML ); - } - - bridge.sendMessage( 'issuesClicked', { "issues": res } ); - } - - function handleDisambig( sourceNode ) { - var res = []; - var hatnotes = sourceNode.parentNode.querySelectorAll( 'div.hatnote' ); - var i = 0, - len = hatnotes.length; - for (; i < len; i++) { - res.push( hatnotes[i].innerHTML ); - } - bridge.sendMessage( 'disambigClicked', { "hatnotes": res } ); - } - if (sourceNode) { if ( sourceNode.hasAttribute( "data-action" ) ) { var action = sourceNode.getAttribute( "data-action" ); @@ -100,10 +76,10 @@ var href = sourceNode.getAttribute( "href" ); if ( href[0] === "#" ) { var targetId = href.slice(1); - if ("issues" === targetId) { - collectIssues(sourceNode); - } else if ("disambig" === targetId) { - handleDisambig(sourceNode); + if ( "issues" === targetId ) { + issuesClicked( sourceNode ); + } else if ( "disambig" === targetId ) { + disambigClicked( sourceNode ); } else { handleReference( targetId, ancestorContainsClass( sourceNode, "mw-cite-backlink" ) ); } @@ -115,4 +91,39 @@ } }; +function issuesClicked( sourceNode ) { + var issues = collectIssues( sourceNode.parentNode ); + var disambig = collectDisambig( document ); // the other node is not a child of sourceNode + bridge.sendMessage( 'issuesClicked', { "hatnotes": disambig, "issues": issues } ); +} + +function disambigClicked( sourceNode ) { + var disambig = collectDisambig( sourceNode.parentNode ); + var issues = collectIssues( document ); // the other node is not a child of sourceNode + bridge.sendMessage( 'disambigClicked', { "hatnotes": disambig, "issues": issues } ); +} + +function collectDisambig( sourceNode ) { + var res = []; + var hatnotes = sourceNode.querySelectorAll( 'div.hatnote' ); + var i = 0, + len = hatnotes.length; + for (; i < len; i++) { + res.push( hatnotes[i].innerHTML ); + } + return res; +} + +function collectIssues( sourceNode ) { + var res = []; + var issues = sourceNode.querySelectorAll( 'table.ambox' ); + var i = 0, + len = issues.length; + for (; i < len; i++) { + // .ambox- is used e.g. on eswiki + res.push( issues[i].querySelector( '.mbox-text, .ambox-text' ).innerHTML ); + } + return res; +} + module.exports = new ActionsHandler(); -- To view, visit https://gerrit.wikimedia.org/r/171512 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If216e2b73cfc94184fca64c384575a5d1d903add Gerrit-PatchSet: 1 Gerrit-Project: apps/android/wikipedia Gerrit-Branch: master Gerrit-Owner: BearND <bsitzm...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits