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