Skip to content

Commit

Permalink
Ok, hiding retweets. Closes #104.
Browse files Browse the repository at this point in the history
  • Loading branch information
kickscondor committed Mar 19, 2020
1 parent ff9de82 commit 447b5b6
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 23 deletions.
49 changes: 49 additions & 0 deletions src/js/frago.js
Expand Up @@ -4,6 +4,55 @@
// circumvent web extension file size quotas).
//
module.exports = {
//
// Compare two 'post' objects
//
cmp(follow, a, b, sortPosts, showReposts) {
if (!showReposts) {
if (!b.author || b.author === follow.author) {
if (a.author && a.author !== follow.author)
return 1
}
}
return b[sortPosts] > a[sortPosts] ? 1 : -1
},

//
// Sort a feed using the above sort function.
//
sort(follow, settings) {
let sortPosts = settings['mode-updates'] || 'publishedAt'
let showReposts = settings['mode-reposts'] === 'all'
let sortedBy = [sortPosts, showReposts].join(',')
if (follow.sortedBy !== sortedBy) {
follow.sortedBy = sortedBy
follow.posts.sort((a, b) =>
this.cmp(follow, a, b, sortPosts, showReposts))
}
},

//
// Build a truncated master index of various sorts.
//
master(follow, sortFields, limit) {
let posts = follow.posts.slice(0, limit)
if (posts.length > 0) {
for (let sortField of sortFields) {
for (let reposts of [true, false]) {
let sb = [sortField, reposts].join(',')
if (follow.sortedBy !== sb) {
let add = follow.posts.concat().sort((a, b) =>
this.cmp(follow, a, b, sortField, reposts)).
slice(0, limit)
posts = posts.concat(add)
}
}
}
posts = Array.from(new Set(posts))
}
return posts
},

//
// Merge separated objects back into a single object. The 'items' object is
// a dictionary with keys of the form 'follows/0', 'follows/1' ... 'follows/N'
Expand Down
16 changes: 7 additions & 9 deletions src/js/storage.js
Expand Up @@ -22,6 +22,7 @@ import u from '@kickscondor/umbrellajs'

const fraidyscrape = require('fraidyscrape')
const og = require('opml-generator')
const frago = require('./frago')
const url = require('url')

const SYNC_FULL = 1
Expand Down Expand Up @@ -329,8 +330,7 @@ module.exports = {
// Sort posts based on the settings.
//
Object.assign(meta, feed)
meta.sortedBy = sortedBy
meta.posts.sort((a, b) => b[sortedBy] > a[sortedBy] ? 1 : -1)
frago.sort(meta, this.settings)
}

feed.fresh = fresh
Expand Down Expand Up @@ -385,19 +385,17 @@ module.exports = {
follow.url = meta.url
follow.actualTitle = meta.title
follow.status = meta.status
follow.sortedBy = meta.sortedBy
follow.author = meta.author
if (meta.photos)
follow.photo = meta.photos['avatar'] || Object.values(meta.photos)[0]

//
// Add some posts from the other sort method, in case it is toggled.
// Select the top posts for every possible sort method, to give us a limited
// index of the posts that each filter method would select.
//
let sortOpposite = meta.sortedBy === 'publishedAt' ? 'updatedAt' : 'publishedAt'
let oppo = meta.posts.concat().sort((a, b) => b[sortOpposite] > a[sortOpposite] ? 1 : -1)
follow.posts = frago.master(meta, ['publishedAt', 'updatedAt'], POSTS_IN_MAIN_INDEX)
follow.sortedBy = meta.sortedBy
follow.limit = POSTS_IN_MAIN_INDEX
follow.posts = meta.posts.slice(0, POSTS_IN_MAIN_INDEX)
follow.posts = follow.posts.concat(oppo.slice(0, POSTS_IN_MAIN_INDEX).
filter(o => !follow.posts.includes(o)))

//
// Build the 'activity' array - most recent first, then trim
Expand Down
25 changes: 13 additions & 12 deletions src/js/view.js
Expand Up @@ -3,6 +3,7 @@ import { h } from 'hyperapp'
import { jsonDateParser } from "json-date-parser"
import { Link, Route, Switch } from '@kickscondor/router'
import EmojiButton from '@kickscondor/emoji-button'
const frago = require('./frago')
const url = require('url')
const sparkline = require('./sparkline')
import u from '@kickscondor/umbrellajs'
Expand Down Expand Up @@ -281,14 +282,12 @@ const ListFollow = ({ location, match }) => ({follows}, actions) => {
let tag = match.params.tag ? match.params.tag : house
let tags = {}, imps = {}
let sortPosts = follows.settings['mode-updates'] || 'publishedAt'
let showReposts = follows.settings['mode-reposts'] === 'all'
let viewable = Object.values(follows.all).filter(follow => {
let ftags = (follow.tags || [house])
let lastPost = null
if (follow.posts instanceof Array && follow.posts[0]) {
if (follow.sortedBy !== sortPosts) {
follow.sortedBy = sortPosts
follow.posts.sort((a, b) => b[sortPosts] > a[sortPosts] ? 1 : -1)
}
frago.sort(follow, follows.settings)
lastPost = follow.posts[0]
}
ftags.forEach(k => {
Expand Down Expand Up @@ -342,6 +341,7 @@ const ListFollow = ({ location, match }) => ({follows}, actions) => {
<li><Setting name="sort-follows" value="createdAt">Recently Followed</Setting></li>
<li class="sep"><Setting name="sort-follows" value="title">A to Z</Setting></li>
<li><Setting name="mode-updates" value="updatedAt">Show Post Updates</Setting></li>
<li><Setting name="mode-reposts" value="all">Show Reposts</Setting></li>
<li><Setting name="mode-expand" value="all">Expand All</Setting></li>
<li class="dark-mode"><Setting name="mode-theme" value="dark">Dark Mode</Setting></li>
<li class="light-mode"><Setting name="mode-theme" value="light">Light Mode</Setting></li>
Expand Down Expand Up @@ -386,14 +386,15 @@ const ListFollow = ({ location, match }) => ({follows}, actions) => {
</h3>
<div class={`extra ${follows.settings['mode-expand'] || "trunc"}`}>
<div class="post">{follow.posts instanceof Array &&
<ol class="title">{follow.posts.slice(0, follow.limit || 10).map(f => {
let postAge = timeAgo(f[sortPosts], now)
return <li class={timeDarkness(f[sortPosts], now)}>
{f.author && <span class="author">{f.author}</span>}
{follow.fetchesContent ? f.title : <a href={f.url}>{f.title}</a>}
<span class="ago">{timeAgo(f[sortPosts], now)}</span>
</li>
})}</ol>}
<ol class="title">{(showReposts ? follow.posts : follow.posts.filter(x => !x.author || x.author === follow.author)).
slice(0, follow.limit || 10).map(f => {
let postAge = timeAgo(f[sortPosts], now)
return <li class={timeDarkness(f[sortPosts], now)}>
{f.author && <span class="author">{f.author}</span>}
{follow.fetchesContent ? f.title : <a href={f.url}>{f.title}</a>}
<span class="ago">{timeAgo(f[sortPosts], now)}</span>
</li>
})}</ol>}
{!follow.fetchesContent && <a class="collapse" href="#"
onclick={e => ToggleShow(e, ".extra", "trunc")}>
<span class="enter">&#x2ba8;</span>
Expand Down
21 changes: 19 additions & 2 deletions test.js
Expand Up @@ -2,16 +2,18 @@ import test from 'ava'
const fs = require('fs')
const frago = require('./src/js/frago')

//
// 'frago' - piece merging tests
//
const syncParts = JSON.parse(fs.readFileSync('test/sync.json'))

test('basic merge on load', t => {
t.plan(6)
t.plan(5)
let sync = frago.merge(syncParts, 'follows')
t.deepEqual(sync.follows['blog.presentandcorrect.com-f29bc778'],
syncParts['follows/1']['blog.presentandcorrect.com-f29bc778'])
t.is(1, sync.index['blog.presentandcorrect.com-f29bc778'])
t.is(0, sync.index['warpdoor.com-3ae79d0c'])
t.is(1, sync.maxIndex)
t.is(61, Object.keys(sync.follows).length)
t.false(sync.settings.broadcast)
})
Expand Down Expand Up @@ -86,3 +88,18 @@ test('separation on deletions', async t => {
})
t.is(61, len)
})

//
// Utility function tests
//
const feed = JSON.parse(fs.readFileSync('test/electrolemon.json'))

test('sort by fields', t => {
t.plan(2)

frago.sort(feed, {'mode-updates': 'updatedAt'})
t.is(feed.posts.slice(0, 4).map(x => x.id).join(','),
'twitter.com-9dde7abc,twitter.com-cab7bde,twitter.com-10a61e13,twitter.com-95ad78d1')
let posts = frago.master(feed, ['publishedAt', 'updatedAt'], 10)
t.assert(posts.some(x => x.id === 'twitter.com-104e3097'))
})
1 change: 1 addition & 0 deletions test/electrolemon.json

Large diffs are not rendered by default.

0 comments on commit 447b5b6

Please sign in to comment.