Bug 889351 - Show more details in reading list row. r=lucasr
--- a/mobile/android/base/home/ReadingListRow.java
+++ b/mobile/android/base/home/ReadingListRow.java
@@ -3,40 +3,85 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
import org.mozilla.gecko.home.TwoLinePageRow;
import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class ReadingListRow extends LinearLayout {
+
+ private final Resources resources;
-public class ReadingListRow extends TwoLinePageRow {
+ private final TextView title;
+ private final TextView excerpt;
+ private final TextView readTime;
+
+ // Average reading speed in words per minute.
+ private static final int AVERAGE_READING_SPEED = 250;
+
+ // Length of average word.
+ private static final float AVERAGE_WORD_LENGTH = 5.1f;
+
public ReadingListRow(Context context) {
this(context, null);
}
public ReadingListRow(Context context, AttributeSet attrs) {
super(context, attrs);
+
+ LayoutInflater.from(context).inflate(R.layout.reading_list_row_view, this);
+
+ setOrientation(LinearLayout.VERTICAL);
+
+ resources = context.getResources();
+
+ title = (TextView) findViewById(R.id.title);
+ excerpt = (TextView) findViewById(R.id.excerpt);
+ readTime = (TextView) findViewById(R.id.read_time);
}
- @Override
- protected void updateDisplayedUrl() {
- String pageUrl = getUrl();
+ public void updateFromCursor(Cursor cursor) {
+ if (cursor == null) {
+ return;
+ }
- boolean isPrivate = Tabs.getInstance().getSelectedTab().isPrivate();
- Tab tab = Tabs.getInstance().getFirstReaderTabForUrl(pageUrl, isPrivate);
+ final int titleIndex = cursor.getColumnIndexOrThrow(ReadingListItems.TITLE);
+ title.setText(cursor.getString(titleIndex));
- if (tab != null) {
- setUrl(R.string.switch_to_tab);
- setSwitchToTabIcon(R.drawable.ic_url_bar_tab);
+ final int excerptIndex = cursor.getColumnIndexOrThrow(ReadingListItems.EXCERPT);
+ excerpt.setText(cursor.getString(excerptIndex));
+
+ final int lengthIndex = cursor.getColumnIndexOrThrow(ReadingListItems.LENGTH);
+ final int minutes = getEstimatedReadTime(cursor.getInt(lengthIndex));
+ if (minutes <= 60) {
+ readTime.setText(resources.getString(R.string.reading_list_time_minutes, minutes));
} else {
- setUrl(pageUrl);
- setSwitchToTabIcon(NO_ICON);
+ readTime.setText(resources.getString(R.string.reading_list_time_over_an_hour));
}
}
+ /**
+ * Calculates the estimated time to read an article based on its length.
+ *
+ * @param length of the article (in characters)
+ * @return estimated time to read the article (in minutes)
+ */
+ private static int getEstimatedReadTime(int length) {
+ final int minutes = (int) Math.ceil((length / AVERAGE_WORD_LENGTH) / AVERAGE_READING_SPEED);
+
+ // Minimum of one minute.
+ return Math.max(minutes, 1);
+ }
}
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -359,16 +359,22 @@ size. -->
<!ENTITY site_settings_cancel "Cancel">
<!ENTITY site_settings_clear "Clear">
<!ENTITY site_settings_no_settings "There are no settings to clear.">
<!ENTITY reading_list_added "Page added to your Reading List">
<!ENTITY reading_list_failed "Failed to add page to your Reading List">
<!ENTITY reading_list_duplicate "Page already in your Reading List">
+<!-- Localization note (reading_list_time_minutes) : This string is used in the "Reading List"
+ panel on the home page to give the user an estimate of how many minutes it will take to
+ read an article. The word "minute" should be abbreviated if possible. -->
+<!ENTITY reading_list_time_minutes "&formatD;min">
+<!ENTITY reading_list_time_over_an_hour "Over an hour">
+
<!-- Localization note : These strings are used as alternate text for accessibility.
They are not visible in the UI. -->
<!ENTITY page_action_dropmarker_description "Additional Actions">
<!ENTITY masterpassword_create_title "Create Master Password">
<!ENTITY masterpassword_remove_title "Remove Master Password">
<!ENTITY masterpassword_password "Password">
<!ENTITY masterpassword_confirm "Confirm password">
--- a/mobile/android/base/resources/layout/reading_list_item_row.xml
+++ b/mobile/android/base/resources/layout/reading_list_item_row.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<org.mozilla.gecko.home.ReadingListRow xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.BookmarkItemView"
android:layout_width="match_parent"
- android:layout_height="@dimen/page_row_height"
- android:minHeight="@dimen/page_row_height"/>
+ android:layout_height="wrap_content"
+ android:padding="10dp"/>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/reading_list_row_view.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ style="@style/Widget.ReadingListRow.Title" />
+
+ <TextView
+ android:id="@+id/read_time"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/Widget.ReadingListRow.ReadTime" />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/excerpt"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ style="@style/Widget.ReadingListRow.Description" />
+
+</merge>
--- a/mobile/android/base/resources/values-v16/styles.xml
+++ b/mobile/android/base/resources/values-v16/styles.xml
@@ -12,16 +12,22 @@
<style name="TextAppearance.Widget.Home.ItemTitle" parent="TextAppearance.Medium">
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.Widget.Home.PageTitle" parent="TextAppearance.Medium">
<item name="android:fontFamily">sans-serif-light</item>
</style>
+ <style name="Widget.ReadingListRow.ReadTime">
+ <item name="android:textStyle">italic</item>
+ <item name="android:textColor">#FF9400</item>
+ <item name="android:fontFamily">sans-serif-condensed</item>
+ </style>
+
<style name="OnboardStartTextAppearance.Subtext">
<item name="android:textSize">18sp</item>
<item name="android:fontFamily">sans-serif-light</item>
</style>
<style name="TextAppearance.UrlBar.Title" parent="TextAppearance.Small">
<item name="android:textSize">15sp</item>
<item name="android:fontFamily">sans-serif-light</item>
</style>
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -122,16 +122,35 @@
<style name="Widget.TwoLinePageRow.Url">
<item name="android:textAppearance">@style/TextAppearance.Widget.Home.ItemDescription</item>
<item name="android:includeFontPadding">false</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">middle</item>
</style>
+ <style name="Widget.ReadingListRow" />
+
+ <style name="Widget.ReadingListRow.Title">
+ <item name="android:textAppearance">@style/TextAppearance.Widget.Home.ItemTitle</item>
+ <item name="android:maxLines">2</item>
+ <item name="android:ellipsize">end</item>
+ </style>
+
+ <style name="Widget.ReadingListRow.Description">
+ <item name="android:textAppearance">@style/TextAppearance.Widget.Home.ItemDescription</item>
+ <item name="android:maxLines">4</item>
+ <item name="android:ellipsize">end</item>
+ </style>
+
+ <style name="Widget.ReadingListRow.ReadTime">
+ <item name="android:textStyle">italic</item>
+ <item name="android:textColor">@color/text_color_highlight</item>
+ </style>
+
<style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
<item name="android:singleLine">true</item>
<item name="android:ellipsize">none</item>
<item name="android:paddingLeft">10dip</item>
<item name="android:drawablePadding">10dip</item>
<item name="android:drawableLeft">@drawable/bookmark_folder</item>
</style>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -293,16 +293,18 @@
<string name="site_settings_title">&site_settings_title3;</string>
<string name="site_settings_cancel">&site_settings_cancel;</string>
<string name="site_settings_clear">&site_settings_clear;</string>
<string name="site_settings_no_settings">&site_settings_no_settings;</string>
<string name="reading_list_added">&reading_list_added;</string>
<string name="reading_list_failed">&reading_list_failed;</string>
<string name="reading_list_duplicate">&reading_list_duplicate;</string>
+ <string name="reading_list_time_minutes">&reading_list_time_minutes;</string>
+ <string name="reading_list_time_over_an_hour">&reading_list_time_over_an_hour;</string>
<string name="page_action_dropmarker_description">&page_action_dropmarker_description;</string>
<string name="contextmenu_open_new_tab">&contextmenu_open_new_tab;</string>
<string name="contextmenu_open_private_tab">&contextmenu_open_private_tab;</string>
<string name="contextmenu_remove">&contextmenu_remove;</string>
<string name="contextmenu_add_to_launcher">&contextmenu_add_to_launcher;</string>
<string name="contextmenu_share">&contextmenu_share;</string>