mirror of
https://github.com/viq/NewsBlur.git
synced 2025-11-01 09:09:16 +00:00
Added comment DB structure. Added comment and shared-icons for reading items. Added refresh of feed counts on app start. Added ability to manually refresh feed counts (currently un-throttled.) Modified Imageloader to use UIDs as the storage mechanism (rather than urls) to reduce network calls when we have the userId but not their photoUrl.
This commit is contained in:
parent
c4714abf57
commit
6536bdf41e
21 changed files with 438 additions and 187 deletions
|
|
@ -1,12 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.newsblur.view.NonfocusScrollview xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res/com.newsblur"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white">
|
||||
android:background="@color/white" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="9dp" >
|
||||
|
||||
|
|
@ -54,7 +55,6 @@
|
|||
android:textSize="11dp"
|
||||
android:textStyle="italic" />
|
||||
|
||||
|
||||
<android.support.v7.widget.GridLayout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/reading_item_tags"
|
||||
|
|
@ -78,8 +78,51 @@
|
|||
<WebView
|
||||
android:id="@+id/reading_webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/reading_shared_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" >
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/reading_share_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/list_background"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="10dp" >
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="@string/reading_sharedby"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<android.support.v7.widget.GridLayout
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/reading_social_shareimages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:columnCount="8"
|
||||
app:useDefaultMargins="true" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/reading_comment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/reading_share_bar"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</com.newsblur.view.NonfocusScrollview>
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/row_item_sidebar"
|
||||
android:maxLines="2"
|
||||
android:textColor="@color/darkgray"
|
||||
android:textSize="18dp" />
|
||||
|
||||
|
|
@ -38,8 +39,8 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/row_item_title"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_toRightOf="@id/row_item_sidebar"
|
||||
android:layout_toLeftOf="@id/row_item_date"
|
||||
android:layout_toRightOf="@id/row_item_sidebar"
|
||||
android:textColor="@color/lightgray"
|
||||
android:textSize="12dp" />
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@
|
|||
<string name="description_row_folder_icon">folder icon</string>
|
||||
<string name="description_activity_icon">An icon illustrating the user\'s activity</string>
|
||||
<string name="description_follow_button">Follow or unfollow a user</string>
|
||||
|
||||
<string name="description_comment_user">Comment user image</string>
|
||||
|
||||
<string name="reading_sharedby">SHARED BY: </string>
|
||||
|
||||
<string name="share" formatted="false">\"%s\" - %s (via Newsblur)</string>
|
||||
|
||||
<string name="profile">Profile</string>
|
||||
|
|
@ -55,5 +58,4 @@
|
|||
<string name="menu_original">View original</string>
|
||||
<string name="menu_share">Share</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
@ -1,38 +1,36 @@
|
|||
package com.newsblur.activity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.util.Log;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import com.actionbarsherlock.view.Window;
|
||||
import com.newsblur.R;
|
||||
import com.newsblur.database.FeedProvider;
|
||||
import com.newsblur.domain.Feed;
|
||||
import com.newsblur.domain.Story;
|
||||
import com.newsblur.fragment.ItemListFragment;
|
||||
import com.newsblur.service.DetachableResultReceiver;
|
||||
import com.newsblur.service.DetachableResultReceiver.Receiver;
|
||||
import com.newsblur.fragment.SyncUpdateFragment;
|
||||
import com.newsblur.service.SyncService;
|
||||
|
||||
public class ItemsList extends SherlockFragmentActivity {
|
||||
public class ItemsList extends SherlockFragmentActivity implements SyncUpdateFragment.SyncUpdateFragmentInterface {
|
||||
|
||||
public static final String EXTRA_FEED = "feedId";
|
||||
private ItemListFragment itemListFragment;
|
||||
private FragmentManager fragmentManager;
|
||||
private final String FRAGMENT_TAG = "itemListFragment";
|
||||
private SyncReadingUpdaterFragment syncFragment;
|
||||
private SyncUpdateFragment syncFragment;
|
||||
private String feedId;
|
||||
private String TAG = "ItemsList";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle bundle) {
|
||||
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.activity_itemslist);
|
||||
fragmentManager = getSupportFragmentManager();
|
||||
|
|
@ -54,20 +52,16 @@ public class ItemsList extends SherlockFragmentActivity {
|
|||
listTransaction.commit();
|
||||
}
|
||||
|
||||
syncFragment = (SyncReadingUpdaterFragment) fragmentManager.findFragmentByTag(SyncReadingUpdaterFragment.TAG);
|
||||
syncFragment = (SyncUpdateFragment) fragmentManager.findFragmentByTag(SyncUpdateFragment.TAG);
|
||||
if (syncFragment == null) {
|
||||
syncFragment = new SyncReadingUpdaterFragment();
|
||||
fragmentManager.beginTransaction().add(syncFragment, SyncReadingUpdaterFragment.TAG).commit();
|
||||
syncFragment = new SyncUpdateFragment();
|
||||
fragmentManager.beginTransaction().add(syncFragment, SyncUpdateFragment.TAG).commit();
|
||||
triggerRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void redrawUI() {
|
||||
Log.d(TAG , "Redrawing UI");
|
||||
itemListFragment.updated();
|
||||
}
|
||||
|
||||
public void triggerRefresh() {
|
||||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_FEED_UPDATE);
|
||||
|
|
@ -75,47 +69,6 @@ public class ItemsList extends SherlockFragmentActivity {
|
|||
startService(intent);
|
||||
}
|
||||
|
||||
public static class SyncReadingUpdaterFragment extends Fragment implements Receiver {
|
||||
public static final String TAG = "SyncReadingFragment";
|
||||
private DetachableResultReceiver receiver;
|
||||
|
||||
public SyncReadingUpdaterFragment() {
|
||||
receiver = new DetachableResultReceiver(new Handler());
|
||||
receiver.setReceiver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
Log.d(TAG, "Creating syncfragment");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
Log.d(TAG, "Attached");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiverResult(int resultCode, Bundle resultData) {
|
||||
switch (resultCode) {
|
||||
case SyncService.STATUS_FINISHED:
|
||||
Log.d(TAG, "Synchronisation finished.");
|
||||
if (getActivity() != null) {
|
||||
((ItemsList) getActivity()).redrawUI();
|
||||
}
|
||||
break;
|
||||
case SyncService.STATUS_RUNNING:
|
||||
Log.d(TAG, "Synchronisation running.");
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unrecognised response attempting to get reading data");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
|
@ -126,4 +79,18 @@ public class ItemsList extends SherlockFragmentActivity {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAfterSync() {
|
||||
Log.d(TAG , "Redrawing UI");
|
||||
itemListFragment.updated();
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSyncStatus(boolean syncRunning) {
|
||||
if (syncRunning) {
|
||||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -10,41 +10,70 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
|
|||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import com.actionbarsherlock.view.Window;
|
||||
import com.newsblur.R;
|
||||
import com.newsblur.fragment.FolderFeedListFragment;
|
||||
import com.newsblur.fragment.ItemListFragment;
|
||||
import com.newsblur.fragment.SyncUpdateFragment;
|
||||
import com.newsblur.network.domain.FeedFolderResponse;
|
||||
import com.newsblur.service.SyncService;
|
||||
import com.newsblur.view.StateToggleButton.StateChangedListener;
|
||||
|
||||
public class Main extends SherlockFragmentActivity implements StateChangedListener {
|
||||
|
||||
public class Main extends SherlockFragmentActivity implements StateChangedListener, SyncUpdateFragment.SyncUpdateFragmentInterface {
|
||||
|
||||
private ActionBar actionBar;
|
||||
private FolderFeedListFragment folderFeedList;
|
||||
private FragmentManager fragmentManager;
|
||||
private SyncUpdateFragment syncFragment;
|
||||
private static final String TAG = "MainActivity";
|
||||
private Menu menu;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
setupActionBar();
|
||||
|
||||
fragmentManager = getSupportFragmentManager();
|
||||
folderFeedList = (FolderFeedListFragment) fragmentManager.findFragmentByTag("folderFeedListFragment");
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
setupActionBar();
|
||||
|
||||
fragmentManager = getSupportFragmentManager();
|
||||
folderFeedList = (FolderFeedListFragment) fragmentManager.findFragmentByTag("folderFeedListFragment");
|
||||
|
||||
syncFragment = (SyncUpdateFragment) fragmentManager.findFragmentByTag(SyncUpdateFragment.TAG);
|
||||
if (syncFragment == null) {
|
||||
syncFragment = new SyncUpdateFragment();
|
||||
fragmentManager.beginTransaction().add(syncFragment, SyncUpdateFragment.TAG).commit();
|
||||
triggerRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerRefresh() {
|
||||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
if (menu != null) {
|
||||
menu.findItem(R.id.menu_refresh).setEnabled(false);
|
||||
}
|
||||
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_REFRESH_COUNTS);
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
private void setupActionBar() {
|
||||
actionBar = getSupportActionBar();
|
||||
actionBar = getSupportActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
MenuInflater inflater = getSupportMenuInflater();
|
||||
inflater.inflate(R.menu.main, menu);
|
||||
return true;
|
||||
inflater.inflate(R.menu.main, menu);
|
||||
this.menu = menu;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
|
@ -52,6 +81,9 @@ public class Main extends SherlockFragmentActivity implements StateChangedListen
|
|||
Intent profileIntent = new Intent(this, Profile.class);
|
||||
startActivity(profileIntent);
|
||||
return true;
|
||||
case R.id.menu_refresh:
|
||||
triggerRefresh();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
|
@ -59,8 +91,24 @@ public class Main extends SherlockFragmentActivity implements StateChangedListen
|
|||
@Override
|
||||
public void changedState(int state) {
|
||||
Log.d(TAG, "State changed");
|
||||
|
||||
folderFeedList.changeState(state);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateAfterSync() {
|
||||
Log.d(TAG, "Finished feed count refresh.");
|
||||
folderFeedList.hasUpdated();
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
menu.findItem(R.id.menu_refresh).setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSyncStatus(boolean syncRunning) {
|
||||
if (syncRunning) {
|
||||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
if (menu != null) {
|
||||
menu.findItem(R.id.menu_refresh).setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package com.newsblur.activity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
|
|
@ -8,8 +7,6 @@ import android.graphics.Color;
|
|||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.text.TextUtils;
|
||||
|
|
@ -20,15 +17,11 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
|
|||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import com.actionbarsherlock.view.Window;
|
||||
import com.newsblur.R;
|
||||
import com.newsblur.database.FeedProvider;
|
||||
import com.newsblur.database.ReadingAdapter;
|
||||
import com.newsblur.domain.Feed;
|
||||
import com.newsblur.domain.Story;
|
||||
import com.newsblur.service.DetachableResultReceiver;
|
||||
import com.newsblur.service.DetachableResultReceiver.Receiver;
|
||||
import com.newsblur.service.SyncService;
|
||||
import com.newsblur.util.UIUtils;
|
||||
|
||||
public class Reading extends SherlockFragmentActivity {
|
||||
|
|
@ -47,9 +40,6 @@ public class Reading extends SherlockFragmentActivity {
|
|||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceBundle) {
|
||||
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
|
||||
super.onCreate(savedInstanceBundle);
|
||||
setContentView(R.layout.activity_reading);
|
||||
|
||||
|
|
@ -58,12 +48,12 @@ public class Reading extends SherlockFragmentActivity {
|
|||
passedPosition = getIntent().getIntExtra(EXTRA_POSITION, 0);
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
contentResolver = getContentResolver();
|
||||
|
||||
contentResolver = getContentResolver();
|
||||
Uri storiesURI = FeedProvider.STORIES_URI.buildUpon().appendPath(feedId).build();
|
||||
Cursor stories = contentResolver.query(storiesURI, null, null, null, null);
|
||||
readingAdapter = new ReadingAdapter(fragmentManager, this, feedId, stories);
|
||||
|
||||
|
||||
final Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(feedId).build();
|
||||
feed = Feed.fromCursor(contentResolver.query(feedUri, null, null, null, null));
|
||||
setTitle(feed.title);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.newsblur.database;
|
|||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public class BlurDatabase extends SQLiteOpenHelper {
|
||||
|
|
@ -12,17 +13,17 @@ public class BlurDatabase extends SQLiteOpenHelper {
|
|||
private final static String TAG = "DatabaseHelper";
|
||||
private final static String DB_NAME = "blur.db";
|
||||
private final static int VERSION = 1;
|
||||
|
||||
|
||||
public BlurDatabase(Context context) {
|
||||
super(context, DB_NAME, null, VERSION);
|
||||
Log.d(TAG, "Initiating database");
|
||||
}
|
||||
|
||||
|
||||
private final String FOLDER_SQL = "CREATE TABLE " + DatabaseConstants.FOLDER_TABLE + " (" +
|
||||
DatabaseConstants.FOLDER_ID + INTEGER + ", " +
|
||||
DatabaseConstants.FOLDER_NAME + TEXT + " PRIMARY KEY " +
|
||||
")";
|
||||
|
||||
|
||||
private final String FEED_SQL = "CREATE TABLE " + DatabaseConstants.FEED_TABLE + " (" +
|
||||
DatabaseConstants.FEED_ID + INTEGER + " PRIMARY KEY, " +
|
||||
DatabaseConstants.FEED_ACTIVE + TEXT + ", " +
|
||||
|
|
@ -39,7 +40,16 @@ public class BlurDatabase extends SQLiteOpenHelper {
|
|||
DatabaseConstants.FEED_TITLE + TEXT + ", " +
|
||||
DatabaseConstants.FEED_UPDATED_SECONDS +
|
||||
")";
|
||||
|
||||
|
||||
private final String COMMENT_SQL = "CREATE TABLE " + DatabaseConstants.COMMENT_TABLE + " (" +
|
||||
DatabaseConstants.COMMENT_DATE + TEXT + ", " +
|
||||
DatabaseConstants.COMMENT_SHAREDDATE + TEXT + ", " +
|
||||
DatabaseConstants.COMMENT_ID + TEXT + " PRIMARY KEY, " +
|
||||
DatabaseConstants.COMMENT_STORYID + TEXT + ", " +
|
||||
DatabaseConstants.COMMENT_TEXT + TEXT + ", " +
|
||||
DatabaseConstants.COMMENT_USERID + TEXT +
|
||||
")";
|
||||
|
||||
private final String STORY_SQL = "CREATE TABLE " + DatabaseConstants.STORY_TABLE + " (" +
|
||||
DatabaseConstants.STORY_AUTHORS + TEXT + ", " +
|
||||
DatabaseConstants.STORY_CONTENT + TEXT + ", " +
|
||||
|
|
@ -52,31 +62,33 @@ public class BlurDatabase extends SQLiteOpenHelper {
|
|||
DatabaseConstants.STORY_INTELLIGENCE_TITLE + INTEGER + ", " +
|
||||
DatabaseConstants.STORY_COMMENT_COUNT + INTEGER + ", " +
|
||||
DatabaseConstants.STORY_SHARE_COUNT + INTEGER + ", " +
|
||||
DatabaseConstants.STORY_SHARED_USER_IDS + TEXT + ", " +
|
||||
DatabaseConstants.STORY_TAGS + TEXT + ", " +
|
||||
DatabaseConstants.STORY_PERMALINK + TEXT + ", " +
|
||||
DatabaseConstants.STORY_READ + TEXT + ", " +
|
||||
DatabaseConstants.STORY_TITLE + TEXT +
|
||||
")";
|
||||
|
||||
|
||||
private final String CLASSIFIER_SQL = "CREATE TABLE " + DatabaseConstants.CLASSIFIER_TABLE + " (" +
|
||||
DatabaseConstants.CLASSIFIER_ID + TEXT + ", " +
|
||||
DatabaseConstants.CLASSIFIER_KEY + TEXT + ", " +
|
||||
DatabaseConstants.CLASSIFIER_TYPE + TEXT + ", " +
|
||||
DatabaseConstants.CLASSIFIER_VALUE + TEXT +
|
||||
")";
|
||||
|
||||
|
||||
private final String FEED_FOLDER_SQL = "CREATE TABLE " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + " (" +
|
||||
DatabaseConstants.FEED_FOLDER_FOLDER_NAME + TEXT + ", " +
|
||||
DatabaseConstants.FEED_FOLDER_FEED_ID + INTEGER + ", " +
|
||||
"PRIMARY KEY (" + DatabaseConstants.FEED_FOLDER_FOLDER_NAME + ", " + DatabaseConstants.FEED_FOLDER_FEED_ID + ") " +
|
||||
")";
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(FEED_SQL);
|
||||
db.execSQL(FOLDER_SQL);
|
||||
db.execSQL(STORY_SQL);
|
||||
db.execSQL(COMMENT_SQL);
|
||||
db.execSQL(CLASSIFIER_SQL);
|
||||
db.execSQL(FEED_FOLDER_SQL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ public class DatabaseConstants {
|
|||
public static final String FEED_FOLDER_FEED_ID = "feed_feed_id";
|
||||
public static final String FEED_FOLDER_FOLDER_NAME = "feed_folder_name";
|
||||
|
||||
public static final String COMMENT_TABLE = "comments";
|
||||
|
||||
public static final String CLASSIFIER_TABLE = "classifiers";
|
||||
public static final String CLASSIFIER_ID = BaseColumns._ID;
|
||||
public static final String CLASSIFIER_TYPE = "type";
|
||||
|
|
@ -55,19 +57,32 @@ public class DatabaseConstants {
|
|||
public static final String STORY_READ = "read";
|
||||
public static final String STORY_TAGS = "tags";
|
||||
public static final String STORY_FEED_ID = "feed_id";
|
||||
public static final String STORY_SHARED_USER_IDS = "shared_user_ids";
|
||||
|
||||
public static final String COMMENT_ID = BaseColumns._ID;
|
||||
public static final String COMMENT_STORYID = "comment_storyid";
|
||||
public static final String COMMENT_TEXT = "comment_text";
|
||||
public static final String COMMENT_DATE = "comment_date";
|
||||
public static final String COMMENT_SHAREDDATE = "comment_shareddate";
|
||||
public static final String COMMENT_USERID = "comment_userid";
|
||||
|
||||
// Aggregated columns
|
||||
public static final String SUM_POS = "sum_postive";
|
||||
public static final String SUM_NEUT = "sum_neutral";
|
||||
public static final String SUM_NEG = "sum_negative";
|
||||
|
||||
public static final String[] COMMENT_COLUMNS = {
|
||||
COMMENT_ID, COMMENT_STORYID, COMMENT_TEXT, COMMENT_USERID, COMMENT_DATE, COMMENT_SHAREDDATE
|
||||
};
|
||||
|
||||
public static final String[] FOLDER_COLUMNS = {
|
||||
FOLDER_TABLE + "." + FOLDER_ID, FOLDER_TABLE + "." + FOLDER_NAME, " SUM(" + FEED_POSITIVE_COUNT + ") AS " + SUM_POS, " SUM(" + FEED_NEUTRAL_COUNT + ") AS " + SUM_NEUT, " SUM(" + FEED_NEGATIVE_COUNT + ") AS " + SUM_NEG
|
||||
};
|
||||
|
||||
public static final String[] STORY_COLUMNS = {
|
||||
STORY_AUTHORS, STORY_COMMENT_COUNT, STORY_CONTENT, STORY_DATE, STORY_FEED_ID, STORY_ID, STORY_INTELLIGENCE_AUTHORS, STORY_INTELLIGENCE_FEED, STORY_INTELLIGENCE_TAGS, STORY_INTELLIGENCE_TITLE,
|
||||
STORY_PERMALINK, STORY_READ, STORY_SHARE_COUNT, STORY_TAGS, STORY_TITLE
|
||||
STORY_PERMALINK, STORY_READ, STORY_SHARE_COUNT, STORY_TAGS, STORY_TITLE, STORY_SHARED_USER_IDS
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ public class FeedProvider extends ContentProvider {
|
|||
public static final Uri NEWSBLUR_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION);
|
||||
public static final Uri FEEDS_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/feeds/");
|
||||
public static final Uri STORIES_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/stories/");
|
||||
public static final Uri COMMENTS_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/comments/");
|
||||
public static final Uri FEED_FOLDER_MAP_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/feedfoldermap/");
|
||||
public static final Uri FOLDERS_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/folders/");
|
||||
|
||||
|
|
@ -27,6 +28,7 @@ public class FeedProvider extends ContentProvider {
|
|||
|
||||
private static final int ALL_FEEDS = 0;
|
||||
private static final int FEED_STORIES = 1;
|
||||
private static final int STORY_COMMENTS = 7;
|
||||
private static final int ALL_FOLDERS = 2;
|
||||
private static final int SPECIFIC_FOLDER = 3;
|
||||
private static final int FEED_FOLDER_MAP = 4;
|
||||
|
|
@ -41,6 +43,7 @@ public class FeedProvider extends ContentProvider {
|
|||
uriMatcher.addURI(AUTHORITY, VERSION + "/feeds/", ALL_FEEDS);
|
||||
uriMatcher.addURI(AUTHORITY, VERSION + "/feeds/*/", INDIVIDUAL_FEED);
|
||||
uriMatcher.addURI(AUTHORITY, VERSION + "/stories/#/", FEED_STORIES);
|
||||
uriMatcher.addURI(AUTHORITY, VERSION + "/comments/", STORY_COMMENTS);
|
||||
uriMatcher.addURI(AUTHORITY, VERSION + "/feedfoldermap/", FEED_FOLDER_MAP);
|
||||
uriMatcher.addURI(AUTHORITY, VERSION + "/feedfoldermap/*/", SPECIFIC_FEED_FOLDER_MAP);
|
||||
uriMatcher.addURI(AUTHORITY, VERSION + "/folders/", ALL_FOLDERS);
|
||||
|
|
@ -90,6 +93,14 @@ public class FeedProvider extends ContentProvider {
|
|||
resultUri = uri.buildUpon().appendPath(values.getAsString(DatabaseConstants.FEED_ID)).build();
|
||||
break;
|
||||
|
||||
// Inserting a comment
|
||||
case STORY_COMMENTS:
|
||||
db.beginTransaction();
|
||||
db.insertWithOnConflict(DatabaseConstants.COMMENT_TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
break;
|
||||
|
||||
// Inserting a story
|
||||
case FEED_STORIES:
|
||||
db.beginTransaction();
|
||||
|
|
@ -97,51 +108,51 @@ public class FeedProvider extends ContentProvider {
|
|||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
break;
|
||||
|
||||
|
||||
case UriMatcher.NO_MATCH:
|
||||
Log.d(TAG, "No match found for URI: " + uri.toString());
|
||||
break;
|
||||
}
|
||||
db.close();
|
||||
return resultUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
Log.d(TAG, "Creating provider and database.");
|
||||
databaseHelper = new BlurDatabase(getContext().getApplicationContext());
|
||||
databaseHelper = new BlurDatabase(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||
final SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = null;
|
||||
switch (uriMatcher.match(uri)) {
|
||||
|
||||
// Query for all feeds (by default only return those that have unread items in them)
|
||||
case ALL_FEEDS:
|
||||
cursor = db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
|
||||
return db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
|
||||
" INNER JOIN " + DatabaseConstants.FEED_TABLE +
|
||||
" ON " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_ID + " = " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FEED_ID +
|
||||
" WHERE (" + DatabaseConstants.FEED_NEGATIVE_COUNT + " + " + DatabaseConstants.FEED_NEUTRAL_COUNT + " + " + DatabaseConstants.FEED_POSITIVE_COUNT + ") > 0 " +
|
||||
" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE", selectionArgs);
|
||||
break;
|
||||
|
||||
// Query for a specific feed
|
||||
// Query for a specific feed
|
||||
case INDIVIDUAL_FEED:
|
||||
cursor = db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_TABLE +
|
||||
" WHERE " + DatabaseConstants.FEED_ID + "= '" + uri.getLastPathSegment() + "'", selectionArgs);
|
||||
break;
|
||||
|
||||
// Querying for a stories from a feed
|
||||
return db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_TABLE +
|
||||
" WHERE " + DatabaseConstants.FEED_ID + "= '" + uri.getLastPathSegment() + "'", selectionArgs);
|
||||
|
||||
// Querying for a stories from a feed
|
||||
case FEED_STORIES:
|
||||
selection = DatabaseConstants.STORY_FEED_ID + " = ?";
|
||||
selectionArgs = new String[] { uri.getLastPathSegment() };
|
||||
cursor = db.query(DatabaseConstants.STORY_TABLE, DatabaseConstants.STORY_COLUMNS, selection, selectionArgs, null, null, null);
|
||||
break;
|
||||
return db.query(DatabaseConstants.STORY_TABLE, DatabaseConstants.STORY_COLUMNS, selection, selectionArgs, null, null, null);
|
||||
|
||||
// Query for feeds with no folder mapping
|
||||
// Querying for a stories from a feed
|
||||
case STORY_COMMENTS:
|
||||
selection = DatabaseConstants.COMMENT_STORYID + " = ?";
|
||||
return db.query(DatabaseConstants.COMMENT_TABLE, DatabaseConstants.COMMENT_COLUMNS, selection, selectionArgs, null, null, null);
|
||||
|
||||
// Query for feeds with no folder mapping
|
||||
case FEED_FOLDER_MAP:
|
||||
String nullFolderQuery = "SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_TABLE +
|
||||
" LEFT JOIN " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
|
||||
|
|
@ -155,10 +166,9 @@ public class FeedProvider extends ContentProvider {
|
|||
nullFolderBuilder.append(selectionArgs[0]);
|
||||
}
|
||||
nullFolderBuilder.append(" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE");
|
||||
cursor = db.rawQuery(nullFolderBuilder.toString(), null);
|
||||
break;
|
||||
return db.rawQuery(nullFolderBuilder.toString(), null);
|
||||
|
||||
// Querying for feeds for a given folder
|
||||
// Querying for feeds for a given folder
|
||||
case SPECIFIC_FEED_FOLDER_MAP:
|
||||
selection = DatabaseConstants.FOLDER_ID + " = ?";
|
||||
String[] folderArguments = new String[] { uri.getLastPathSegment() };
|
||||
|
|
@ -175,10 +185,9 @@ public class FeedProvider extends ContentProvider {
|
|||
builder.append(selectionArgs[0]);
|
||||
}
|
||||
builder.append(" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE");
|
||||
cursor = db.rawQuery(builder.toString(), folderArguments);
|
||||
break;
|
||||
return db.rawQuery(builder.toString(), folderArguments);
|
||||
|
||||
// Querying for all folders with unread items
|
||||
// Querying for all folders with unread items
|
||||
case ALL_FOLDERS:
|
||||
String folderQuery = "SELECT " + TextUtils.join(",", DatabaseConstants.FOLDER_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
|
||||
" LEFT JOIN " + DatabaseConstants.FOLDER_TABLE +
|
||||
|
|
@ -194,15 +203,24 @@ public class FeedProvider extends ContentProvider {
|
|||
}
|
||||
folderBuilder.append(" ORDER BY ");
|
||||
folderBuilder.append(DatabaseConstants.FOLDER_TABLE + "." + DatabaseConstants.FOLDER_NAME + " COLLATE NOCASE");
|
||||
cursor = db.rawQuery(folderBuilder.toString(), null);
|
||||
break;
|
||||
return db.rawQuery(folderBuilder.toString(), null);
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown URI: " + uri);
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
return 0;
|
||||
final SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
|
||||
switch (uriMatcher.match(uri)) {
|
||||
case INDIVIDUAL_FEED:
|
||||
return db.update(DatabaseConstants.FEED_TABLE, values, DatabaseConstants.FEED_ID + " = ?", new String[] { uri.getLastPathSegment() });
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown URI: " + uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ public class Feed {
|
|||
feed.positiveCount = childCursor.getInt(childCursor.getColumnIndex(DatabaseConstants.FEED_POSITIVE_COUNT));
|
||||
feed.subscribers = childCursor.getString(childCursor.getColumnIndex(DatabaseConstants.FEED_SUBSCRIBERS));
|
||||
feed.title = childCursor.getString(childCursor.getColumnIndex(DatabaseConstants.FEED_TITLE));
|
||||
childCursor.close();
|
||||
return feed;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import java.io.Serializable;
|
|||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
|
@ -22,6 +20,9 @@ public class Story implements Serializable {
|
|||
|
||||
@SerializedName("share_count")
|
||||
public String shareCount;
|
||||
|
||||
@SerializedName("share_user_ids")
|
||||
public String[] sharedUserIds;
|
||||
|
||||
@SerializedName("comment_count")
|
||||
public String commentCount;
|
||||
|
|
@ -38,7 +39,7 @@ public class Story implements Serializable {
|
|||
@SerializedName("story_title")
|
||||
public String title;
|
||||
|
||||
@SerializedName("short_parsed_date")
|
||||
@SerializedName("story_date")
|
||||
public String date;
|
||||
|
||||
@SerializedName("story_content")
|
||||
|
|
@ -50,12 +51,12 @@ public class Story implements Serializable {
|
|||
@SerializedName("story_feed_id")
|
||||
public String feedId;
|
||||
|
||||
@SerializedName("public_comments")
|
||||
public Comment[] comments;
|
||||
|
||||
@SerializedName("intelligence")
|
||||
public Intelligence intelligence = new Intelligence();
|
||||
|
||||
@SerializedName("intelligence_title")
|
||||
public String intelligenceTitle;
|
||||
|
||||
public ContentValues getValues() {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(DatabaseConstants.STORY_ID, id);
|
||||
|
|
@ -66,6 +67,7 @@ public class Story implements Serializable {
|
|||
values.put(DatabaseConstants.STORY_COMMENT_COUNT, commentCount);
|
||||
values.put(DatabaseConstants.STORY_SHARE_COUNT, shareCount);
|
||||
values.put(DatabaseConstants.STORY_AUTHORS, authors);
|
||||
values.put(DatabaseConstants.STORY_SHARED_USER_IDS, TextUtils.join(",", sharedUserIds));
|
||||
values.put(DatabaseConstants.STORY_INTELLIGENCE_AUTHORS, intelligence.intelligenceAuthors);
|
||||
values.put(DatabaseConstants.STORY_INTELLIGENCE_FEED, intelligence.intelligenceFeed);
|
||||
values.put(DatabaseConstants.STORY_INTELLIGENCE_TAGS, intelligence.intelligenceTags);
|
||||
|
|
@ -85,6 +87,7 @@ public class Story implements Serializable {
|
|||
story.shareCount = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_SHARE_COUNT));
|
||||
story.commentCount = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_COMMENT_COUNT));
|
||||
story.permalink = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_PERMALINK));
|
||||
story.sharedUserIds = TextUtils.split(cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_SHARED_USER_IDS)), ",");
|
||||
story.intelligence.intelligenceAuthors = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_AUTHORS));
|
||||
story.intelligence.intelligenceFeed = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_FEED));
|
||||
story.intelligence.intelligenceTags = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_TAGS));
|
||||
|
|
@ -96,7 +99,9 @@ public class Story implements Serializable {
|
|||
return story;
|
||||
}
|
||||
|
||||
private class Intelligence {
|
||||
private class Intelligence implements Serializable {
|
||||
private static final long serialVersionUID = -1314486209455376730L;
|
||||
|
||||
@SerializedName("feed")
|
||||
public int intelligenceFeed = 0;
|
||||
|
||||
|
|
@ -109,5 +114,6 @@ public class Story implements Serializable {
|
|||
@SerializedName("title")
|
||||
public int intelligenceTitle = 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,11 +15,9 @@ import android.widget.ExpandableListView.OnGroupClickListener;
|
|||
|
||||
import com.newsblur.R;
|
||||
import com.newsblur.activity.ItemsList;
|
||||
import com.newsblur.activity.Reading;
|
||||
import com.newsblur.database.DatabaseConstants;
|
||||
import com.newsblur.database.FeedProvider;
|
||||
import com.newsblur.database.FolderTreeAdapter;
|
||||
import com.newsblur.domain.Feed;
|
||||
import com.newsblur.util.AppConstants;
|
||||
import com.newsblur.util.UIUtils;
|
||||
import com.newsblur.view.FolderTreeViewBinder;
|
||||
|
|
@ -50,6 +48,11 @@ public class FolderFeedListFragment extends Fragment implements OnGroupClickList
|
|||
folderAdapter = new FolderTreeAdapter(getActivity(), cursor, R.layout.row_folder_collapsed, groupFrom, groupTo, R.layout.row_feed, childFrom, childTo);
|
||||
folderAdapter.setViewBinder(viewBinder);
|
||||
}
|
||||
|
||||
public void hasUpdated() {
|
||||
folderAdapter.getCursor().requery();
|
||||
folderAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
|
@ -68,7 +71,6 @@ public class FolderFeedListFragment extends Fragment implements OnGroupClickList
|
|||
}
|
||||
|
||||
public void changeState(int state) {
|
||||
|
||||
String selection = null;
|
||||
viewBinder.setState(state);
|
||||
|
||||
|
|
|
|||
|
|
@ -82,8 +82,9 @@ public class ItemListFragment extends Fragment implements LoaderManager.LoaderCa
|
|||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
Log.d(TAG, "Load finished: " + cursor.getCount());
|
||||
adapter.swapCursor(cursor);
|
||||
if (cursor != null) {
|
||||
adapter.swapCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
public void updated() {
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ public class ProfileDetailsFragment extends Fragment implements OnClickListener
|
|||
followingCount.setText("" + user.followingCount);
|
||||
|
||||
if (!viewingSelf) {
|
||||
imageLoader.DisplayImage(user.photoUrl, imageView);
|
||||
imageLoader.displayImage(user.photoUrl, user.userId, imageView);
|
||||
if (user.followedByYou) {
|
||||
unfollowButton.setVisibility(View.VISIBLE);
|
||||
followButton.setVisibility(View.GONE);
|
||||
|
|
|
|||
|
|
@ -1,58 +1,146 @@
|
|||
package com.newsblur.fragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.GridLayout;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.newsblur.R;
|
||||
import com.newsblur.activity.Profile;
|
||||
import com.newsblur.database.FeedProvider;
|
||||
import com.newsblur.domain.Comment;
|
||||
import com.newsblur.domain.Story;
|
||||
import com.newsblur.domain.UserProfile;
|
||||
import com.newsblur.network.APIManager;
|
||||
import com.newsblur.network.domain.ProfileResponse;
|
||||
import com.newsblur.util.ImageLoader;
|
||||
import com.newsblur.util.UIUtils;
|
||||
|
||||
public class ReadingItemFragment extends Fragment {
|
||||
|
||||
Story story;
|
||||
LayoutInflater inflater;
|
||||
private static final String TAG = "ReadingItemFragment";
|
||||
private Story story;
|
||||
private LayoutInflater inflater;
|
||||
private APIManager apiManager;
|
||||
private ImageLoader imageLoader = new ImageLoader(getActivity());
|
||||
|
||||
public static ReadingItemFragment newInstance(Story story) {
|
||||
ReadingItemFragment readingFragment = new ReadingItemFragment();
|
||||
|
||||
|
||||
// Supply num input as an argument.
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable("story", story);
|
||||
readingFragment.setArguments(args);
|
||||
|
||||
return readingFragment;
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable("story", story);
|
||||
readingFragment.setArguments(args);
|
||||
|
||||
return readingFragment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
apiManager = new APIManager(getActivity());
|
||||
story = getArguments() != null ? (Story) getArguments().getSerializable("story") : null;
|
||||
}
|
||||
|
||||
|
||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
|
||||
this.inflater = inflater;
|
||||
|
||||
|
||||
View view = inflater.inflate(R.layout.fragment_readingitem, null);
|
||||
WebView web = (WebView) view.findViewById(R.id.reading_webview);
|
||||
setupWebview(web);
|
||||
setupItemMetadata(view);
|
||||
|
||||
if (story.sharedUserIds.length > 0) {
|
||||
view.findViewById(R.id.reading_shared_container).setVisibility(View.VISIBLE);
|
||||
setupItemCommentsAndShares(view);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void setupItemCommentsAndShares(final View view) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
private List<UserProfile> profiles = new ArrayList<UserProfile>();
|
||||
private ArrayList<View> commentViews;
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... arg0) {
|
||||
inflater = getActivity().getLayoutInflater();
|
||||
for (String userId : story.sharedUserIds) {
|
||||
if (!imageLoader.checkForImage(userId)) {
|
||||
ProfileResponse user = apiManager.getUser(userId);
|
||||
imageLoader.cacheImage(user.user.photoUrl, user.user.userId);
|
||||
}
|
||||
}
|
||||
|
||||
ContentResolver resolver = getActivity().getContentResolver();
|
||||
Cursor cursor = resolver.query(FeedProvider.COMMENTS_URI, null, null, new String[] { story.id }, null);
|
||||
|
||||
commentViews = new ArrayList<View>();
|
||||
while (cursor.moveToNext()) {
|
||||
Comment comment = Comment.fromCursor(cursor);
|
||||
View commentView = inflater.inflate(R.layout.include_comment, null);
|
||||
TextView commentText = (TextView) commentView.findViewById(R.id.comment_text);
|
||||
commentText.setText(comment.commentText);
|
||||
ImageView commentImage = (ImageView) commentView.findViewById(R.id.comment_user_image);
|
||||
imageLoader.displayImage(Integer.toString(comment.userId), commentImage);
|
||||
TextView commentSharedDate = (TextView) commentView.findViewById(R.id.comment_shareddate);
|
||||
commentSharedDate.setText(comment.sharedDate);
|
||||
|
||||
commentViews.add(commentView);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Void result) {
|
||||
for (final String userId : story.sharedUserIds) {
|
||||
ImageView image = new ImageView(getActivity());
|
||||
image.setMaxHeight(UIUtils.convertDPsToPixels(getActivity(), 20));
|
||||
image.setMaxWidth(UIUtils.convertDPsToPixels(getActivity(), 20));
|
||||
|
||||
GridLayout grid = (GridLayout) view.findViewById(R.id.reading_social_shareimages);
|
||||
grid.addView(image);
|
||||
imageLoader.displayImage(userId, image);
|
||||
image.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent i = new Intent(getActivity(), Profile.class);
|
||||
i.putExtra(Profile.USER_ID, userId);
|
||||
startActivity(i);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (View comment : commentViews) {
|
||||
((LinearLayout) view.findViewById(R.id.reading_comment_container)).addView(comment);
|
||||
}
|
||||
};
|
||||
}.execute();
|
||||
}
|
||||
|
||||
|
||||
private void setupItemMetadata(View view) {
|
||||
TextView itemTitle = (TextView) view.findViewById(R.id.reading_item_title);
|
||||
TextView itemDate = (TextView) view.findViewById(R.id.reading_item_date);
|
||||
TextView itemAuthors = (TextView) view.findViewById(R.id.reading_item_authors);
|
||||
GridLayout tagContainer = (GridLayout) view.findViewById(R.id.reading_item_tags);
|
||||
|
||||
|
||||
if (story.tags != null || story.tags.length > 0) {
|
||||
tagContainer.setVisibility(View.VISIBLE);
|
||||
for (String tag : story.tags) {
|
||||
|
|
@ -62,7 +150,7 @@ public class ReadingItemFragment extends Fragment {
|
|||
tagContainer.addView(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
itemDate.setText(story.date);
|
||||
itemTitle.setText(story.title);
|
||||
itemAuthors.setText(story.authors);
|
||||
|
|
@ -79,7 +167,7 @@ public class ReadingItemFragment extends Fragment {
|
|||
web.getSettings().setAppCacheEnabled(true);
|
||||
web.setVerticalScrollBarEnabled(false);
|
||||
web.setHorizontalScrollBarEnabled(false);
|
||||
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
// TODO: Define a better strategy for rescaling the HTML across device screen sizes and storying this HTML as boilderplate somewhere
|
||||
builder.append("<html><head><meta name=\"viewport\" content=\"target-densitydpi=device-dpi\" /><link rel=\"stylesheet\" type=\"text/css\" href=\"reading.css\" /></head><body>");
|
||||
|
|
@ -88,5 +176,5 @@ public class ReadingItemFragment extends Fragment {
|
|||
web.loadDataWithBaseURL("file:///android_asset/", builder.toString(), "text/html", "UTF-8", null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public class APIClient {
|
|||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append((String) entry.getKey());
|
||||
builder.append("=");
|
||||
builder.append((String) entry.getValue());
|
||||
builder.append(URLEncoder.encode((String) entry.getValue()));
|
||||
parameters.add(builder.toString());
|
||||
}
|
||||
final String parameterString = TextUtils.join("&", parameters);
|
||||
|
|
|
|||
|
|
@ -10,14 +10,20 @@ public class APIConstants {
|
|||
public static final String URL_UNFOLLOW = "http://dev.newsblur.com/social/unfollow";
|
||||
|
||||
public static final String URL_USER_INTERACTIONS = "http://dev.newsblur.com/social/interactions";
|
||||
public static final String URL_FEEDS_STORIES = "http://dev.newsblur.com/reader/river_stories";
|
||||
public static final String URL_RIVER_STORIES = "http://dev.newsblur.com/reader/river_stories";
|
||||
public static final String URL_FEED_STORIES = "http://dev.newsblur.com/reader/feed";
|
||||
public static final String URL_SIGNUP = "http://dev.newsblur.com/api/signup";
|
||||
public static final String URL_FEED_COUNTS = "http://dev.newsblur.com/reader/refresh_feeds/";
|
||||
|
||||
public static final String PARAMETER_FEEDS = "feeds";
|
||||
public static final String PARAMETER_PASSWORD = "password";
|
||||
public static final String PARAMETER_USER_ID = "user_id";
|
||||
public static final String PARAMETER_USERNAME = "username";
|
||||
public static final String PARAMETER_USERID = "user_id";
|
||||
|
||||
public static final String PARAMETER_STORYID = "story_id";
|
||||
public static final String PARAMETER_FEEDID = "feed_id";
|
||||
|
||||
public static final String NEWSBLUR_URL = "http://www.newsblur.com";
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,18 @@ import android.content.ContentResolver;
|
|||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.newsblur.database.DatabaseConstants;
|
||||
import com.newsblur.database.FeedProvider;
|
||||
import com.newsblur.domain.Comment;
|
||||
import com.newsblur.domain.Feed;
|
||||
import com.newsblur.domain.FolderStructure;
|
||||
import com.newsblur.domain.Story;
|
||||
import com.newsblur.network.domain.FeedFolderResponse;
|
||||
import com.newsblur.network.domain.FeedRefreshResponse;
|
||||
import com.newsblur.network.domain.LoginResponse;
|
||||
import com.newsblur.network.domain.ProfileResponse;
|
||||
import com.newsblur.network.domain.StoriesResponse;
|
||||
|
|
@ -85,13 +88,23 @@ public class APIManager {
|
|||
final APIClient client = new APIClient(context);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_FEEDS, feedId);
|
||||
client.get(APIConstants.URL_FEEDS_STORIES, values);
|
||||
final APIResponse response = client.get(APIConstants.URL_FEEDS_STORIES, values);
|
||||
Uri feedUri = Uri.parse(APIConstants.URL_FEED_STORIES).buildUpon().appendPath(feedId).build();
|
||||
final APIResponse response = client.get(feedUri.toString(), values);
|
||||
StoriesResponse storiesResponse = gson.fromJson(response.responseString, StoriesResponse.class);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
Uri feedUri = FeedProvider.STORIES_URI.buildUpon().appendPath(feedId).build();
|
||||
Uri storyUri = FeedProvider.STORIES_URI.buildUpon().appendPath(feedId).build();
|
||||
for (Story story : storiesResponse.stories) {
|
||||
contentResolver.insert(feedUri, story.getValues());
|
||||
contentResolver.insert(storyUri, story.getValues());
|
||||
|
||||
for (Comment comment : story.comments) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(story.id);
|
||||
builder.append(story.feedId);
|
||||
builder.append(comment.userId);
|
||||
comment.storyId = story.id;
|
||||
comment.id = (builder.toString());
|
||||
contentResolver.insert(FeedProvider.COMMENTS_URI, comment.getValues());
|
||||
}
|
||||
}
|
||||
return storiesResponse;
|
||||
} else {
|
||||
|
|
@ -160,4 +173,16 @@ public class APIManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void refreshFeedCounts() {
|
||||
final APIClient client = new APIClient(context);
|
||||
final APIResponse response = client.get(APIConstants.URL_FEED_COUNTS);
|
||||
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
|
||||
final FeedRefreshResponse feedCountUpdate = gson.fromJson(response.responseString, FeedRefreshResponse.class);
|
||||
for (String feedId : feedCountUpdate.feedCounts.keySet()) {
|
||||
Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(feedId).build();
|
||||
contentResolver.update(feedUri, feedCountUpdate.feedCounts.get(feedId).getValues(), null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import android.util.Log;
|
|||
|
||||
import com.newsblur.network.APIClient;
|
||||
import com.newsblur.network.APIManager;
|
||||
import com.newsblur.network.domain.StoriesResponse;
|
||||
|
||||
/**
|
||||
* The SyncService is based on an app architecture that tries to place network calls
|
||||
|
|
@ -25,13 +24,14 @@ public class SyncService extends IntentService {
|
|||
public static final String EXTRA_STATUS_RECEIVER = "resultReceiverExtra";
|
||||
public static final String EXTRA_TASK_FEED_ID = "taskFeedId";
|
||||
|
||||
public final static int STATUS_RUNNING = 0;
|
||||
public final static int STATUS_FINISHED = 1;
|
||||
public final static int STATUS_ERROR = 2;
|
||||
public static final int NOT_RUNNING = -1;
|
||||
public final static int STATUS_RUNNING = 0x02;
|
||||
public final static int STATUS_FINISHED = 0x03;
|
||||
public final static int STATUS_ERROR = 0x04;
|
||||
public static final int NOT_RUNNING = 0x01;
|
||||
|
||||
public static final int EXTRA_TASK_FOLDER_UPDATE = 30;
|
||||
public static final int EXTRA_TASK_FEED_UPDATE = 31;
|
||||
public static final int EXTRA_TASK_REFRESH_COUNTS = 32;
|
||||
|
||||
public APIClient apiClient;
|
||||
private APIManager apiManager;
|
||||
|
|
@ -60,6 +60,9 @@ public class SyncService extends IntentService {
|
|||
case EXTRA_TASK_FOLDER_UPDATE:
|
||||
apiManager.getFolderFeedMapping();
|
||||
break;
|
||||
case EXTRA_TASK_REFRESH_COUNTS:
|
||||
apiManager.refreshFeedCounts();
|
||||
break;
|
||||
case EXTRA_TASK_FEED_UPDATE:
|
||||
if (!TextUtils.isEmpty(intent.getStringExtra(EXTRA_TASK_FEED_ID))) {
|
||||
apiManager.getStoriesForFeed(intent.getStringExtra(EXTRA_TASK_FEED_ID));
|
||||
|
|
|
|||
|
|
@ -34,26 +34,43 @@ public class ImageLoader {
|
|||
fileCache = new FileCache(context);
|
||||
executorService = Executors.newFixedThreadPool(5);
|
||||
}
|
||||
|
||||
public void DisplayImage(String url, ImageView imageView) {
|
||||
imageViews.put(imageView, url);
|
||||
Bitmap bitmap = memoryCache.get(url);
|
||||
|
||||
public void displayImage(String url, String uid, ImageView imageView) {
|
||||
imageViews.put(imageView, uid);
|
||||
Bitmap bitmap = memoryCache.get(uid);
|
||||
if (bitmap != null) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
} else {
|
||||
queuePhoto(url, imageView);
|
||||
queuePhoto(url, uid, imageView);
|
||||
imageView.setImageResource(R.drawable.logo);
|
||||
}
|
||||
}
|
||||
|
||||
private void queuePhoto(String url, ImageView imageView) {
|
||||
PhotoToLoad p = new PhotoToLoad(url, imageView);
|
||||
executorService.submit(new PhotosLoader(p));
|
||||
|
||||
// Display an image assuming it's in cache
|
||||
public void displayImage(String uid, ImageView imageView) {
|
||||
Bitmap bitmap = memoryCache.get(uid);
|
||||
if (bitmap != null) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
} else {
|
||||
File f= fileCache.getFile(uid);
|
||||
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath());
|
||||
memoryCache.put(uid, bitmap);
|
||||
imageView.setImageBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
private Bitmap getBitmap(String url) {
|
||||
private void queuePhoto(String url, String uid, ImageView imageView) {
|
||||
PhotoToLoad p = new PhotoToLoad(url, uid, imageView);
|
||||
executorService.submit(new PhotosLoader(p));
|
||||
}
|
||||
|
||||
public boolean checkForImage(String uid) {
|
||||
return (fileCache.getFile(uid) != null || memoryCache.get(uid) != null);
|
||||
}
|
||||
|
||||
private Bitmap getBitmap(String url, String uid) {
|
||||
|
||||
File f = fileCache.getFile(url);
|
||||
File f = fileCache.getFile(uid);
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(f.getAbsolutePath());
|
||||
|
||||
if (bitmap != null) {
|
||||
|
|
@ -88,8 +105,10 @@ public class ImageLoader {
|
|||
private class PhotoToLoad {
|
||||
public String url;
|
||||
public ImageView imageView;
|
||||
public PhotoToLoad(final String u, final ImageView i) {
|
||||
public String uid;
|
||||
public PhotoToLoad(final String u, final String id, final ImageView i) {
|
||||
url = u;
|
||||
uid = id;
|
||||
imageView = i;
|
||||
}
|
||||
}
|
||||
|
|
@ -107,8 +126,8 @@ public class ImageLoader {
|
|||
return;
|
||||
}
|
||||
|
||||
Bitmap bmp = getBitmap(photoToLoad.url);
|
||||
memoryCache.put(photoToLoad.url, bmp);
|
||||
Bitmap bmp = getBitmap(photoToLoad.url, photoToLoad.uid);
|
||||
memoryCache.put(photoToLoad.uid, bmp);
|
||||
if (imageViewReused(photoToLoad)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -121,7 +140,7 @@ public class ImageLoader {
|
|||
|
||||
private boolean imageViewReused(PhotoToLoad photoToLoad){
|
||||
final String tag = imageViews.get(photoToLoad.imageView);
|
||||
return (tag == null || !tag.equals(photoToLoad.url));
|
||||
return (tag == null || !tag.equals(photoToLoad.uid));
|
||||
}
|
||||
|
||||
private class BitmapDisplayer implements Runnable {
|
||||
|
|
@ -148,4 +167,8 @@ public class ImageLoader {
|
|||
fileCache.clear();
|
||||
}
|
||||
|
||||
public void cacheImage(String photoUrl, String userId) {
|
||||
getBitmap(photoUrl, userId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ public class ActivitiesAdapter extends ArrayAdapter<ActivitiesResponse> {
|
|||
ImageView imageView = (ImageView) view.findViewById(R.id.row_activity_icon);
|
||||
|
||||
activityTime.setText(activity.timeSince + " " + ago);
|
||||
imageLoader.DisplayImage(activity.user.photoUrl, imageView);
|
||||
imageLoader.displayImage(activity.user.photoUrl, activity.id, imageView);
|
||||
|
||||
activityText.setText(stringBuilder);
|
||||
activityText.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue