Show what pages watched threads are on. #1030

This commit is contained in:
ccd0 2019-04-04 17:36:01 -07:00
parent ccf3692944
commit 574d1ad0d3
10 changed files with 78 additions and 30 deletions

View File

@ -160,7 +160,7 @@ ThreadWatcher =
else if ThreadWatcher.unreadEnabled and Conf['Show Unread Count'] else if ThreadWatcher.unreadEnabled and Conf['Show Unread Count']
ThreadWatcher.fetchStatus {siteID, boardID, threadID, data} ThreadWatcher.fetchStatus {siteID, boardID, threadID, data}
else else
db.extend {boardID, threadID, val: {isDead: true}} db.extend {boardID, threadID, val: {isDead: true, page: undefined, lastPage: undefined, unread: undefined, quotingYou: undefined}}
nKilled++ nKilled++
ThreadWatcher.refresh() if nKilled ThreadWatcher.refresh() if nKilled
onThreadRefresh: (e) -> onThreadRefresh: (e) ->
@ -224,7 +224,7 @@ ThreadWatcher =
clearTimeout ThreadWatcher.timeout clearTimeout ThreadWatcher.timeout
return unless Conf['Auto Update Thread Watcher'] return unless Conf['Auto Update Thread Watcher']
{db} = ThreadWatcher {db} = ThreadWatcher
interval = if ThreadWatcher.unreadEnabled and Conf['Show Unread Count'] then 5 * $.MINUTE else 2 * $.HOUR interval = if Conf['Show Page'] or (ThreadWatcher.unreadEnabled and Conf['Show Unread Count']) then 5 * $.MINUTE else 2 * $.HOUR
now = Date.now() now = Date.now()
unless now - interval < (db.data.lastChecked or 0) <= now or d.hidden or not d.hasFocus() unless now - interval < (db.data.lastChecked or 0) <= now or d.hidden or not d.hasFocus()
ThreadWatcher.fetchAllStatus() ThreadWatcher.fetchAllStatus()
@ -254,40 +254,65 @@ ThreadWatcher =
deep = !(now - 2 * $.HOUR < (db.data.lastChecked2 or 0) <= now) deep = !(now - 2 * $.HOUR < (db.data.lastChecked2 or 0) <= now)
boards = ThreadWatcher.getAll(true) boards = ThreadWatcher.getAll(true)
for board in boards for board in boards
ThreadWatcher.fetchBoard board, deep ThreadWatcher.fetchBoard board, false, deep
db.setLastChecked() db.setLastChecked()
db.setLastChecked('lastChecked2') if deep db.setLastChecked('lastChecked2') if deep
if ThreadWatcher.fetched is ThreadWatcher.requests.length if ThreadWatcher.fetched is ThreadWatcher.requests.length
ThreadWatcher.clearRequests() ThreadWatcher.clearRequests()
fetchBoard: (board, deep) -> fetchBoard: (board, force, deep) ->
return unless board.some (thread) -> !thread.data.isDead return unless board.some (thread) -> !thread.data.isDead
{siteID, boardID} = board[0] {siteID, boardID} = board[0]
software = Conf['siteProperties'][siteID]?.software software = Conf['siteProperties'][siteID]?.software
urlF = if deep and software is 'tinyboard' then 'catalogJSON' else 'threadsListJSON' urlF = if deep and software is 'tinyboard' then 'catalogJSON' else 'threadsListJSON'
url = SW[software]?.urls[urlF]?({siteID, boardID}) url = SW[software]?.urls[urlF]?({siteID, boardID})
return unless url return unless url
ThreadWatcher.fetch url, {siteID}, [board, url], ThreadWatcher.parseBoard ThreadWatcher.fetch url, {siteID, force}, [board, url], ThreadWatcher.parseBoard
parseBoard: (board, url) -> parseBoard: (board, url) ->
return unless @status is 200 return unless @status is 200
{siteID, boardID} = board[0] {siteID, boardID} = board[0]
software = Conf['siteProperties'][siteID]?.software
lmDate = @getResponseHeader('Last-Modified') lmDate = @getResponseHeader('Last-Modified')
ThreadWatcher.dbLM.extend {siteID, boardID, val: $.item(url, lmDate)} ThreadWatcher.dbLM.extend {siteID, boardID, val: $.item(url, lmDate)}
modified = {} threads = {}
replies = {} pageLength = 0
nThreads = 0
oldest = null
try try
for page in @response pageLength = @response[0]?.threads.length or 0
for page, i in @response
for item in page.threads for item in page.threads
modified[item.no] = item.last_modified threads[item.no] =
replies[item.no] = item.replies page: i + 1
index: nThreads
modified: item.last_modified
replies: item.replies
nThreads++
if !oldest? or item.no < oldest
oldest = item.no
catch
for thread in board
ThreadWatcher.fetchStatus thread
for thread in board for thread in board
{threadID, data} = thread {threadID, data} = thread
if modified[threadID] if threads[threadID]
if modified[threadID] is data.modified and (!replies[threadID]? or replies[threadID] is data.replies) {page, index, modified, replies} = threads[threadID]
continue if Conf['Show Page']
ThreadWatcher.db.extend {siteID, boardID, threadID, val: {modified: modified[threadID]}} lastPage = if SW[software]?.isPrunedByAge?({siteID, boardID})
ThreadWatcher.fetchStatus thread threadID is oldest
else
index >= nThreads - pageLength
ThreadWatcher.update siteID, boardID, threadID, {page, lastPage}
if ThreadWatcher.unreadEnabled and Conf['Show Unread Count']
if modified isnt data.modified or (replies? and replies isnt data.replies)
ThreadWatcher.db.extend {siteID, boardID, threadID, val: {modified}}
ThreadWatcher.fetchStatus thread
else
if ThreadWatcher.unreadEnabled and Conf['Show Unread Count']
ThreadWatcher.fetchStatus thread
else
ThreadWatcher.update siteID, boardID, threadID, {isDead: true}
return return
fetchStatus: (thread, force) -> fetchStatus: (thread, force) ->
@ -348,9 +373,9 @@ ThreadWatcher =
else if @status is 404 else if @status is 404
if SW[software].mayLackJSON and !data.last? if SW[software].mayLackJSON and !data.last?
ThreadWatcher.update siteID, boardID, threadID, {last: -1, unread: undefined, quotingYou: undefined} ThreadWatcher.update siteID, boardID, threadID, {last: -1}
else else
ThreadWatcher.update siteID, boardID, threadID, {isDead: true, unread: undefined, quotingYou: undefined} ThreadWatcher.update siteID, boardID, threadID, {isDead: true}
getAll: (groupByBoard) -> getAll: (groupByBoard) ->
all = [] all = []
@ -381,6 +406,12 @@ ThreadWatcher =
title: excerpt title: excerpt
className: 'watcher-link' className: 'watcher-link'
if Conf['Show Page'] and data.page?
page = $.el 'span',
textContent: "[#{data.page}]"
className: 'watcher-page'
$.add link, page
if ThreadWatcher.unreadEnabled and Conf['Show Unread Count'] and data.unread? if ThreadWatcher.unreadEnabled and Conf['Show Unread Count'] and data.unread?
count = $.el 'span', count = $.el 'span',
textContent: "(#{data.unread})" textContent: "(#{data.unread})"
@ -398,6 +429,9 @@ ThreadWatcher =
div.dataset.siteID = siteID div.dataset.siteID = siteID
$.addClass div, 'current' if g.VIEW is 'thread' and fullID is "#{g.BOARD}.#{g.THREADID}" $.addClass div, 'current' if g.VIEW is 'thread' and fullID is "#{g.BOARD}.#{g.THREADID}"
$.addClass div, 'dead-thread' if data.isDead $.addClass div, 'dead-thread' if data.isDead
if Conf['Show Page']
$.addClass div, 'last-page' if data.lastPage
div.dataset.page = data.page if data.page?
if ThreadWatcher.unreadEnabled and Conf['Show Unread Count'] if ThreadWatcher.unreadEnabled and Conf['Show Unread Count']
$.addClass div, 'replies-read' if data.unread is 0 $.addClass div, 'replies-read' if data.unread is 0
$.addClass div, 'replies-unread' if data.unread $.addClass div, 'replies-unread' if data.unread
@ -467,6 +501,9 @@ ThreadWatcher =
if newData.isDead and Conf['Auto Prune'] if newData.isDead and Conf['Auto Prune']
ThreadWatcher.rm siteID, boardID, threadID ThreadWatcher.rm siteID, boardID, threadID
return return
if newData.isDead or newData.last is -1
for key in ['page', 'lastPage', 'unread', 'quotingyou'] when key not of newData
newData[key] = undefined
n = 0 n = 0
n++ for key, val of newData when data[key] isnt val n++ for key, val of newData when data[key] isnt val
return unless n return unless n
@ -483,8 +520,8 @@ ThreadWatcher =
if Conf['Auto Prune'] if Conf['Auto Prune']
ThreadWatcher.db.delete {boardID, threadID} ThreadWatcher.db.delete {boardID, threadID}
return cb() return cb()
return cb() if data.isDead and not (data.unread? or data.quotingYou?) return cb() if data.isDead and not (data.page? or data.lastPage? or data.unread? or data.quotingYou?)
ThreadWatcher.db.extend {boardID, threadID, val: {isDead: true, unread: undefined, quotingYou: undefined}}, cb ThreadWatcher.db.extend {boardID, threadID, val: {isDead: true, page: undefined, lastPage: undefined, unread: undefined, quotingYou: undefined}}, cb
toggle: (thread) -> toggle: (thread) ->
siteID = Site.hostname siteID = Site.hostname
@ -511,8 +548,11 @@ ThreadWatcher =
addRaw: (boardID, threadID, data) -> addRaw: (boardID, threadID, data) ->
ThreadWatcher.db.set {boardID, threadID, val: data} ThreadWatcher.db.set {boardID, threadID, val: data}
ThreadWatcher.refresh() ThreadWatcher.refresh()
if ThreadWatcher.unreadEnabled and Conf['Show Unread Count'] thread = {siteID: Site.hostname, boardID, threadID, data}
ThreadWatcher.fetchStatus {siteID: Site.hostname, boardID, threadID, data}, true if Conf['Show Page'] and !data.isDead
ThreadWatcher.fetchBoard [thread], true
else if ThreadWatcher.unreadEnabled and Conf['Show Unread Count']
ThreadWatcher.fetchStatus thread, true
rm: (siteID, boardID, threadID) -> rm: (siteID, boardID, threadID) ->
ThreadWatcher.db.delete {siteID, boardID, threadID} ThreadWatcher.db.delete {siteID, boardID, threadID}
@ -589,6 +629,6 @@ ThreadWatcher =
$.addClass entry.el, 'disabled' $.addClass entry.el, 'disabled'
entry.el.title += '\n[Remember Last Read Post is disabled.]' entry.el.title += '\n[Remember Last Read Post is disabled.]'
$.on input, 'change', $.cb.checked $.on input, 'change', $.cb.checked
$.on input, 'change', ThreadWatcher.refresh if name in ['Current Board', 'Show Unread Count', 'Show Site Prefix'] $.on input, 'change', ThreadWatcher.refresh if name in ['Current Board', 'Show Page', 'Show Unread Count', 'Show Site Prefix']
$.on input, 'change', ThreadWatcher.fetchAuto if name in ['Show Unread Count', 'Auto Update Thread Watcher'] $.on input, 'change', ThreadWatcher.fetchAuto if name in ['Show Page', 'Show Unread Count', 'Auto Update Thread Watcher']
@menu.addEntry entry @menu.addEntry entry

View File

@ -676,6 +676,10 @@ Config =
false false
'Automatically remove dead threads.' 'Automatically remove dead threads.'
] ]
'Show Page': [
true
'Show what page watched threads are on.'
]
'Show Unread Count': [ 'Show Unread Count': [
true true
'Show number of unread posts in watched threads.' 'Show number of unread posts in watched threads.'

View File

@ -93,7 +93,7 @@
} }
/* Thread Watcher */ /* Thread Watcher */
:root.burichan .replies-quoting-you > a, :root.burichan #watcher-link.replies-quoting-you { :root.burichan .replies-quoting-you > a, :root.burichan #watcher-link.replies-quoting-you, :root.burichan .last-page > a > .watcher-page {
color: #F00; color: #F00;
} }

View File

@ -93,7 +93,7 @@
} }
/* Thread Watcher */ /* Thread Watcher */
:root.futaba .replies-quoting-you > a, :root.futaba #watcher-link.replies-quoting-you { :root.futaba .replies-quoting-you > a, :root.futaba #watcher-link.replies-quoting-you, :root.futaba .last-page > a > .watcher-page {
color: #F00; color: #F00;
} }

View File

@ -91,7 +91,7 @@
} }
/* Thread Watcher */ /* Thread Watcher */
:root.photon .replies-quoting-you > a, :root.photon #watcher-link.replies-quoting-you { :root.photon .replies-quoting-you > a, :root.photon #watcher-link.replies-quoting-you, :root.photon .last-page > a > .watcher-page {
color: #00F !important; color: #00F !important;
} }

View File

@ -157,7 +157,7 @@
} }
/* Thread Watcher */ /* Thread Watcher */
:root.spooky .replies-quoting-you > a, :root.spooky #watcher-link.replies-quoting-you { :root.spooky .replies-quoting-you > a, :root.spooky #watcher-link.replies-quoting-you, :root.spooky .last-page > a > .watcher-page {
color: #F00 !important; color: #F00 !important;
} }

View File

@ -1168,10 +1168,12 @@ span.hide-announcement {
-webkit-flex-direction: row; -webkit-flex-direction: row;
flex-direction: row; flex-direction: row;
} }
#watched-threads .watcher-page,
#watched-threads .watcher-unread { #watched-threads .watcher-unread {
-webkit-flex: 0 0 auto; -webkit-flex: 0 0 auto;
flex: 0 0 auto; flex: 0 0 auto;
} }
#watched-threads .watcher-page::after,
#watched-threads .watcher-unread::after { #watched-threads .watcher-unread::after {
content: "\00a0"; content: "\00a0";
} }
@ -1181,7 +1183,7 @@ span.hide-announcement {
-webkit-flex: 0 1 auto; -webkit-flex: 0 1 auto;
flex: 0 1 auto; flex: 0 1 auto;
} }
.replies-quoting-you > a, #watcher-link.replies-quoting-you { .replies-quoting-you > a, #watcher-link.replies-quoting-you, .last-page > a > .watcher-page {
color: #F00; color: #F00;
} }
#thread-watcher a { #thread-watcher a {

View File

@ -162,7 +162,7 @@
} }
/* Thread Watcher */ /* Thread Watcher */
:root.tomorrow .replies-quoting-you > a, :root.tomorrow #watcher-link.replies-quoting-you { :root.tomorrow .replies-quoting-you > a, :root.tomorrow #watcher-link.replies-quoting-you, :root.tomorrow .last-page > a > .watcher-page {
color: #F00 !important; color: #F00 !important;
} }

View File

@ -88,7 +88,7 @@
} }
/* Thread Watcher */ /* Thread Watcher */
:root.yotsuba .replies-quoting-you > a, :root.yotsuba #watcher-link.replies-quoting-you { :root.yotsuba .replies-quoting-you > a, :root.yotsuba #watcher-link.replies-quoting-you, :root.yotsuba .last-page > a > .watcher-page {
color: #F00; color: #F00;
} }

View File

@ -8,6 +8,8 @@ SW.yotsuba =
archiveListJSON: ({boardID}) -> if BoardConfig.isArchived(boardID) then "#{location.protocol}//a.4cdn.org/#{boardID}/archive.json" else '' archiveListJSON: ({boardID}) -> if BoardConfig.isArchived(boardID) then "#{location.protocol}//a.4cdn.org/#{boardID}/archive.json" else ''
catalogJSON: ({boardID}) -> "#{location.protocol}//a.4cdn.org/#{boardID}/catalog.json" catalogJSON: ({boardID}) -> "#{location.protocol}//a.4cdn.org/#{boardID}/catalog.json"
isPrunedByAge: ({boardID}) -> boardID is 'f'
selectors: selectors:
board: '.board' board: '.board'
thread: '.thread' thread: '.thread'