mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
Merge branch 'master' into organizer
* master: Preventing brentozar.com from being subscribed to because their lawyer sent me a Cease and Desist nastygram. Adding lisp syntax highlighting. Also upgrading syntax highlighter. Per @IFTTT's request, changing ifttt key to meta. Make full mark-read action lifecycle recount stories, not just first mark. Improve chaining of updated cursor data from Reading activity down through to adapter and fragments.
This commit is contained in:
commit
4c4c48f195
9 changed files with 147 additions and 152 deletions
|
@ -455,14 +455,14 @@ def api_unread_story(request, trigger_slug=None):
|
|||
"Site": feed and feed['title'],
|
||||
"SiteURL": feed and feed['website'],
|
||||
"SiteRSS": feed and feed['address'],
|
||||
"ifttt": {
|
||||
"meta": {
|
||||
"id": story['story_hash'],
|
||||
"timestamp": int(story['story_date'].strftime("%s"))
|
||||
},
|
||||
})
|
||||
|
||||
if after:
|
||||
entries = sorted(entries, key=lambda s: s['ifttt']['timestamp'])
|
||||
entries = sorted(entries, key=lambda s: s['meta']['timestamp'])
|
||||
|
||||
logging.user(request, "~FYChecking unread%s stories with ~SB~FCIFTTT~SN~FY: ~SB%s~SN - ~SB%s~SN stories" % (" ~SBfocus~SN" if trigger_slug == "new-unread-focus-story" else "", feed_or_folder, len(entries)))
|
||||
|
||||
|
@ -511,14 +511,14 @@ def api_saved_story(request):
|
|||
"Site": feed and feed['title'],
|
||||
"SiteURL": feed and feed['website'],
|
||||
"SiteRSS": feed and feed['address'],
|
||||
"ifttt": {
|
||||
"meta": {
|
||||
"id": story['story_hash'],
|
||||
"timestamp": int(story['starred_date'].strftime("%s"))
|
||||
},
|
||||
})
|
||||
|
||||
if after:
|
||||
entries = sorted(entries, key=lambda s: s['ifttt']['timestamp'])
|
||||
entries = sorted(entries, key=lambda s: s['meta']['timestamp'])
|
||||
|
||||
logging.user(request, "~FCChecking saved stories from ~SBIFTTT~SB: ~SB%s~SN - ~SB%s~SN stories" % (story_tag if story_tag else "[All stories]", len(entries)))
|
||||
|
||||
|
@ -597,14 +597,14 @@ def api_shared_story(request):
|
|||
"Site": feed and feed['title'],
|
||||
"SiteURL": feed and feed['website'],
|
||||
"SiteRSS": feed and feed['address'],
|
||||
"ifttt": {
|
||||
"meta": {
|
||||
"id": story['story_hash'],
|
||||
"timestamp": int(story['shared_date'].strftime("%s"))
|
||||
},
|
||||
})
|
||||
|
||||
if after:
|
||||
entries = sorted(entries, key=lambda s: s['ifttt']['timestamp'])
|
||||
entries = sorted(entries, key=lambda s: s['meta']['timestamp'])
|
||||
|
||||
logging.user(request, "~FMChecking shared stories from ~SB~FCIFTTT~SN~FM: ~SB~FM%s~FM~SN - ~SB%s~SN stories" % (blurblog_user, len(entries)))
|
||||
|
||||
|
|
|
@ -59,6 +59,10 @@ from utils.ratelimit import ratelimit
|
|||
from vendor.timezones.utilities import localtime_for_timezone
|
||||
|
||||
|
||||
BANNED_URLS = [
|
||||
"brentozar.com",
|
||||
]
|
||||
|
||||
@never_cache
|
||||
@render_to('reader/dashboard.xhtml')
|
||||
def index(request, **kwargs):
|
||||
|
@ -1574,6 +1578,9 @@ def add_url(request):
|
|||
if not url:
|
||||
code = -1
|
||||
message = 'Enter in the website address or the feed URL.'
|
||||
elif any([(banned_url in url) for banned_url in BANNED_URLS]):
|
||||
code = -1
|
||||
message = "The publisher of this website has banned NewsBlur."
|
||||
else:
|
||||
if new_folder:
|
||||
usf, _ = UserSubscriptionFolders.objects.get_or_create(user=request.user)
|
||||
|
|
|
@ -194,41 +194,34 @@ public abstract class Reading extends NbActivity implements OnPageChangeListener
|
|||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
synchronized (STORIES_MUTEX) {
|
||||
if (cursor != null) {
|
||||
readingAdapter.swapCursor(cursor);
|
||||
stories = cursor;
|
||||
}
|
||||
if (cursor == null) return;
|
||||
|
||||
readingAdapter.swapCursor(cursor);
|
||||
stories = cursor;
|
||||
|
||||
// if this is the first time we've found a cursor, we know the onCreate chain is done
|
||||
if (this.pager == null) {
|
||||
|
||||
int currentUnreadCount = getUnreadCount();
|
||||
if (currentUnreadCount > this.startingUnreadCount ) {
|
||||
this.startingUnreadCount = currentUnreadCount;
|
||||
}
|
||||
|
||||
// set up the pager after the unread count, so the first mark-read doesn't happen too quickly
|
||||
setupPager();
|
||||
}
|
||||
|
||||
try {
|
||||
readingAdapter.notifyDataSetChanged();
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
if (this.unreadSearchLatch != null) {
|
||||
this.unreadSearchLatch.countDown();
|
||||
}
|
||||
ReadingItemFragment fragment = getReadingFragment();
|
||||
if (fragment != null ) {
|
||||
fragment.updateStory(readingAdapter.getStory(pager.getCurrentItem()));
|
||||
fragment.updateSaveButton();
|
||||
|
||||
updateOverlayNav();
|
||||
updateOverlayText();
|
||||
}
|
||||
} catch (IllegalStateException ise) {
|
||||
// sometimes the pager is already shutting down by the time the callback finishes
|
||||
finish();
|
||||
}
|
||||
|
||||
checkStoryCount(pager.getCurrentItem());
|
||||
if (this.unreadSearchLatch != null) {
|
||||
this.unreadSearchLatch.countDown();
|
||||
}
|
||||
updateOverlayNav();
|
||||
updateOverlayText();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,7 +321,6 @@ public abstract class Reading extends NbActivity implements OnPageChangeListener
|
|||
protected void handleUpdate() {
|
||||
enableMainProgress(NBSyncService.isFeedSetSyncing(this.fs));
|
||||
updateCursor();
|
||||
readingAdapter.updateAllFragments();
|
||||
}
|
||||
|
||||
private void updateCursor() {
|
||||
|
|
|
@ -108,12 +108,18 @@ public abstract class ReadingAdapter extends FragmentStatePagerAdapter {
|
|||
return frag.get();
|
||||
}
|
||||
|
||||
public void updateAllFragments() {
|
||||
for (int i=0; i<cachedFragments.size(); i++) {
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
super.notifyDataSetChanged();
|
||||
|
||||
// go one step further than the default pageradapter and also refresh the
|
||||
// story object inside each fragment we have active
|
||||
for (int i=0; i<stories.getCount(); i++) {
|
||||
WeakReference<ReadingItemFragment> frag = cachedFragments.get(i);
|
||||
if (frag == null) continue;
|
||||
ReadingItemFragment rif = frag.get();
|
||||
if (rif == null) continue;
|
||||
rif.offerStoryUpdate(getStory(i));
|
||||
rif.handleUpdate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -298,17 +298,29 @@ public class BlurDatabaseHelper {
|
|||
}
|
||||
|
||||
public void setStoryReadState(String hash, boolean read) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(DatabaseConstants.STORY_READ, read);
|
||||
values.put(DatabaseConstants.STORY_READ_THIS_SESSION, read);
|
||||
synchronized (RW_MUTEX) {dbRW.update(DatabaseConstants.STORY_TABLE, values, DatabaseConstants.STORY_HASH + " = ?", new String[]{hash});}
|
||||
Cursor c = getStory(hash);
|
||||
if (c.getCount() < 1) {
|
||||
Log.w(this.getClass().getName(), "story removed before finishing mark-read");
|
||||
return;
|
||||
}
|
||||
Story story = Story.fromCursor(c);
|
||||
if (story == null) {
|
||||
Log.w(this.getClass().getName(), "story removed before finishing mark-read");
|
||||
return;
|
||||
}
|
||||
setStoryReadState(story, read);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a story (un)read and also adjusts unread counts for it.
|
||||
*/
|
||||
public void setStoryReadState(Story story, boolean read) {
|
||||
setStoryReadState(story.storyHash, read);
|
||||
// read flag
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(DatabaseConstants.STORY_READ, read);
|
||||
values.put(DatabaseConstants.STORY_READ_THIS_SESSION, read);
|
||||
synchronized (RW_MUTEX) {dbRW.update(DatabaseConstants.STORY_TABLE, values, DatabaseConstants.STORY_HASH + " = ?", new String[]{story.storyHash});}
|
||||
// non-social feed count
|
||||
refreshFeedCounts(FeedSet.singleFeed(story.feedId));
|
||||
// social feed counts
|
||||
|
|
|
@ -276,22 +276,13 @@ public class ReadingItemFragment extends NbFragment implements ClassifierDialogF
|
|||
});
|
||||
}
|
||||
|
||||
public void updateSaveButton() {
|
||||
private void updateSaveButton() {
|
||||
if (view == null) { return; }
|
||||
Button saveButton = (Button) view.findViewById(R.id.save_story_button);
|
||||
if (saveButton == null) { return; }
|
||||
saveButton.setText(story.starred ? R.string.unsave_this : R.string.save_this);
|
||||
}
|
||||
|
||||
public void updateStory(Story story) {
|
||||
if (story != null ) {
|
||||
this.story = story;
|
||||
if (selectedFeedView == DefaultFeedView.TEXT && originalText == null) {
|
||||
loadOriginalText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupShareButton() {
|
||||
Button shareButton = (Button) view.findViewById(R.id.share_story_button);
|
||||
|
||||
|
@ -450,7 +441,19 @@ public class ReadingItemFragment extends NbFragment implements ClassifierDialogF
|
|||
((Reading) parent).enableLeftProgressCircle(loading);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets the pager offer us an updated version of our story when a new cursor is
|
||||
* cycled in. This class takes the responsibility of ensureing that the cursor
|
||||
* index has not shifted, though, by checking story IDs.
|
||||
*/
|
||||
public void offerStoryUpdate(Story story) {
|
||||
if (story == null) return;
|
||||
if (! TextUtils.equals(story.storyHash, this.story.storyHash)) return;
|
||||
this.story = story;
|
||||
}
|
||||
|
||||
public void handleUpdate() {
|
||||
updateSaveButton();
|
||||
reloadStoryContent();
|
||||
}
|
||||
|
||||
|
|
192
media/css/vendor/highlight.css
vendored
192
media/css/vendor/highlight.css
vendored
|
@ -2,161 +2,135 @@
|
|||
Docco style used in http://jashkenas.github.com/docco/ converted by Simon Madine (@thingsinjars)
|
||||
*/
|
||||
|
||||
pre, code {
|
||||
background: #F4F6F2;
|
||||
padding: 0.15em 0.35em;
|
||||
}
|
||||
pre {
|
||||
padding: 0.5em;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #000;
|
||||
background: #F4F6F2;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
pre .comment,
|
||||
pre .template_comment,
|
||||
pre .diff .header,
|
||||
pre .javadoc {
|
||||
.hljs-comment,
|
||||
.hljs-template_comment,
|
||||
.diff .hljs-header,
|
||||
.hljs-javadoc {
|
||||
color: #408080;
|
||||
font-style: italic
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
pre .keyword,
|
||||
pre .assignment,
|
||||
pre .literal,
|
||||
pre .css .rule .keyword,
|
||||
pre .winutils,
|
||||
pre .javascript .title,
|
||||
pre .lisp .title,
|
||||
pre .subst {
|
||||
.hljs-keyword,
|
||||
.assignment,
|
||||
.hljs-literal,
|
||||
.css .rule .hljs-keyword,
|
||||
.hljs-winutils,
|
||||
.javascript .hljs-title,
|
||||
.lisp .hljs-title,
|
||||
.hljs-subst {
|
||||
color: #954121;
|
||||
}
|
||||
|
||||
pre .number,
|
||||
pre .hexcolor {
|
||||
color: #40a070
|
||||
.hljs-number,
|
||||
.hljs-hexcolor {
|
||||
color: #40a070;
|
||||
}
|
||||
|
||||
pre .string,
|
||||
pre .tag .value,
|
||||
pre .phpdoc,
|
||||
pre .tex .formula {
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-phpdoc,
|
||||
.hljs-dartdoc,
|
||||
.tex .hljs-formula {
|
||||
color: #219161;
|
||||
}
|
||||
|
||||
pre .title,
|
||||
pre .id {
|
||||
color: #19469D;
|
||||
.hljs-title,
|
||||
.hljs-id {
|
||||
color: #19469d;
|
||||
}
|
||||
pre .params {
|
||||
color: #00F;
|
||||
.hljs-params {
|
||||
color: #00f;
|
||||
}
|
||||
|
||||
pre .javascript .title,
|
||||
pre .lisp .title,
|
||||
pre .subst {
|
||||
font-weight: normal
|
||||
.javascript .hljs-title,
|
||||
.lisp .hljs-title,
|
||||
.hljs-subst {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
pre .class .title,
|
||||
pre .haskell .label,
|
||||
pre .tex .command {
|
||||
.hljs-class .hljs-title,
|
||||
.haskell .hljs-label,
|
||||
.tex .hljs-command {
|
||||
color: #458;
|
||||
font-weight: bold
|
||||
}
|
||||
|
||||
pre .tag,
|
||||
pre .tag .title,
|
||||
pre .rules .property,
|
||||
pre .django .tag .keyword {
|
||||
color: #000080;
|
||||
}
|
||||
|
||||
|
||||
pre .keyword,
|
||||
pre .id,
|
||||
pre .title,
|
||||
pre .built_in,
|
||||
pre .aggregate,
|
||||
pre .css .tag,
|
||||
pre .javadoctag,
|
||||
pre .phpdoc,
|
||||
pre .yardoctag,
|
||||
pre .smalltalk .class,
|
||||
pre .winutils,
|
||||
pre .bash .variable,
|
||||
pre .apache .tag,
|
||||
pre .go .typename,
|
||||
pre .tex .command,
|
||||
pre .asciidoc .strong,
|
||||
pre .markdown .strong,
|
||||
pre .request,
|
||||
pre .status {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre .attribute,
|
||||
pre .variable,
|
||||
pre .instancevar,
|
||||
pre .lisp .body {
|
||||
color: #008080
|
||||
.hljs-tag,
|
||||
.hljs-tag .hljs-title,
|
||||
.hljs-rules .hljs-property,
|
||||
.django .hljs-tag .hljs-keyword {
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
pre .regexp {
|
||||
color: #B68
|
||||
.hljs-attribute,
|
||||
.hljs-variable,
|
||||
.instancevar,
|
||||
.lisp .hljs-body {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
pre .class {
|
||||
.hljs-regexp {
|
||||
color: #b68;
|
||||
}
|
||||
|
||||
.hljs-class {
|
||||
color: #458;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre .symbol,
|
||||
pre .ruby .symbol .string,
|
||||
pre .ruby .symbol .keyword,
|
||||
pre .ruby .symbol .keymethods,
|
||||
pre .lisp .keyword,
|
||||
pre .tex .special,
|
||||
pre .input_number {
|
||||
color: #990073
|
||||
.hljs-symbol,
|
||||
.ruby .hljs-symbol .hljs-string,
|
||||
.ruby .hljs-symbol .hljs-keyword,
|
||||
.ruby .hljs-symbol .keymethods,
|
||||
.lisp .hljs-keyword,
|
||||
.tex .hljs-special,
|
||||
.input_number {
|
||||
color: #990073;
|
||||
}
|
||||
|
||||
pre .builtin,
|
||||
pre .constructor,
|
||||
pre .built_in,
|
||||
pre .lisp .title {
|
||||
color: #0086b3
|
||||
.builtin,
|
||||
.constructor,
|
||||
.hljs-built_in,
|
||||
.lisp .hljs-title {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
pre .preprocessor,
|
||||
pre .pragma,
|
||||
pre .pi,
|
||||
pre .doctype,
|
||||
pre .shebang,
|
||||
pre .cdata {
|
||||
.hljs-preprocessor,
|
||||
.hljs-pragma,
|
||||
.hljs-pi,
|
||||
.hljs-doctype,
|
||||
.hljs-shebang,
|
||||
.hljs-cdata {
|
||||
color: #999;
|
||||
font-weight: bold
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre .deletion {
|
||||
background: #fdd
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
pre .addition {
|
||||
background: #dfd
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
}
|
||||
|
||||
pre .diff .change {
|
||||
background: #0086b3
|
||||
.diff .hljs-change {
|
||||
background: #0086b3;
|
||||
}
|
||||
|
||||
pre .chunk {
|
||||
color: #aaa
|
||||
.hljs-chunk {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
pre .tex .formula {
|
||||
.tex .hljs-formula {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
|
@ -566,6 +566,7 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
|||
|
||||
attach_syntax_highlighter_handler: function() {
|
||||
_.delay(_.bind(function() {
|
||||
// hljs.configure({useBR: true}); // Don't use
|
||||
this.$('pre').each(function(i, e) {
|
||||
hljs.highlightBlock(e);
|
||||
});
|
||||
|
|
2
media/js/vendor/highlight.js
vendored
2
media/js/vendor/highlight.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue