diff --git a/README.md b/README.md
index b51f082..64d0c1e 100644
--- a/README.md
+++ b/README.md
@@ -96,7 +96,7 @@ Instead, the web interface can be locked behind a password set via `intake passw
Parity features
-* [ ] web feed supports item TTS
+* [x] web feed supports item TTS
* [ ] item punt
* [ ] web feed paging
* [ ] web fetch
diff --git a/core/item.go b/core/item.go
index b8231fe..50896b4 100644
--- a/core/item.go
+++ b/core/item.go
@@ -46,6 +46,11 @@ func (item Item) TtsTime() time.Time {
return time.Unix(int64(item.Created)+int64(item.Tts), 0)
}
+func (item Item) Visible() bool {
+ now := time.Now() // TODO pass this value in
+ return item.Active && now.After(item.TtsTime())
+}
+
// Whether an item that no longer appears in a fetch can be deleted.
func (item Item) Deletable(now time.Time) bool {
if item.Ttl != 0 && item.TtlTime().After(now) {
diff --git a/core/items.go b/core/items.go
index 9251e34..c99bfe1 100644
--- a/core/items.go
+++ b/core/items.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "time"
_ "github.com/mattn/go-sqlite3"
)
@@ -211,6 +212,7 @@ func GetAllItems(db DB) ([]Item, error) {
}
func GetActiveItemsForSource(db DB, source string) ([]Item, error) {
+ now := int(time.Now().Unix()) // TODO pass this value in
return getItems(db, `
select
source, id, created, active, title, author, body, link, time, ttl, ttd, tts, json(action)
@@ -218,8 +220,9 @@ func GetActiveItemsForSource(db DB, source string) ([]Item, error) {
where
source = ?
and active <> 0
+ and created + tts < ?
order by case when time = 0 then created else time end, id
- `, source)
+ `, source, now)
}
func GetAllItemsForSource(db DB, source string) ([]Item, error) {
@@ -234,6 +237,7 @@ func GetAllItemsForSource(db DB, source string) ([]Item, error) {
}
func GetActiveItemsForChannel(db DB, channel string) ([]Item, error) {
+ now := int(time.Now().Unix()) // TODO pass this value in
return getItems(db, `
select
i.source, i.id, i.created, i.active, i.title, i.author, i.body, i.link, i.time, i.ttl, i.ttd, i.tts, json(i.action)
@@ -242,8 +246,9 @@ func GetActiveItemsForChannel(db DB, channel string) ([]Item, error) {
where
c.name = ?
and i.active <> 0
+ and i.created + i.tts < ?
order by case when i.time = 0 then i.created else i.time end, i.id
- `, channel)
+ `, channel, now)
}
func GetAllItemsForChannel(db DB, channel string) ([]Item, error) {
diff --git a/test/test_items.sh b/test/test_items.sh
index 88aff4e..e647712 100755
--- a/test/test_items.sh
+++ b/test/test_items.sh
@@ -8,22 +8,23 @@ tmp/intake migrate
tmp/intake source add -s feedtest
tmp/intake item add -s feedtest --id "this-item-has-no-title"
-tmp/intake item add -s feedtest --title "This item has only a title"
-tmp/intake item add -s feedtest --title "Title and body" --body "This is the item body"
-tmp/intake item add -s feedtest --title "Title and link" --link "#"
-tmp/intake item add -s feedtest --title "Title, link, body" --link "#" --body "This is the body"
-tmp/intake item add -s feedtest --title "HTML title" --link "#" --body "HTML body"
-tmp/intake item add -s feedtest --title "Title and author" --author "Authorname"
-tmp/intake item add -s feedtest --title "Title, author, time" --author "Authorname" --time 1700000000
-tmp/intake item add -s feedtest --title "Title, time" --time 1737780324
-tmp/intake item add -s feedtest --title "Title, author, body" --author "Authorname" --body "Hello body!"
-tmp/intake item add -s feedtest --title "Title, author, time, body" --author "Authorname" --time 1700000000 --body "Hello body!"
-tmp/intake item add -s feedtest --title "Title, time, body" --time 1737780324 --body "Hello, body!"
-tmp/intake item add -s feedtest --title "TTL 30s" --ttl 30
-tmp/intake item add -s feedtest --title "TTL 10d" --ttl 864000
-tmp/intake item add -s feedtest --title "TTD 30s" --ttd 30
-tmp/intake item add -s feedtest --title "TTS 30s" --tts 30
-tmp/intake item add -s feedtest --title "TTS -10d" --tts "-864000"
+tmp/intake item add -s feedtest --id a --title "This item has only a title"
+tmp/intake item add -s feedtest --id b --title "Title and body" --body "This is the item body"
+tmp/intake item add -s feedtest --id c --title "Title and link" --link "#"
+tmp/intake item add -s feedtest --id d --title "Title, link, body" --link "#" --body "This is the body"
+tmp/intake item add -s feedtest --id e --title "HTML title" --link "#" --body "HTML body"
+tmp/intake item add -s feedtest --id f --title "Title and author" --author "Authorname"
+tmp/intake item add -s feedtest --id g --title "Title, author, time" --author "Authorname" --time 1700000000
+tmp/intake item add -s feedtest --id h --title "Title, time" --time 1737780324
+tmp/intake item add -s feedtest --id i --title "Title, author, body" --author "Authorname" --body "Hello body!"
+tmp/intake item add -s feedtest --id j --title "Title, author, time, body" --author "Authorname" --time 1700000000 --body "Hello body!"
+tmp/intake item add -s feedtest --id k --title "Title, time, body" --time 1737780324 --body "Hello, body!"
+tmp/intake item add -s feedtest --id l --title "TTL 30s" --ttl 30
+tmp/intake item add -s feedtest --id m --title "TTL 10d" --ttl 864000
+tmp/intake item add -s feedtest --id n --title "TTD 30s" --ttd 30
+tmp/intake item add -s feedtest --id o --title "TTS 30s" --tts 30
+tmp/intake item add -s feedtest --id p --title "TTS 10d" --tts 864000
+tmp/intake item add -s feedtest --id q --title "TTS -10d" --tts "-864000"
tmp/intake source add -s spook
tmp/intake action add -s spook -a spookier -- jq -c '.title = .title + "o"'
diff --git a/web/html/html.go b/web/html/html.go
index 72bf212..8a434e3 100644
--- a/web/html/html.go
+++ b/web/html/html.go
@@ -25,7 +25,8 @@ func tsToDate(t int) time.Time {
}
func until(tm time.Time) string {
- dur := time.Until(tm).Round(time.Second)
+ now := time.Now() // TODO pass this value in
+ dur := tm.Sub(now).Round(time.Second)
var format string
if dur < 0 {
diff --git a/web/html/item.html b/web/html/item.html
index 7a7301e..248339b 100644
--- a/web/html/item.html
+++ b/web/html/item.html
@@ -28,7 +28,7 @@
{{ or .Title .Id | raw }}
{{- end }}
-{{ define "item-class" -}}{{ if not .Active }}strikethru {{ end }}{{ if not .Active }}fade{{ end }}{{- end}}
+{{ define "item-class" -}}{{ if not .Active }}strikethru {{ end }}{{ if not .Visible }}fade{{ end }}{{- end}}
{{ define "item" -}}