Merge branch 'v3' into catalog
This commit is contained in:
commit
f080a15292
@ -1,5 +1,8 @@
|
||||
## 3.16.0 - *2014-01-30*
|
||||
|
||||
- More index navigation improvements:
|
||||
- New index mode: `catalog`
|
||||
- New index mode: `catalog`<br>
|
||||

|
||||
- When in catalog mode, use `Shift+Click` to hide, and `Alt+Click` to pin threads.
|
||||
- Existing features affect the catalog mode such as:
|
||||
<ul>
|
||||
|
||||
BIN
img/changelog/3.16.0/0.png
Normal file
BIN
img/changelog/3.16.0/0.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
18
lib/$.coffee
18
lib/$.coffee
@ -267,7 +267,6 @@ $.set = do ->
|
||||
setArea = (area) ->
|
||||
data = items[area]
|
||||
return if !Object.keys(data).length or timeout[area]
|
||||
items[area] = {}
|
||||
chrome.storage[area].set data, ->
|
||||
if chrome.runtime.lastError
|
||||
c.error chrome.runtime.lastError.message
|
||||
@ -276,23 +275,20 @@ $.set = do ->
|
||||
timeout[area] = setTimeout setArea, $.MINUTE, area
|
||||
return
|
||||
delete timeout[area]
|
||||
items[area] = {}
|
||||
|
||||
setAll = $.debounce $.SECOND, ->
|
||||
for key in $.localKeys
|
||||
if key of items.sync
|
||||
items.local[key] = items.sync[key]
|
||||
delete items.sync[key]
|
||||
try
|
||||
setArea 'local'
|
||||
setArea 'sync'
|
||||
catch err
|
||||
c.error err.stack
|
||||
setAll = $.debounce 5 * $.SECOND, ->
|
||||
setArea 'local'
|
||||
setArea 'sync'
|
||||
|
||||
(key, val) ->
|
||||
if typeof key is 'string'
|
||||
items.sync[key] = val
|
||||
else
|
||||
$.extend items.sync, key
|
||||
for key in $.localKeys when key of items.sync
|
||||
items.local[key] = items.sync[key]
|
||||
delete items.sync[key]
|
||||
setAll()
|
||||
$.clear = (cb) ->
|
||||
count = 2
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "4chan-X",
|
||||
"version": "3.15.2",
|
||||
"version": "3.16.0",
|
||||
"description": "Cross-browser extension for productive lurking on 4chan.",
|
||||
"meta": {
|
||||
"name": "4chan X",
|
||||
@ -26,13 +26,13 @@
|
||||
"grunt-bump": "~0.0.13",
|
||||
"grunt-concurrent": "~0.4.3",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
"grunt-contrib-coffee": "~0.8.2",
|
||||
"grunt-contrib-coffee": "~0.9.0",
|
||||
"grunt-contrib-compress": "~0.6.0",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-copy": "~0.5.0",
|
||||
"grunt-contrib-watch": "~0.5.3",
|
||||
"grunt-shell": "~0.6.4",
|
||||
"load-grunt-tasks": "~0.2.1"
|
||||
"load-grunt-tasks": "~0.3.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@ -19,7 +19,7 @@ ThreadHiding =
|
||||
thread = Get.threadFromRoot root
|
||||
continue unless thread.isHidden
|
||||
unless thread.stub
|
||||
nodes[i + 1].hidden = true
|
||||
Index.nodes[i + 1].hidden = true
|
||||
else unless root.contains thread.stub
|
||||
# When we come back to a page, the stub is already there.
|
||||
ThreadHiding.makeStub thread, root
|
||||
|
||||
@ -176,7 +176,7 @@ Build =
|
||||
''
|
||||
|
||||
if isOP and g.VIEW is 'index'
|
||||
pageNum = Math.floor Index.liveThreadIDs.indexOf(postID) / Index.threadsNumPerPage
|
||||
pageNum = Index.liveThreadIDs.indexOf(postID) // Index.threadsNumPerPage
|
||||
pageIcon = " <span class=page-num title='This thread is on page #{pageNum} in the original index.'>Page #{pageNum}</span>"
|
||||
replyLink = " <span>[<a href='/#{boardID}/res/#{threadID}' class=replylink>Reply</a>]</span>"
|
||||
else
|
||||
@ -284,7 +284,7 @@ Build =
|
||||
|
||||
postCount = data.replies + 1
|
||||
fileCount = data.images + !!data.ext
|
||||
pageCount = Math.floor Index.liveThreadIDs.indexOf(thread.ID) / Index.threadsNumPerPage
|
||||
pageCount = Index.liveThreadIDs.indexOf(thread.ID) // Index.threadsNumPerPage
|
||||
|
||||
subject = if thread.OP.info.subject
|
||||
"<div class='subject'>#{thread.OP.info.subject}</div>"
|
||||
|
||||
@ -7,8 +7,9 @@ class CatalogThread
|
||||
@board = @thread.board
|
||||
@nodes =
|
||||
root: root
|
||||
thumb: $ '.thumb', root
|
||||
postCount: $ '.post-count', root
|
||||
fileCount: $ '.file-count', root
|
||||
pageCount: $ '.page-count', root
|
||||
thumb: $ '.thumb', root
|
||||
icons: $ '.thread-icons', root
|
||||
postCount: $ '.post-count', root
|
||||
fileCount: $ '.file-count', root
|
||||
pageCount: $ '.page-count', root
|
||||
@thread.catalogView = @
|
||||
|
||||
@ -71,7 +71,7 @@ class DataBoard
|
||||
ajaxClean: (boardID) ->
|
||||
$.cache "//a.4cdn.org/#{boardID}/threads.json", (e) =>
|
||||
if e.target.status isnt 200
|
||||
@delete boardID if e.target.status is 404
|
||||
@delete {boardID} if e.target.status is 404
|
||||
return
|
||||
board = @data.boards[boardID]
|
||||
threads = {}
|
||||
|
||||
@ -188,7 +188,7 @@ Get =
|
||||
|
||||
comment = bq.innerHTML
|
||||
# greentext
|
||||
.replace(/(^|>)(>[^<$]*)(<|$)/g, '$1<span class=quote>$2</span>$3')
|
||||
.replace /(^|>)(>[^<$]*)(<|$)/g, '$1<span class=quote>$2</span>$3'
|
||||
# quotes
|
||||
.replace /((>){2}(>\/[a-z\d]+\/)?\d+)/g, '<span class=deadlink>$1</span>'
|
||||
|
||||
|
||||
@ -353,7 +353,7 @@ Index =
|
||||
threadRoot = Build.thread g.BOARD, threadData
|
||||
Index.nodes.push threadRoot, $.el 'hr'
|
||||
if thread = g.BOARD.threads[threadData.no]
|
||||
thread.setPage Math.floor i / Index.threadsNumPerPage
|
||||
thread.setPage i // Index.threadsNumPerPage
|
||||
thread.setCount 'post', threadData.replies + 1, threadData.bumplimit
|
||||
thread.setCount 'file', threadData.images + !!threadData.ext, threadData.imagelimit
|
||||
thread.setStatus 'Sticky', !!threadData.sticky
|
||||
@ -403,8 +403,8 @@ Index =
|
||||
Main.callbackNodes Post, posts
|
||||
buildCatalogViews: ->
|
||||
threads = Index.sortedNodes
|
||||
.filter((n, i) -> !(i % 2))
|
||||
.map((threadRoot) -> Get.threadFromRoot threadRoot)
|
||||
.filter (n, i) -> !(i % 2)
|
||||
.map (threadRoot) -> Get.threadFromRoot threadRoot
|
||||
.filter (thread) -> !thread.isHidden
|
||||
catalogThreads = []
|
||||
for thread in threads when !thread.catalogView
|
||||
@ -417,8 +417,8 @@ Index =
|
||||
sortedThreadIDs = Index.liveThreadIDs
|
||||
when 'lastreply'
|
||||
sortedThreadIDs = [Index.liveThreadData...].sort((a, b) ->
|
||||
a = a.last_replies[a.last_replies.length - 1] if 'last_replies' of a
|
||||
b = b.last_replies[b.last_replies.length - 1] if 'last_replies' of b
|
||||
[..., a] = a.last_replies if 'last_replies' of a
|
||||
[..., b] = b.last_replies if 'last_replies' of b
|
||||
b.no - a.no
|
||||
).map (data) -> data.no
|
||||
when 'birth'
|
||||
|
||||
@ -33,7 +33,7 @@ class Thread
|
||||
typeLC = type.toLowerCase()
|
||||
unless status
|
||||
$.rm $ ".#{typeLC}Icon", @OP.nodes.info
|
||||
$.rm $ ".#{typeLC}Icon", @catalogView if @catalogView
|
||||
$.rm $ ".#{typeLC}Icon", @catalogView.nodes.icons if @catalogView
|
||||
return
|
||||
|
||||
icon = $.el 'img',
|
||||
@ -49,8 +49,7 @@ class Thread
|
||||
$.after root, [$.tn(' '), icon]
|
||||
|
||||
return unless @catalogView
|
||||
root = $ '.thread-icons', @catalogView
|
||||
(if type is 'Sticky' and @isClosed then $.prepend else $.add) root, icon.cloneNode()
|
||||
(if type is 'Sticky' and @isClosed then $.prepend else $.add) @catalogView.nodes.icons, icon.cloneNode()
|
||||
|
||||
pin: ->
|
||||
@isOnTop = @isPinned = true
|
||||
|
||||
@ -191,7 +191,7 @@ UI = do ->
|
||||
# prevent text selection
|
||||
e.preventDefault()
|
||||
if isTouching = e.type is 'touchstart'
|
||||
e = e.changedTouches[e.changedTouches.length - 1]
|
||||
[..., e] = e.changedTouches
|
||||
# distance from pointer to el edge is constant; calculate it here.
|
||||
el = $.x 'ancestor::div[contains(@class,"dialog")][1]', @
|
||||
rect = el.getBoundingClientRect()
|
||||
|
||||
@ -50,14 +50,13 @@ QR =
|
||||
else
|
||||
QR.status()
|
||||
|
||||
QR.persist() if Conf['Persistent QR']
|
||||
return unless Conf['Persistent QR']
|
||||
QR.open()
|
||||
QR.hide() if Conf['Auto-Hide QR'] or g.VIEW is 'index' and Conf['Index Mode'] is 'catalog'
|
||||
|
||||
node: ->
|
||||
$.on $('a[title="Quote this post"]', @nodes.info), 'click', QR.quote
|
||||
|
||||
persist: ->
|
||||
QR.open()
|
||||
QR.hide() if Conf['Auto-Hide QR']
|
||||
open: ->
|
||||
if QR.nodes
|
||||
QR.nodes.el.hidden = false
|
||||
|
||||
@ -48,7 +48,7 @@ QR.cooldown =
|
||||
$.delete "cooldown.#{g.BOARD}"
|
||||
count: ->
|
||||
unless Object.keys(QR.cooldown.cooldowns).length
|
||||
$.delete "#{g.BOARD}.cooldown"
|
||||
$.delete "cooldown.#{g.BOARD}"
|
||||
delete QR.cooldown.isCounting
|
||||
delete QR.cooldown.seconds
|
||||
QR.status()
|
||||
@ -76,7 +76,7 @@ QR.cooldown =
|
||||
if isReply is cooldown.isReply
|
||||
# Only cooldowns relevant to this post can set the seconds variable:
|
||||
# reply cooldown with a reply, thread cooldown with a thread
|
||||
elapsed = Math.floor (now - start) / $.SECOND
|
||||
elapsed = (now - start) // $.SECOND
|
||||
continue if elapsed < 0 # clock changed since then?
|
||||
type = unless isReply
|
||||
'thread'
|
||||
@ -91,7 +91,7 @@ QR.cooldown =
|
||||
seconds = Math.max seconds, types[type] - elapsed
|
||||
|
||||
if seconds and Conf['Cooldown Prediction'] and hasFile and upSpd
|
||||
seconds -= Math.floor post.file.size / upSpd * upSpdAccuracy
|
||||
seconds -= post.file.size // (upSpd * upSpdAccuracy)
|
||||
seconds = Math.max seconds, 0
|
||||
# Update the status when we change posting type.
|
||||
# Don't get stuck at some random number.
|
||||
|
||||
@ -35,7 +35,7 @@ QR.post = class
|
||||
else
|
||||
'new'
|
||||
|
||||
prev = QR.posts[QR.posts.length - 1]
|
||||
[..., prev] = QR.posts
|
||||
QR.posts.push @
|
||||
@nodes.spoiler.checked = @spoiler = if prev and Conf['Remember Spoiler']
|
||||
prev.spoiler
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user