diff --git a/src/General/Build.coffee b/src/General/Build.coffee
index 8752adf87..c646250d6 100755
--- a/src/General/Build.coffee
+++ b/src/General/Build.coffee
@@ -1,4 +1,6 @@
Build =
+ staticPath: '//s.4cdn.org/image/'
+ gifIcon: if window.devicePixelRatio >= 2 then '@2x.gif' else '.gif'
initPixelRatio: window.devicePixelRatio
spoilerRange: {}
unescape: (text) ->
@@ -303,9 +305,58 @@ Build =
[posts, files] = if Conf['Show Replies']
[data.omitted_posts, data.omitted_images]
else
- # XXX data.images is not accurate.
- [data.replies, data.omitted_images + data.last_replies.filter((data) -> !!data.ext).length]
+ [data.replies, data.images]
nodes.push Build.summary board.ID, data.no, posts, files
nodes
fullThread: (board, data) -> Build.postFromObject data, board.ID
+
+ threadCatalog: (thread) ->
+ for data in Index.liveThreadData
+ break if data.no is thread.ID
+
+ if data.spoiler and !Conf['Reveal Spoiler Thumbnails']
+ src = "#{Build.staticPath}spoiler"
+ if spoilerRange = Build.spoilerRange[thread.board]
+ # Randomize the spoiler image.
+ src += "-#{thread.board}" + Math.floor 1 + spoilerRange * Math.random()
+ src += '.png'
+ imgWidth = imgHeight = 100
+ else if data.filedeleted
+ src = "#{Build.staticPath}filedeleted-res#{Build.gifIcon}"
+ imgWidth = 127
+ imgHeight = 13
+ else
+ src = thread.OP.file.thumbURL
+ max = Math.max data.tn_w, data.tn_h
+ imgWidth = data.tn_w * 150 / max
+ imgHeight = data.tn_h * 150 / max
+
+ postCount = data.replies + 1
+ fileCount = data.images + !!data.ext
+ pageCount = Index.liveThreadIDs.indexOf(thread.ID) // Index.threadsNumPerPage + 1
+
+ subject = if thread.OP.info.subject
+ <%= html('
${thread.OP.info.subject}
') %>
+ else
+ <%= html('') %>
+
+ root = $.el 'div',
+ className: 'catalog-thread'
+ $.extend root, <%= html(
+ '' +
+ '
' +
+ '' +
+ '' +
+ '${postCount} / ${fileCount} / ${pageCount}' +
+ '
' +
+ '&{subject}' +
+ ''
+ ) %>
+
+ if data.bumplimit
+ $.addClass $('.post-count', root), 'warning'
+ if data.imagelimit
+ $.addClass $('.file-count', root), 'warning'
+
+ root
diff --git a/src/General/Index.coffee b/src/General/Index.coffee
index a4890b7df..94387d9d4 100644
--- a/src/General/Index.coffee
+++ b/src/General/Index.coffee
@@ -18,6 +18,7 @@ Index =
{ el: $.el 'label', <%= html(' Paged') %> }
{ el: $.el 'label', <%= html(' Infinite scrolling') %> }
{ el: $.el 'label', <%= html(' All threads') %> }
+ { el: $.el 'label', <%= html(' Catalog') %> }
]
for label in modeEntry.subEntries
input = label.el.firstChild
@@ -63,6 +64,7 @@ Index =
$.addClass doc, 'index-loading'
@root = $.el 'div', className: 'board'
+ Index.cb.rootClass()
@pagelist = $.el 'div',
className: 'pagelist'
hidden: true
@@ -130,7 +132,10 @@ Index =
setTimeout reset, 3 * $.SECOND
cb:
+ rootClass: ->
+ (if Conf['Index Mode'] is 'catalog' then $.addClass else $.rmClass) Index.root, 'catalog-mode'
mode: ->
+ Index.cb.rootClass()
Index.togglePagelist()
Index.buildIndex()
sort: ->
@@ -410,14 +415,23 @@ Index =
Index.sortedNodes = topNodes.concat(bottomNodes)
buildIndex: ->
- if Conf['Index Mode'] isnt 'all pages'
- nodes = Index.buildSinglePage Index.getCurrentPage()
- else
- nodes = Index.sortedNodes
+ switch Conf['Index Mode']
+ when 'all pages'
+ nodes = Index.sortedNodes
+ when 'catalog'
+ nodes = Index.sortedNodes
+ .map((threadRoot) -> Get.threadFromRoot threadRoot)
+ .filter((thread) -> !thread.isHidden)
+ .map (thread) -> thread.getCatalogView()
+ else
+ nodes = Index.buildSinglePage Index.getCurrentPage()
$.rmAll Index.root
$.rmAll Header.hover
- Index.buildReplies nodes if Conf['Show Replies']
- Index.buildStructure nodes
+ if Conf['Index Mode'] is 'catalog'
+ $.add Index.root, nodes
+ else
+ Index.buildReplies nodes if Conf['Show Replies']
+ Index.buildStructure nodes
buildSinglePage: (pageNum) ->
nodesPerPage = Index.threadsNumPerPage
diff --git a/src/General/css/style.css b/src/General/css/style.css
index 187052c6e..120967692 100755
--- a/src/General/css/style.css
+++ b/src/General/css/style.css
@@ -497,6 +497,37 @@ hr ~ div.center:not(.ad-cnt) {
.summary {
text-decoration: none;
}
+.catalog-mode {
+ text-align: center;
+}
+.catalog-thread {
+ display: inline-block;
+ vertical-align: top;
+ padding-top: 5px;
+ width: 165px;
+ max-height: 320px;
+ overflow: hidden;
+ word-break: break-word;
+}
+.thumb {
+ max-width: 150px;
+ max-height: 150px;
+ box-shadow: 0 0 5px rgba(0, 0, 0, .25);
+}
+.thread-stats {
+ cursor: help;
+ font-size: 10px;
+ font-weight: 700;
+ line-height: .8;
+ margin-top: 1px;
+ float: none;
+}
+.catalog-thread .subject {
+ font-weight: 700;
+}
+.catalog-thread .comment br + br {
+ display: none;
+}
/* Announcement Hiding */
:root.hide-announcement #globalMessage {
diff --git a/src/General/lib/thread.class b/src/General/lib/thread.class
index ea17b1e1e..aa2dd000a 100755
--- a/src/General/lib/thread.class
+++ b/src/General/lib/thread.class
@@ -39,6 +39,10 @@ class Thread
$ '[title="Reply to this post"]', @OP.nodes.info
$.after root, [$.tn(' '), icon]
+ getCatalogView: ->
+ return @catalogView if @catalogView
+ @catalogView = Build.threadCatalog @
+
kill: ->
@isDead = true
@timeOfDeath = Date.now()