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:
parent
96cae8339a
commit
481a775a80
@ -691,6 +691,10 @@ Index =
|
|||||||
isHiddenReply: (threadID, replyData) ->
|
isHiddenReply: (threadID, replyData) ->
|
||||||
PostHiding.isHidden(g.BOARD.ID, threadID, replyData.no) or Filter.isHidden(Build.parseJSON replyData, g.BOARD.ID)
|
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) ->
|
buildThreads: (threadIDs, isCatalog, withReplies) ->
|
||||||
threads = []
|
threads = []
|
||||||
newThreads = []
|
newThreads = []
|
||||||
@ -713,7 +717,6 @@ Index =
|
|||||||
thread = new Thread ID, g.BOARD
|
thread = new Thread ID, g.BOARD
|
||||||
newThreads.push thread
|
newThreads.push thread
|
||||||
thread.json = threadData
|
thread.json = threadData
|
||||||
thread.lastPost = if threadData.last_replies then threadData.last_replies[threadData.last_replies.length - 1].no else ID
|
|
||||||
threads.push thread
|
threads.push thread
|
||||||
|
|
||||||
if ((OP = thread.OP) and not OP.isFetchedQuote)
|
if ((OP = thread.OP) and not OP.isFetchedQuote)
|
||||||
@ -741,7 +744,7 @@ Index =
|
|||||||
Main.callbackNodes 'Thread', newThreads
|
Main.callbackNodes 'Thread', newThreads
|
||||||
Main.callbackNodes 'Post', newPosts
|
Main.callbackNodes 'Post', newPosts
|
||||||
Index.updateHideLabel()
|
Index.updateHideLabel()
|
||||||
$.event 'IndexRefreshInternal'
|
$.event 'IndexRefreshInternal', {threadIDs: (t.fullID for t in threads), isCatalog}
|
||||||
|
|
||||||
threads
|
threads
|
||||||
|
|
||||||
|
|||||||
@ -68,6 +68,8 @@ ExpandThread =
|
|||||||
postsCount = 0
|
postsCount = 0
|
||||||
filesCount = 0
|
filesCount = 0
|
||||||
for reply in replies
|
for reply in replies
|
||||||
|
# rm elements above post such as unread line
|
||||||
|
$.rm node while (node = a.nextSibling) and node isnt reply
|
||||||
# rm clones
|
# rm clones
|
||||||
inlined.click() while inlined = $ '.inlined', reply if Conf['Quote Inlining']
|
inlined.click() while inlined = $ '.inlined', reply if Conf['Quote Inlining']
|
||||||
postsCount++
|
postsCount++
|
||||||
|
|||||||
@ -15,6 +15,7 @@ Unread =
|
|||||||
|
|
||||||
@hr = $.el 'hr',
|
@hr = $.el 'hr',
|
||||||
id: 'unread-line'
|
id: 'unread-line'
|
||||||
|
className: 'unread-line'
|
||||||
@posts = new Set()
|
@posts = new Set()
|
||||||
@postsQuotingYou = new Set()
|
@postsQuotingYou = new Set()
|
||||||
@order = new RandomAccessList()
|
@order = new RandomAccessList()
|
||||||
|
|||||||
@ -1,69 +1,109 @@
|
|||||||
UnreadIndex =
|
UnreadIndex =
|
||||||
hasUnread: {}
|
lastReadPost: {}
|
||||||
|
hr: {}
|
||||||
markReadLink: {}
|
markReadLink: {}
|
||||||
|
|
||||||
init: ->
|
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
|
@db = new DataBoard 'lastReadPosts', @sync
|
||||||
|
|
||||||
if Index.enabled
|
Callbacks.Thread.push
|
||||||
$.on d, 'IndexRefreshInternal',
|
name: 'Unread Line in Index'
|
||||||
@onIndexRefresh
|
cb: @node
|
||||||
else
|
|
||||||
Callbacks.Thread.push
|
|
||||||
name: 'Mark Read from Index'
|
|
||||||
cb: @node
|
|
||||||
|
|
||||||
Callbacks.Post.push
|
$.on d, 'IndexRefreshInternal', @onIndexRefresh
|
||||||
name: 'Mark Read from Index'
|
$.on d, 'PostsInserted', @onPostsInserted
|
||||||
cb: @addPost
|
|
||||||
|
|
||||||
onIndexRefresh: ->
|
|
||||||
g.threads.forEach (thread) ->
|
|
||||||
UnreadIndex.addMarkReadLink thread
|
|
||||||
UnreadIndex.update thread
|
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
UnreadIndex.addMarkReadLink @
|
UnreadIndex.lastReadPost[@fullID] = UnreadIndex.db.get(
|
||||||
UnreadIndex.update @
|
boardID: @board.ID
|
||||||
|
threadID: @ID
|
||||||
|
) or 0
|
||||||
|
if !Index.enabled # let onIndexRefresh handle JSON Index
|
||||||
|
UnreadIndex.update @
|
||||||
|
|
||||||
addPost: ->
|
onIndexRefresh: (e) ->
|
||||||
if @ID is @thread.lastPost
|
return if e.detail.isCatalog
|
||||||
UnreadIndex.update @thread
|
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: ->
|
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]
|
link = UnreadIndex.markReadLink[thread.fullID]
|
||||||
unless link
|
if !link
|
||||||
link = UnreadIndex.markReadLink[thread.fullID] = $.el 'a',
|
link = UnreadIndex.markReadLink[thread.fullID] = $.el 'a',
|
||||||
className: 'unread-mark-read brackets-wrap'
|
className: 'unread-mark-read brackets-wrap'
|
||||||
href: 'javascript:;'
|
href: 'javascript:;'
|
||||||
textContent: 'Mark Read'
|
textContent: 'Mark Read'
|
||||||
$.on link, 'click', UnreadIndex.markRead
|
$.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
|
$.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: ->
|
markRead: ->
|
||||||
thread = Get.threadFromNode @
|
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
|
UnreadIndex.db.set
|
||||||
boardID: thread.board.ID
|
boardID: thread.board.ID
|
||||||
threadID: thread.ID
|
threadID: thread.ID
|
||||||
val: thread.lastPost
|
val: lastPost
|
||||||
UnreadIndex.update thread
|
$.rm UnreadIndex.hr[thread.fullID]
|
||||||
|
$.rm UnreadIndex.markReadLink[thread.fullID]
|
||||||
ThreadWatcher.update thread.board.ID, thread.ID,
|
ThreadWatcher.update thread.board.ID, thread.ID,
|
||||||
unread: 0
|
unread: 0
|
||||||
quotingYou: false
|
quotingYou: false
|
||||||
|
|||||||
@ -61,7 +61,6 @@ class Post
|
|||||||
|
|
||||||
@board.posts.push @ID, @
|
@board.posts.push @ID, @
|
||||||
@thread.posts.push @ID, @
|
@thread.posts.push @ID, @
|
||||||
@thread.lastPost = @ID if @ID > @thread.lastPost
|
|
||||||
g.posts.push @fullID, @
|
g.posts.push @fullID, @
|
||||||
|
|
||||||
parseNodes: (root) ->
|
parseNodes: (root) ->
|
||||||
|
|||||||
@ -13,14 +13,12 @@ class Thread
|
|||||||
@fileLimit = false
|
@fileLimit = false
|
||||||
@ipCount = undefined
|
@ipCount = undefined
|
||||||
@json = null
|
@json = null
|
||||||
@lastPost = 0
|
|
||||||
|
|
||||||
@OP = null
|
@OP = null
|
||||||
@catalogView = null
|
@catalogView = null
|
||||||
|
|
||||||
@nodes =
|
@nodes =
|
||||||
root: null
|
root: null
|
||||||
summary: null
|
|
||||||
|
|
||||||
@board.threads.push @ID, @
|
@board.threads.push @ID, @
|
||||||
g.threads.push @fullID, @
|
g.threads.push @fullID, @
|
||||||
|
|||||||
@ -383,9 +383,9 @@ Config =
|
|||||||
'Scroll back to the last read post when reopening a thread.'
|
'Scroll back to the last read post when reopening a thread.'
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
'Mark Read from Index': [
|
'Unread Line in Index': [
|
||||||
false
|
false
|
||||||
'Add links in the index for marking threads read.'
|
'Show a line between read and unread posts in threads in the index.'
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
'Remove Thread Excerpt': [
|
'Remove Thread Excerpt': [
|
||||||
|
|||||||
@ -147,7 +147,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Unread */
|
/* Unread */
|
||||||
:root.spooky #unread-line {
|
:root.spooky .unread-line {
|
||||||
border-color: rgb(197, 200, 198);
|
border-color: rgb(197, 200, 198);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1059,7 +1059,7 @@ span.hide-announcement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Unread */
|
/* Unread */
|
||||||
#unread-line {
|
.unread-line {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-color: rgb(255,0,0);
|
border-color: rgb(255,0,0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -154,7 +154,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Unread */
|
/* Unread */
|
||||||
:root.tomorrow #unread-line {
|
:root.tomorrow .unread-line {
|
||||||
border-color: rgb(197, 200, 198);
|
border-color: rgb(197, 200, 198);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -510,7 +510,7 @@ Main =
|
|||||||
['Thread Expansion', ExpandThread]
|
['Thread Expansion', ExpandThread]
|
||||||
['Favicon', Favicon]
|
['Favicon', Favicon]
|
||||||
['Unread', Unread]
|
['Unread', Unread]
|
||||||
['Mark Read from Index', UnreadIndex]
|
['Unread Line in Index', UnreadIndex]
|
||||||
['Quote Threading', QuoteThreading]
|
['Quote Threading', QuoteThreading]
|
||||||
['Thread Stats', ThreadStats]
|
['Thread Stats', ThreadStats]
|
||||||
['Thread Updater', ThreadUpdater]
|
['Thread Updater', ThreadUpdater]
|
||||||
|
|||||||
@ -53,6 +53,7 @@ SW.tinyboard =
|
|||||||
selectors:
|
selectors:
|
||||||
board: 'form[name="postcontrols"]'
|
board: 'form[name="postcontrols"]'
|
||||||
thread: 'div[id^="thread_"]'
|
thread: 'div[id^="thread_"]'
|
||||||
|
threadDivider: 'div[id^="thread_"] > hr:last-of-type'
|
||||||
postContainer: '.reply' # postContainer is thread for OP
|
postContainer: '.reply' # postContainer is thread for OP
|
||||||
infoRoot: '.intro'
|
infoRoot: '.intro'
|
||||||
info:
|
info:
|
||||||
|
|||||||
@ -7,6 +7,7 @@ SW.yotsuba =
|
|||||||
selectors:
|
selectors:
|
||||||
board: '.board'
|
board: '.board'
|
||||||
thread: '.thread'
|
thread: '.thread'
|
||||||
|
threadDivider: '.board > hr'
|
||||||
postContainer: '.postContainer'
|
postContainer: '.postContainer'
|
||||||
sideArrows: '.sideArrows'
|
sideArrows: '.sideArrows'
|
||||||
post: '.post'
|
post: '.post'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user