Add item readtime on item list activity and item activity

This commit is contained in:
Shinokuni 2019-02-08 18:22:42 +00:00
parent cc88fc8334
commit a1d4112322
13 changed files with 197 additions and 24 deletions

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WizardSettings">
<option name="children">
<map>
<entry key="vectorWizard">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="vectorAssetStep">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="clipartAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="url" value="jar:file:/Applications/Android%20Studio.app/Contents/plugins/android/lib/android.jar!/images/material_design_icons/device/ic_access_time_black_24dp.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="outputName" value="ic_read_time" />
<entry key="sourceFile" value="$USER_HOME$" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</component>
</project>

View File

@ -14,6 +14,7 @@ import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.readrops.app.database.ItemWithFeed;
@ -37,6 +38,8 @@ public class ItemActivity extends AppCompatActivity {
private TextView author;
private TextView readTime;
private RelativeLayout readTimeLayout;
private CollapsingToolbarLayout toolbarLayout;
private ReadropsWebView webView;
@ -71,6 +74,7 @@ public class ItemActivity extends AppCompatActivity {
title = findViewById(R.id.activity_item_title);
author = findViewById(R.id.activity_item_author);
readTime = findViewById(R.id.activity_item_readtime);
readTimeLayout = findViewById(R.id.activity_item_readtime_layout);
viewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()).create(ItemViewModel.class);
viewModel.getItemById(itemId).observe(this, this::bindUI);
@ -87,6 +91,18 @@ public class ItemActivity extends AppCompatActivity {
author.setVisibility(View.VISIBLE);
}
if (item.getReadTime() > 0) {
int minutes = (int)Math.round(item.getReadTime());
if (minutes < 1)
readTime.setText(getResources().getString(R.string.read_time_lower_than_1));
else if (minutes > 1)
readTime.setText(getResources().getString(R.string.read_time, String.valueOf(minutes)));
else
readTime.setText(getResources().getString(R.string.read_time_one_minute));
readTimeLayout.setVisibility(View.VISIBLE);
}
webView.setItem(itemWithFeed);
}
}

View File

@ -203,18 +203,22 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
for (Item dbItem : items) {
if (!Boolean.valueOf(database.itemDao().guidExist(dbItem.getGuid()))) {
if (dbItem.getDescription() != null) {
dbItem.setCleanDescription(Jsoup.parse(dbItem.getDescription()).text());
if (dbItem.getImageLink() == null) {
String imageUrl = HtmlParser.getDescImageLink(dbItem.getDescription(), feed.getSiteUrl());
if (imageUrl != null) {
dbItem.setImageLink(imageUrl);
if (dbItem.getContent() != null) // removing cover image in content if found in description
if (dbItem.getContent() != null) {
// removing cover image in content if found in description
dbItem.setContent(HtmlParser.deleteCoverImage(dbItem.getContent()));
}
}
dbItem.setCleanDescription(Jsoup.parse(dbItem.getDescription()).text());
dbItem.setReadTime(Utils.readTimeFromString(dbItem.getContent()));
} else
dbItem.setReadTime(Utils.readTimeFromString(dbItem.getCleanDescription()));
}
}
}
database.itemDao().insert(dbItem);

View File

@ -90,6 +90,7 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
viewModel.getItemsWithFeed().observe(this, (itemWithFeeds -> {
newItems = itemWithFeeds;
if (!refreshLayout.isRefreshing())
adapter.submitList(newItems);
}));

View File

@ -1,6 +1,7 @@
package com.readrops.app;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -104,6 +105,15 @@ public class MainItemListAdapter extends ListAdapter<ItemWithFeed, MainItemListA
if (itemWithFeed.getColor() != 0)
viewHolder.feedName.setTextColor(itemWithFeed.getColor());
Resources resources = viewHolder.itemView.getResources();
int minutes = (int)Math.round(itemWithFeed.getItem().getReadTime());
if (minutes < 1)
viewHolder.itemReadTime.setText(resources.getString(R.string.read_time_lower_than_1));
else if (minutes > 1)
viewHolder.itemReadTime.setText(resources.getString(R.string.read_time, String.valueOf(minutes)));
else
viewHolder.itemReadTime.setText(resources.getString(R.string.read_time_one_minute));
}
@Override
@ -149,6 +159,7 @@ public class MainItemListAdapter extends ListAdapter<ItemWithFeed, MainItemListA
private TextView itemDescription;
private ImageView feedIcon;
private ImageView itemImage;
private TextView itemReadTime;
ItemViewHolder(@NonNull View itemView) {
super(itemView);
@ -166,6 +177,7 @@ public class MainItemListAdapter extends ListAdapter<ItemWithFeed, MainItemListA
itemDescription = itemView.findViewById(R.id.item_description);
feedIcon = itemView.findViewById(R.id.item_feed_icon);
itemImage = itemView.findViewById(R.id.item_image);
itemReadTime = itemView.findViewById(R.id.item_readtime);
}
private void bind(ItemWithFeed itemWithFeed) {
@ -180,6 +192,8 @@ public class MainItemListAdapter extends ListAdapter<ItemWithFeed, MainItemListA
itemDescription.setText(item.getCleanDescription());
} else
itemDescription.setVisibility(View.GONE);
}
public ImageView getItemImage() {

View File

@ -20,7 +20,7 @@ public interface ItemDao {
@Query("Select * from Item Order By pub_date DESC")
LiveData<List<Item>> getAll();
@Query("Select Item.id, title, clean_description, image_link, pub_date, name, color, icon_url from Item Inner Join Feed on Item.feed_id = Feed.id Order By Item.id DESC")
@Query("Select Item.id, title, clean_description, image_link, pub_date, name, color, icon_url, read_time from Item Inner Join Feed on Item.feed_id = Feed.id Order By Item.id DESC")
LiveData<List<ItemWithFeed>> getAllItemWithFeeds();
@Query("Select case When :guid In (Select guid from Item) Then 'true' else 'false' end")
@ -32,6 +32,6 @@ public interface ItemDao {
@Insert
void insertAll(List<Item> items);
@Query("Select title, Item.description, content, pub_date, author, 0 as color, name from Item Inner Join Feed on Item.feed_id = Feed.id And Item.id = :id")
@Query("Select title, Item.description, content, pub_date, author, 0 as color, read_time, name from Item Inner Join Feed on Item.feed_id = Feed.id And Item.id = :id")
LiveData<ItemWithFeed> getItemById(int id);
}

View File

@ -47,6 +47,9 @@ public class Item {
@ColumnInfo(index = true)
private String guid;
@ColumnInfo(name = "read_time")
private double readTime;
public int getId() {
return id;
}
@ -139,6 +142,14 @@ public class Item {
return getImageLink() != null;
}
public double getReadTime() {
return readTime;
}
public void setReadTime(double readTime) {
this.readTime = readTime;
}
public String getText() {
if (content != null)
return content;

View File

@ -23,6 +23,8 @@ public final class Utils {
public static final String HTTPS_PREFIX = "https://";
public static final int AVERAGE_WORDS_PER_MINUTE = 250;
public static void displayErrorInMainThread(Context context, String message) {
Toast toast = Toast.makeText(context, message, Toast.LENGTH_LONG);
@ -55,4 +57,11 @@ public final class Utils {
return displayMetrics.widthPixels;
}
public static double readTimeFromString(String value) {
int nbWords = value.split("\\s+").length;
double minutes = (double)nbWords / AVERAGE_WORDS_PER_MINUTE;
return minutes;
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
</vector>

View File

@ -58,6 +58,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline"
android:layout_marginBottom="8dp"
tools:text="This is a title" />
<TextView
@ -66,20 +67,42 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/activity_item_title"
android:layout_marginTop="8dp"
android:visibility="gone"
tools:text="By Santa Klaus" />
tools:text="By Santa Klaus"
tools:visibility="visible"/>
<RelativeLayout
android:id="@+id/activity_item_readtime_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_below="@id/activity_item_title"
tools:visibility="visible">
<ImageView
android:id="@+id/activity_item_readtime_icon"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_toStartOf="@id/activity_item_readtime"
android:layout_alignBottom="@id/activity_item_readtime_icon"
android:layout_centerVertical="true"
android:src="@drawable/ic_read_time" />
<TextView
android:id="@+id/activity_item_readtime"
style="@style/Base.TextAppearance.AppCompat.Body1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/activity_item_title"
android:layout_alignParentEnd="true"
android:layout_marginTop="8dp"
android:visibility="gone"
tools:text="3 minutes reading" />
android:layout_alignParentRight="true"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:layout_centerHorizontal="true"
android:textAlignment="viewStart"
tools:text="3 minutes read" />
</RelativeLayout>
</RelativeLayout>
<com.readrops.app.utils.ReadropsWebView

View File

@ -64,6 +64,13 @@
android:layout_below="@id/layout_start"
android:layout_marginTop="6dp">
<RelativeLayout
android:id="@+id/item_feed_title_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_toStartOf="@id/item_readtime">
<ImageView
android:id="@+id/item_feed_icon"
android:layout_width="20dp"
@ -76,17 +83,43 @@
android:id="@+id/item_feed_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:layout_alignParentEnd="true"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp"
android:layout_toRightOf="@id/item_feed_icon"
android:ellipsize="end"
android:maxLines="1"
tools:text="Numerama" />
</RelativeLayout>
<TextView
android:id="@+id/item_readtime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:layout_toStartOf="@id/item_interpoint"
tools:text="3 mins read" />
<TextView
android:id="@+id/item_interpoint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp"
android:layout_toStartOf="@id/item_date"
android:text="@string/interpoint"
android:textStyle="bold" />
<TextView
android:id="@+id/item_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp"
tools:text="January 10 2019" />
</RelativeLayout>

View File

@ -17,5 +17,8 @@
<string name="add_feed_connexion_error">Erreur de connexion au site</string>
<string name="add_feed_unknownhost_error">Site inconnu</string>
<string name="by_author">par %1$s</string>
<string name="read_time">%1$s minutes</string>
<string name="read_time_lower_than_1">Moins d\'une minute</string>
<string name="read_time_one_minute">1 minute</string>
</resources>

View File

@ -18,4 +18,8 @@
<string name="add_feed_connexion_error">Connection error</string>
<string name="add_feed_unknownhost_error">Unknown host</string>
<string name="by_author">by %1$s</string>
<string name="read_time">%1$s mins read</string>
<string name="read_time_lower_than_1">Less than a minute</string>
<string name="read_time_one_minute">1 min read</string>
<string name="interpoint" translatable="false">·</string>
</resources>