Add Unread Line in Index option, combined with previous work on Mark Read button. #625

Also fix various bugs with the old implementation.
This commit is contained in:
ccd0 2018-10-20 22:43:34 -07:00
parent 96cae8339a
commit 481a775a80
13 changed files with 96 additions and 51 deletions

View File

@ -691,6 +691,10 @@ Index =
isHiddenReply: (threadID, replyData) ->
PostHiding.isHidden(g.BOARD.ID, threadID, replyData.no) or Filter.isHidden(Build.parseJSON replyData, g.BOARD.ID)
lastPost: (threadID) ->
threadData = Index.liveThreadDict[threadID]
if threadData?.last_replies then threadData.last_replies[threadData.last_replies.length - 1].no else threadID
buildThreads: (threadIDs, isCatalog, withReplies) ->
threads = []
newThreads = []
@ -713,7 +717,6 @@ Index =
thread = new Thread ID, g.BOARD
newThreads.push thread
thread.json = threadData
thread.lastPost = if threadData.last_replies then threadData.last_replies[threadData.last_replies.length - 1].no else ID
threads.push thread
if ((OP = thread.OP) and not OP.isFetchedQuote)
@ -741,7 +744,7 @@ Index =
Main.callbackNodes 'Thread', newThreads
Main.callbackNodes 'Post', newPosts
Index.updateHideLabel()
$.event 'IndexRefreshInternal'
$.event 'IndexRefreshInternal', {threadIDs: (t.fullID for t in threads), isCatalog}
threads

View File

@ -68,6 +68,8 @@ ExpandThread =
postsCount = 0
filesCount = 0
for reply in replies
# rm elements above post such as unread line
$.rm node while (node = a.nextSibling) and node isnt reply
# rm clones
inlined.click() while inlined = $ '.inlined', reply if Conf['Quote Inlining']
postsCount++

View File

@ -15,6 +15,7 @@ Unread =
@hr = $.el 'hr',
id: 'unread-line'
className: 'unread-line'
@posts = new Set()
@postsQuotingYou = new Set()
@order = new RandomAccessList()

View File

@ -1,69 +1,109 @@
UnreadIndex =
hasUnread: {}
lastReadPost: {}
hr: {}
markReadLink: {}
init: ->
return unless g.VIEW is 'index' and Conf['Remember Last Read Post'] and Conf['Mark Read from Index']
return unless g.VIEW is 'index' and Conf['Remember Last Read Post'] and Conf['Unread Line in Index']
@db = new DataBoard 'lastReadPosts', @sync
if Index.enabled
$.on d, 'IndexRefreshInternal',
@onIndexRefresh
else
Callbacks.Thread.push
name: 'Mark Read from Index'
cb: @node
Callbacks.Thread.push
name: 'Unread Line in Index'
cb: @node
Callbacks.Post.push
name: 'Mark Read from Index'
cb: @addPost
onIndexRefresh: ->
g.threads.forEach (thread) ->
UnreadIndex.addMarkReadLink thread
UnreadIndex.update thread
$.on d, 'IndexRefreshInternal', @onIndexRefresh
$.on d, 'PostsInserted', @onPostsInserted
node: ->
UnreadIndex.addMarkReadLink @
UnreadIndex.update @
UnreadIndex.lastReadPost[@fullID] = UnreadIndex.db.get(
boardID: @board.ID
threadID: @ID
) or 0
if !Index.enabled # let onIndexRefresh handle JSON Index
UnreadIndex.update @
addPost: ->
if @ID is @thread.lastPost
UnreadIndex.update @thread
onIndexRefresh: (e) ->
return if e.detail.isCatalog
for threadID in e.detail.threadIDs
thread = g.threads[threadID]
UnreadIndex.update thread
onPostsInserted: (e) ->
return if e.target is Index.root # onIndexRefresh handles this case
thread = Get.threadFromNode e.target
return if !thread or thread.nodes.root isnt e.target
UnreadIndex.update thread
sync: ->
g.threads.forEach UnreadIndex.update
g.threads.forEach (thread) ->
lastReadPost = UnreadIndex.db.get(
boardID: thread.board.ID
threadID: thread.ID
) or 0
if lastReadPost isnt UnreadIndex.lastReadPost[thread.fullID]
UnreadIndex.lastReadPost[thread.fullID] = lastReadPost
if thread.nodes.root?.parentNode
UnreadIndex.update thread
update: (thread) ->
lastReadPost = UnreadIndex.lastReadPost[thread.fullID]
repliesShown = 0
repliesRead = 0
firstUnread = null
thread.posts.forEach (post) ->
if post.isReply and post.nodes.root.parentNode is thread.nodes.root
repliesShown++
if post.ID <= lastReadPost
repliesRead++
else if (!firstUnread or post.ID < firstUnread.ID) and !post.isHidden and !QuoteYou.isYou(post)
firstUnread = post
hr = UnreadIndex.hr[thread.fullID]
if firstUnread and (repliesRead or lastReadPost is thread.OP.ID)
if !hr
hr = UnreadIndex.hr[thread.fullID] = $.el 'hr',
className: 'unread-line'
$.before firstUnread.nodes.root, hr
else
$.rm hr
hasUnread = if repliesShown
firstUnread or !repliesRead
else if Index.enabled
Index.lastPost(thread.ID) > lastReadPost
else
thread.OP.ID > lastReadPost
thread.nodes.root.classList.toggle 'unread-thread', hasUnread
addMarkReadLink: (thread) ->
return unless thread.nodes.root
link = UnreadIndex.markReadLink[thread.fullID]
unless link
if !link
link = UnreadIndex.markReadLink[thread.fullID] = $.el 'a',
className: 'unread-mark-read brackets-wrap'
href: 'javascript:;'
textContent: 'Mark Read'
$.on link, 'click', UnreadIndex.markRead
if link.parentNode isnt thread.nodes.root
if (divider = $ Site.selectors.threadDivider, thread.nodes.root) # divider inside thread as in Tinyboard
$.before divider, link
else
$.add thread.nodes.root, link
update: (thread) ->
return unless thread.nodes.root
lastReadPost = UnreadIndex.db.get(
boardID: thread.board.ID
threadID: thread.ID
) or 0
hasUnread = (lastReadPost < thread.lastPost)
if hasUnread isnt UnreadIndex.hasUnread[thread.fullID]
thread.nodes.root.classList.toggle 'unread-thread', hasUnread
markRead: ->
thread = Get.threadFromNode @
if Index.enabled
lastPost = Index.lastPost(thread.ID)
else
lastPost = 0
thread.posts.forEach (post) ->
if post.ID > lastPost and !post.isFetchedQuote
lastPost = post.ID
UnreadIndex.lastReadPost[thread.fullID] = lastPost
UnreadIndex.db.set
boardID: thread.board.ID
threadID: thread.ID
val: thread.lastPost
UnreadIndex.update thread
val: lastPost
$.rm UnreadIndex.hr[thread.fullID]
$.rm UnreadIndex.markReadLink[thread.fullID]
ThreadWatcher.update thread.board.ID, thread.ID,
unread: 0
quotingYou: false

View File

@ -61,7 +61,6 @@ class Post
@board.posts.push @ID, @
@thread.posts.push @ID, @
@thread.lastPost = @ID if @ID > @thread.lastPost
g.posts.push @fullID, @
parseNodes: (root) ->

View File

@ -13,14 +13,12 @@ class Thread
@fileLimit = false
@ipCount = undefined
@json = null
@lastPost = 0
@OP = null
@catalogView = null
@nodes =
root: null
summary: null
root: null
@board.threads.push @ID, @
g.threads.push @fullID, @

View File

@ -383,9 +383,9 @@ Config =
'Scroll back to the last read post when reopening a thread.'
1
]
'Mark Read from Index': [
'Unread Line in Index': [
false
'Add links in the index for marking threads read.'
'Show a line between read and unread posts in threads in the index.'
1
]
'Remove Thread Excerpt': [

View File

@ -147,7 +147,7 @@
}
/* Unread */
:root.spooky #unread-line {
:root.spooky .unread-line {
border-color: rgb(197, 200, 198);
}

View File

@ -1059,7 +1059,7 @@ span.hide-announcement {
}
/* Unread */
#unread-line {
.unread-line {
margin: 0;
border-color: rgb(255,0,0);
}

View File

@ -154,7 +154,7 @@
}
/* Unread */
:root.tomorrow #unread-line {
:root.tomorrow .unread-line {
border-color: rgb(197, 200, 198);
}

View File

@ -510,7 +510,7 @@ Main =
['Thread Expansion', ExpandThread]
['Favicon', Favicon]
['Unread', Unread]
['Mark Read from Index', UnreadIndex]
['Unread Line in Index', UnreadIndex]
['Quote Threading', QuoteThreading]
['Thread Stats', ThreadStats]
['Thread Updater', ThreadUpdater]

View File

@ -53,6 +53,7 @@ SW.tinyboard =
selectors:
board: 'form[name="postcontrols"]'
thread: 'div[id^="thread_"]'
threadDivider: 'div[id^="thread_"] > hr:last-of-type'
postContainer: '.reply' # postContainer is thread for OP
infoRoot: '.intro'
info:

View File

@ -7,6 +7,7 @@ SW.yotsuba =
selectors:
board: '.board'
thread: '.thread'
threadDivider: '.board > hr'
postContainer: '.postContainer'
sideArrows: '.sideArrows'
post: '.post'