mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
Merge branch 'master' into tagging
# By ojiikun (6) and Samuel Clay (3) * master: Adding ellipses in webkit. Adding downtime handling to readme. Putting a max on sporadic checks on broken feeds to 8x normal amount. Complete styling of overlay buttons. Placeholder styling of overlay buttons. Enable/disabe state for overlay buttons. Make overlay buttons fuctional. Basic overlay button UI. Fix crash on marking all stories read (#382)
This commit is contained in:
commit
2b5c625c48
26 changed files with 253 additions and 36 deletions
71
README.md
71
README.md
|
@ -240,6 +240,77 @@ reader, and feed importer. To run the test suite:
|
|||
./manage.py test --settings=utils.test-settings
|
||||
|
||||
|
||||
## In Case of Downtime
|
||||
|
||||
You got the downtime message either through email or SMS. This is the order of operations for determining what's wrong.
|
||||
|
||||
0. Ensure you have `secrets-newsblur/configs/hosts` installed in your `/etc/hosts` so server hostnames
|
||||
work.
|
||||
|
||||
1. Check www.newsblur.com to confirm it's down.
|
||||
|
||||
If you don't get a 502 page, then NewsBlur isn't even reachable and you just need to contact the
|
||||
hosting provider and yell at them.
|
||||
|
||||
2. Check [Sentry](https://app.getsentry.com/newsblur/app/) and see if the answer is at the top of the
|
||||
list.
|
||||
|
||||
This will show if a database (redis, mongo, postgres) can't be found.
|
||||
|
||||
3. Check the various databases:
|
||||
|
||||
a. If Redis server (db_redis, db_redis_story, db_redis_pubsub) can't connect, redis is probably down.
|
||||
|
||||
SSH into the offending server (or just check both the `db_redis` and `db_redis_story` servers) and
|
||||
check if `redis` is running. You can often `tail -f -n 100 /var/log/redis.log` to find out if
|
||||
background saving was being SIG(TERM|INT)'ed. When redis goes down, it's always because it's
|
||||
consuming too much memory. That shouldn't happen, so check the [munin
|
||||
graphs](http://db_redis/munin/).
|
||||
|
||||
Boot it with `sudo /etc/init.d/redis start`.
|
||||
|
||||
b. If mongo (db_mongo) can't connect, mongo is probably down.
|
||||
|
||||
This is rare and usually signifies hardware failure. SSH into `db_mongo` and check logs with `tail
|
||||
-f -n 100 /var/log/mongodb/mongodb.log`. Start mongo with `sudo /etc/init.d/mongodb start` then
|
||||
promote the next largest mongodb server. You want to then promote one of the secondaries to
|
||||
primary, kill the offending primary machine, and rebuild it (preferably at a higher size). I
|
||||
recommend waiting a day to rebuild it so that you get a different machine. Don't forget to lodge a
|
||||
support ticket with the hosting provider so they know to check the machine.
|
||||
|
||||
If it's the db_mongo_analytics machine, there is no backup nor secondaries of the data (because
|
||||
it's ephemeral and used for, you guessed it, analytics). You can easily provision a new mongodb
|
||||
server and point to that machine.
|
||||
|
||||
c. If postgresql (db_pgsql) can't connect, postgres is probably down.
|
||||
|
||||
This is the rarest of the rare and has in fact never happened. Machine failure. If you can salvage
|
||||
the db data, move it to another machine. Worst case you have nightly backups in S3. The fabfile.py
|
||||
has commands to assist in restoring from backup (the backup file just needs to be local).
|
||||
|
||||
4. Point to a new/different machine
|
||||
|
||||
a. Confirm the IP address of the new machine with `fab list_do`.
|
||||
|
||||
b. Change `secrets-newsbur/config/hosts` to reflect the new machine.
|
||||
|
||||
c. Copy the new `hosts` file to all machines with:
|
||||
|
||||
```
|
||||
fab all setup_hosts
|
||||
fab ec2task setup_hosts
|
||||
```
|
||||
|
||||
d. Changes should be instant, but you can also bounce every machine with:
|
||||
|
||||
```
|
||||
fab web deploy:fast=True # fast=True just kill -9's processes.
|
||||
fab task celery
|
||||
fab ec2task celery
|
||||
```
|
||||
|
||||
e. Monitor tlnb.py and tlnbt.py for lots of reading and feed fetching.
|
||||
|
||||
## Author
|
||||
|
||||
* Created by [Samuel Clay](http://www.samuelclay.com).
|
||||
|
|
|
@ -1392,8 +1392,7 @@ class Feed(models.Model):
|
|||
total = total * 12
|
||||
|
||||
# 3 day max
|
||||
if total > 60*24*3:
|
||||
total = 60*24*3
|
||||
total = min(total, 60*24*2)
|
||||
|
||||
if verbose:
|
||||
logging.debug(" ---> [%-30s] Fetched every %s min - Subs: %s/%s/%s Stories: %s" % (
|
||||
|
@ -1411,6 +1410,7 @@ class Feed(models.Model):
|
|||
|
||||
if error_count:
|
||||
total = total * error_count
|
||||
total = min(total, 60*24*7)
|
||||
if verbose:
|
||||
logging.debug(' ---> [%-30s] ~FBScheduling feed fetch geometrically: '
|
||||
'~SB%s errors. Time: %s min' % (
|
||||
|
|
BIN
clients/android/NewsBlur/res/drawable/overlay_left_disabled.png
Normal file
BIN
clients/android/NewsBlur/res/drawable/overlay_left_disabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
clients/android/NewsBlur/res/drawable/overlay_left_enabled.png
Normal file
BIN
clients/android/NewsBlur/res/drawable/overlay_left_enabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
clients/android/NewsBlur/res/drawable/overlay_left_pressed.png
Normal file
BIN
clients/android/NewsBlur/res/drawable/overlay_left_pressed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
clients/android/NewsBlur/res/drawable/overlay_right_disabled.png
Normal file
BIN
clients/android/NewsBlur/res/drawable/overlay_right_disabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
BIN
clients/android/NewsBlur/res/drawable/overlay_right_enabled.png
Normal file
BIN
clients/android/NewsBlur/res/drawable/overlay_right_enabled.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
BIN
clients/android/NewsBlur/res/drawable/overlay_right_pressed.png
Normal file
BIN
clients/android/NewsBlur/res/drawable/overlay_right_pressed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_pressed="true" android:drawable="@drawable/overlay_left_pressed" />
|
||||
<item android:state_enabled="false" android:drawable="@drawable/overlay_left_disabled" />
|
||||
<item android:state_enabled="true" android:drawable="@drawable/overlay_left_enabled" />
|
||||
</selector>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_pressed="true" android:drawable="@drawable/overlay_right_pressed" />
|
||||
<item android:state_enabled="false" android:drawable="@drawable/overlay_right_disabled" />
|
||||
<item android:state_enabled="true" android:drawable="@drawable/overlay_right_enabled" />
|
||||
</selector>
|
|
@ -14,4 +14,35 @@
|
|||
android:layout_height="1dip"
|
||||
android:layout_alignParentTop="true" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true" >
|
||||
|
||||
<Button
|
||||
android:id="@+id/reading_overlay_left"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="41dp"
|
||||
android:background="@drawable/selector_overlay_bg_left"
|
||||
android:textSize="14sp"
|
||||
android:padding="6dp"
|
||||
android:onClick="overlayLeft" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/reading_overlay_right"
|
||||
android:layout_width="125dp"
|
||||
android:layout_height="41dp"
|
||||
android:background="@drawable/selector_overlay_bg_right"
|
||||
android:text="@string/overlay_next"
|
||||
android:textColor="@color/half_darkgray"
|
||||
android:textSize="14sp"
|
||||
android:padding="6dp"
|
||||
android:onClick="overlayRight" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.newsblur.view.NonfocusScrollview xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/reading_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/item_background" >
|
||||
|
@ -41,4 +42,4 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
</com.newsblur.view.NonfocusScrollview>
|
||||
</com.newsblur.view.NonfocusScrollview>
|
||||
|
|
|
@ -46,7 +46,8 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp" >
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginBottom="50dp" >
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/reading_friend_comment_container"
|
||||
|
|
|
@ -58,6 +58,9 @@
|
|||
<string name="save_this">SAVE THIS STORY</string>
|
||||
<string name="share_this">SHARE THIS STORY</string>
|
||||
|
||||
<string name="overlay_next">NEXT</string>
|
||||
<string name="overlay_done">DONE</string>
|
||||
|
||||
<string name="reply_to">Reply to \"%s\"</string>
|
||||
|
||||
<string name="alert_dialog_ok">Okay</string>
|
||||
|
|
|
@ -17,7 +17,6 @@ import com.newsblur.util.StoryOrder;
|
|||
|
||||
public class AllSharedStoriesReading extends Reading {
|
||||
|
||||
private Cursor stories;
|
||||
private int currentPage;
|
||||
private boolean requestingPage = false;
|
||||
private boolean stopLoading = false;
|
||||
|
@ -80,11 +79,8 @@ public class AllSharedStoriesReading extends Reading {
|
|||
|
||||
@Override
|
||||
public void updateAfterSync() {
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
stories.requery();
|
||||
readingAdapter.notifyDataSetChanged();
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
requestingPage = false;
|
||||
super.updateAfterSync();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,7 +17,6 @@ import com.newsblur.util.StoryOrder;
|
|||
|
||||
public class AllStoriesReading extends Reading {
|
||||
|
||||
private Cursor stories;
|
||||
private int currentPage;
|
||||
private ArrayList<String> feedIds;
|
||||
private boolean stopLoading = false;
|
||||
|
@ -81,11 +80,8 @@ public class AllStoriesReading extends Reading {
|
|||
|
||||
@Override
|
||||
public void updateAfterSync() {
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
stories.requery();
|
||||
requestedPage = false;
|
||||
readingAdapter.notifyDataSetChanged();
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
super.updateAfterSync();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -69,11 +69,8 @@ public class FeedReading extends Reading {
|
|||
|
||||
@Override
|
||||
public void updateAfterSync() {
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
stories.requery();
|
||||
requestedPage = false;
|
||||
readingAdapter.notifyDataSetChanged();
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
super.updateAfterSync();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -68,11 +68,8 @@ public class FolderReading extends Reading {
|
|||
|
||||
@Override
|
||||
public void updateAfterSync() {
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
stories.requery();
|
||||
requestedPage = false;
|
||||
readingAdapter.notifyDataSetChanged();
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
super.updateAfterSync();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,6 +12,9 @@ import android.support.v4.app.DialogFragment;
|
|||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.view.ViewPager.OnPageChangeListener;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||
|
||||
|
@ -34,8 +37,9 @@ import com.newsblur.util.PrefsUtils;
|
|||
import com.newsblur.util.ReadFilter;
|
||||
import com.newsblur.util.StoryOrder;
|
||||
import com.newsblur.util.UIUtils;
|
||||
import com.newsblur.view.NonfocusScrollview.ScrollChangeListener;
|
||||
|
||||
public abstract class Reading extends NbFragmentActivity implements OnPageChangeListener, SyncUpdateFragment.SyncUpdateFragmentInterface, OnSeekBarChangeListener {
|
||||
public abstract class Reading extends NbFragmentActivity implements OnPageChangeListener, SyncUpdateFragment.SyncUpdateFragmentInterface, OnSeekBarChangeListener, ScrollChangeListener {
|
||||
|
||||
public static final String EXTRA_FEED = "feed_selected";
|
||||
public static final String EXTRA_POSITION = "feed_position";
|
||||
|
@ -45,10 +49,14 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
|
|||
public static final String EXTRA_FEED_IDS = "feed_ids";
|
||||
private static final String TEXT_SIZE = "textsize";
|
||||
|
||||
private static final int OVERLAY_RANGE_TOP_DP = 50;
|
||||
private static final int OVERLAY_RANGE_BOT_DP = 60;
|
||||
|
||||
protected int passedPosition;
|
||||
protected int currentState;
|
||||
|
||||
protected ViewPager pager;
|
||||
protected Button overlayLeft, overlayRight;
|
||||
protected FragmentManager fragmentManager;
|
||||
protected ReadingAdapter readingAdapter;
|
||||
protected ContentResolver contentResolver;
|
||||
|
@ -58,12 +66,18 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
|
|||
|
||||
private Set<Story> storiesToMarkAsRead;
|
||||
|
||||
private float overlayRangeTopPx;
|
||||
private float overlayRangeBotPx;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceBundle) {
|
||||
requestWindowFeature(Window.FEATURE_PROGRESS);
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
super.onCreate(savedInstanceBundle);
|
||||
|
||||
setContentView(R.layout.activity_reading);
|
||||
this.overlayLeft = (Button) findViewById(R.id.reading_overlay_left);
|
||||
this.overlayRight = (Button) findViewById(R.id.reading_overlay_right);
|
||||
|
||||
fragmentManager = getSupportFragmentManager();
|
||||
|
||||
|
@ -76,6 +90,10 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
|
|||
|
||||
this.apiManager = new APIManager(this);
|
||||
|
||||
// this value is expensive to compute but doesn't change during a single runtime
|
||||
this.overlayRangeTopPx = (float) UIUtils.convertDPsToPixels(this, OVERLAY_RANGE_TOP_DP);
|
||||
this.overlayRangeBotPx = (float) UIUtils.convertDPsToPixels(this, OVERLAY_RANGE_BOT_DP);
|
||||
|
||||
}
|
||||
|
||||
protected void setupPager() {
|
||||
|
@ -93,6 +111,7 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
|
|||
pager.setAdapter(readingAdapter);
|
||||
pager.setCurrentItem(passedPosition);
|
||||
readingAdapter.setCurrentItem(passedPosition);
|
||||
this.enableOverlays();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -151,6 +170,8 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
|
|||
}
|
||||
}
|
||||
|
||||
// interface OnPageChangeListener
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int arg0) {
|
||||
}
|
||||
|
@ -160,15 +181,49 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(final int position) {
|
||||
public void onPageSelected(int position) {
|
||||
this.setOverlayAlpha(1.0f);
|
||||
this.enableOverlays();
|
||||
}
|
||||
|
||||
// interface ScrollChangeListener
|
||||
|
||||
@Override
|
||||
public void scrollChanged(int hPos, int vPos, int currentWidth, int currentHeight) {
|
||||
int scrollMax = currentHeight - findViewById(android.R.id.content).getMeasuredHeight();
|
||||
int posFromBot = (scrollMax - vPos);
|
||||
|
||||
float newAlpha = 0.0f;
|
||||
if (vPos < this.overlayRangeTopPx) {
|
||||
float delta = this.overlayRangeTopPx - ((float) vPos);
|
||||
newAlpha = delta / this.overlayRangeTopPx;
|
||||
} else if (posFromBot < this.overlayRangeBotPx) {
|
||||
float delta = this.overlayRangeBotPx - ((float) posFromBot);
|
||||
newAlpha = delta / this.overlayRangeBotPx;
|
||||
}
|
||||
|
||||
this.setOverlayAlpha(newAlpha);
|
||||
}
|
||||
|
||||
private void setOverlayAlpha(float a) {
|
||||
UIUtils.setViewAlpha(this.overlayLeft, a);
|
||||
UIUtils.setViewAlpha(this.overlayRight, a);
|
||||
}
|
||||
|
||||
private void enableOverlays() {
|
||||
int page = this.pager.getCurrentItem();
|
||||
this.overlayLeft.setEnabled(page > 0);
|
||||
this.overlayRight.setEnabled(page < (this.readingAdapter.getCount()-1));
|
||||
this.overlayRight.setText((page < (this.readingAdapter.getCount()-1)) ? R.string.overlay_next : R.string.overlay_done);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAfterSync() {
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
stories.requery();
|
||||
readingAdapter.notifyDataSetChanged();
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
this.enableOverlays();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -176,6 +231,7 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
|
|||
stories.requery();
|
||||
readingAdapter.notifyDataSetChanged();
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
this.enableOverlays();
|
||||
}
|
||||
|
||||
public abstract void checkStoryCount(int position);
|
||||
|
@ -246,7 +302,12 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
|
|||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
public void overlayRight(View v) {
|
||||
pager.setCurrentItem(pager.getCurrentItem()+1, true);
|
||||
}
|
||||
|
||||
|
||||
public void overlayLeft(View v) {
|
||||
pager.setCurrentItem(pager.getCurrentItem()-1, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import com.newsblur.service.SyncService;
|
|||
|
||||
public class SavedStoriesReading extends Reading {
|
||||
|
||||
private Cursor stories;
|
||||
private int currentPage;
|
||||
private boolean stopLoading = false;
|
||||
private boolean requestedPage = false;
|
||||
|
@ -66,11 +65,8 @@ public class SavedStoriesReading extends Reading {
|
|||
|
||||
@Override
|
||||
public void updateAfterSync() {
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
stories.requery();
|
||||
requestedPage = false;
|
||||
readingAdapter.notifyDataSetChanged();
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
super.updateAfterSync();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -153,7 +153,7 @@ public class DatabaseConstants {
|
|||
private static final String SOCIAL_INTELLIGENCE_BEST = " (" + DatabaseConstants.SOCIAL_FEED_POSITIVE_COUNT + ") > 0 ";
|
||||
private static final String SUM_STORY_TOTAL = "storyTotal";
|
||||
|
||||
public static final String FEED_FILTER_FOCUS = " WHERE " + FEED_TABLE + "." + FEED_POSITIVE_COUNT + " > 0 ";
|
||||
public static final String FEED_FILTER_FOCUS = FEED_TABLE + "." + FEED_POSITIVE_COUNT + " > 0 ";
|
||||
|
||||
private static String STORY_SUM_TOTAL = " CASE " +
|
||||
"WHEN MAX(" + DatabaseConstants.STORY_INTELLIGENCE_AUTHORS + "," + DatabaseConstants.STORY_INTELLIGENCE_TAGS + "," + DatabaseConstants.STORY_INTELLIGENCE_TITLE + ") > 0 " +
|
||||
|
@ -163,9 +163,9 @@ public class DatabaseConstants {
|
|||
"ELSE " + DatabaseConstants.STORY_INTELLIGENCE_FEED + " " +
|
||||
"END AS " + DatabaseConstants.SUM_STORY_TOTAL;
|
||||
|
||||
public static final String STORY_INTELLIGENCE_BEST = DatabaseConstants.SUM_STORY_TOTAL + " > 0 ";
|
||||
public static final String STORY_INTELLIGENCE_SOME = DatabaseConstants.SUM_STORY_TOTAL + " >= 0 ";
|
||||
public static final String STORY_INTELLIGENCE_ALL = DatabaseConstants.SUM_STORY_TOTAL + " >= 0 ";
|
||||
private static final String STORY_INTELLIGENCE_BEST = DatabaseConstants.SUM_STORY_TOTAL + " > 0 ";
|
||||
private static final String STORY_INTELLIGENCE_SOME = DatabaseConstants.SUM_STORY_TOTAL + " >= 0 ";
|
||||
private static final String STORY_INTELLIGENCE_ALL = DatabaseConstants.SUM_STORY_TOTAL + " >= 0 ";
|
||||
|
||||
public static final String[] STORY_COLUMNS = {
|
||||
STORY_AUTHORS, STORY_COMMENT_COUNT, STORY_CONTENT, STORY_DATE, STORY_SHARED_DATE, STORY_SHORTDATE, STORY_LONGDATE, STORY_TABLE + "." + STORY_FEED_ID, STORY_TABLE + "." + STORY_ID, STORY_INTELLIGENCE_AUTHORS, STORY_INTELLIGENCE_FEED, STORY_INTELLIGENCE_TAGS, STORY_INTELLIGENCE_TITLE,
|
||||
|
|
|
@ -355,7 +355,7 @@ public class FeedProvider extends ContentProvider {
|
|||
String feedsQuery = "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 +
|
||||
((selection == null) ? "" : selection) +
|
||||
((selection == null) ? "" : " WHERE " + selection) +
|
||||
" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE";
|
||||
return db.rawQuery(feedsQuery, selectionArgs);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.newsblur.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
|
@ -42,6 +43,7 @@ import com.newsblur.util.UIUtils;
|
|||
import com.newsblur.util.ViewUtils;
|
||||
import com.newsblur.view.FlowLayout;
|
||||
import com.newsblur.view.NewsblurWebview;
|
||||
import com.newsblur.view.NonfocusScrollview;
|
||||
|
||||
public class ReadingItemFragment extends Fragment implements ClassifierDialogFragment.TagUpdateCallback, ShareDialogFragment.SharedCallbackDialog {
|
||||
|
||||
|
@ -64,6 +66,7 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
|
|||
private UserDetails user;
|
||||
public String previouslySavedShareText;
|
||||
private ImageView feedIcon;
|
||||
private Reading activity;
|
||||
|
||||
public static ReadingItemFragment newInstance(Story story, String feedTitle, String feedFaviconColor, String feedFaviconFade, String feedFaviconBorder, String faviconText, String faviconUrl, Classifier classifier, boolean displayFeedDetails) {
|
||||
ReadingItemFragment readingFragment = new ReadingItemFragment();
|
||||
|
@ -83,6 +86,13 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
|
|||
return readingFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
if (activity instanceof Reading) {
|
||||
this.activity = (Reading) activity;
|
||||
}
|
||||
super.onAttach(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -147,6 +157,9 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
|
|||
setupItemCommentsAndShares(view);
|
||||
}
|
||||
|
||||
NonfocusScrollview scrollView = (NonfocusScrollview) view.findViewById(R.id.reading_scrollview);
|
||||
scrollView.registerScrollChangeListener(this.activity);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
public class UIUtils {
|
||||
|
||||
|
@ -70,9 +72,20 @@ public class UIUtils {
|
|||
* used throughout Android.
|
||||
* See: http://bit.ly/MfsAUZ (Romain Guy's comment)
|
||||
*/
|
||||
|
||||
public static int convertDPsToPixels(Context context, final int dps) {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dps * scale + 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the alpha of a view in a manner that is safe to use before API version 11.
|
||||
* If alpha isn't supported, just make the view invisible if the alpha is so low
|
||||
* that it may as well be.
|
||||
*/
|
||||
public static void setViewAlpha(View v, float alpha) {
|
||||
v.setVisibility((alpha > 0.001) ? View.VISIBLE : View.INVISIBLE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
v.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
package com.newsblur.view;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
public class NonfocusScrollview extends ScrollView {
|
||||
|
||||
private Set<ScrollChangeListener> changeListeners = new HashSet<ScrollChangeListener>();
|
||||
|
||||
public NonfocusScrollview(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
@ -23,4 +29,22 @@ public class NonfocusScrollview extends ScrollView {
|
|||
}
|
||||
super.requestChildFocus(child, focused);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
|
||||
int w = this.getChildAt(0).getMeasuredWidth();
|
||||
int h = this.getChildAt(0).getMeasuredHeight();
|
||||
for (ScrollChangeListener listener : this.changeListeners) {
|
||||
listener.scrollChanged(l, t, w, h);
|
||||
}
|
||||
super.onScrollChanged(l, t, oldl, oldt);
|
||||
}
|
||||
|
||||
public void registerScrollChangeListener(ScrollChangeListener listener) {
|
||||
this.changeListeners.add(listener);
|
||||
}
|
||||
|
||||
public interface ScrollChangeListener {
|
||||
public void scrollChanged(int hPos, int vPos, int currentWidth, int currentHeight);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -674,6 +674,11 @@ body {
|
|||
height: 14px;
|
||||
overflow: hidden;
|
||||
text-shadow: 0 1px 0 rgba(250, 250, 250, .4);
|
||||
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
display: -webkit-box;
|
||||
}
|
||||
|
||||
.NB-feedlist .feed .NB-feedlist-manage-icon,
|
||||
|
|
Loading…
Add table
Reference in a new issue