Merge branch 'v3'
Conflicts: CHANGELOG.md LICENSE builds/appchan-x.user.js builds/crx/script.js src/General/Config.coffee src/General/css/style.css src/Miscellaneous/AnnouncementHiding.coffee src/Miscellaneous/InfiniScroll.coffee src/Posting/QR.coffee
This commit is contained in:
commit
e459069ae6
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,3 +1,9 @@
|
|||||||
|
**Mayhem**:
|
||||||
|
- Bugfixes
|
||||||
|
|
||||||
|
**Zixaphir**:
|
||||||
|
- Bugfixes
|
||||||
|
|
||||||
### v2.9.3
|
### v2.9.3
|
||||||
*2014-03-11*
|
*2014-03-11*
|
||||||
|
|
||||||
@ -69,7 +75,7 @@
|
|||||||
<li> Filter (hiding, highlighting)
|
<li> Filter (hiding, highlighting)
|
||||||
<li> Thread Hiding
|
<li> Thread Hiding
|
||||||
<li> Linkify
|
<li> Linkify
|
||||||
<li> Auto-GIF
|
<li> Thumbnail Replacemenu
|
||||||
<li> Image Hover
|
<li> Image Hover
|
||||||
</ul>
|
</ul>
|
||||||
- Support for the official catalog will be removed in the future, once the catalog mode for the index is deemed satisfactory.
|
- Support for the official catalog will be removed in the future, once the catalog mode for the index is deemed satisfactory.
|
||||||
@ -86,7 +92,10 @@
|
|||||||
**Vampiricwulf**
|
**Vampiricwulf**
|
||||||
- Flash embedding and other Flash features.
|
- Flash embedding and other Flash features.
|
||||||
|
|
||||||
**Zixaphir**
|
**Zixaphir**
|
||||||
|
- Update Custom Navigation legend to reflect index mode changes.
|
||||||
|
- JSON Navigation now works for backlinks (when Quote Inlining is disabled) and backlink hashlinks.
|
||||||
|
- JSON Navigation (Index, Catalog) performance improvements.
|
||||||
- Added a nifty bread-crumb for the JSON Navigation.
|
- Added a nifty bread-crumb for the JSON Navigation.
|
||||||
- Many spiffy performance, state awareness, and sanity improvements to JSON Navigation.
|
- Many spiffy performance, state awareness, and sanity improvements to JSON Navigation.
|
||||||
- Bugfixes.
|
- Bugfixes.
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* appchan x - Version 2.9.3 - 2014-03-11
|
* appchan x - Version 2.9.3 - 2014-03-13
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
* https://github.com/zixaphir/appchan-x/blob/master/LICENSE
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,26 +0,0 @@
|
|||||||
<input type="search" id="index-search" class="field" placeholder="Search">
|
|
||||||
<a id="index-search-clear" class="fa fa-times-circle" href="javascript:;"></a>
|
|
||||||
|
|
||||||
<time id="index-last-refresh" title="Last index refresh">...</time>
|
|
||||||
<span id="hidden-label" hidden> — <span id="hidden-count"></span> <span id="hidden-toggle">[<a href="javascript:;">Show</a>]</span></span>
|
|
||||||
<span style="flex:1"></span>
|
|
||||||
<select id="index-mode" name="Index Mode">
|
|
||||||
<option disabled>Index Mode</option>
|
|
||||||
<option value="paged">Paged</option>
|
|
||||||
<option value="infinite">Infinite Scrolling</option>
|
|
||||||
<option value="all pages">All threads</option>
|
|
||||||
<option value="catalog">Catalog</option>
|
|
||||||
</select>
|
|
||||||
<select id="index-sort" name="Index Sort">
|
|
||||||
<option disabled>Index Sort</option>
|
|
||||||
<option value="bump">Bump order</option>
|
|
||||||
<option value="lastreply">Last reply</option>
|
|
||||||
<option value="birth">Creation date</option>
|
|
||||||
<option value="replycount">Reply count</option>
|
|
||||||
<option value="filecount">File count</option>
|
|
||||||
</select>
|
|
||||||
<select id="index-size" name="Index Size">
|
|
||||||
<option disabled>Image Size</option>
|
|
||||||
<option value="small">Small</option>
|
|
||||||
<option value="large">Large</option>
|
|
||||||
</select>
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
<button class="export">Export Settings</button>
|
|
||||||
<button class="import">Import Settings</button>
|
|
||||||
<button class="reset">Reset Settings</button>
|
|
||||||
<input type="file" hidden>
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
<div id="fourchanx-settings" class="dialog">
|
|
||||||
<nav>
|
|
||||||
<div class="sections-list"></div>
|
|
||||||
<div class="credits">
|
|
||||||
<a href="<%= meta.page %>" target="_blank"><%= meta.name %></a>
|
|
||||||
|
|
|
||||||
<a href="<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md" target="_blank">#{g.VERSION}</a>
|
|
||||||
|
|
|
||||||
<a href="<%= meta.repo %>blob/<%= meta.mainBranch %>/CONTRIBUTING.md#reporting-bugs-and-suggestions" target="_blank">Issues</a>
|
|
||||||
|
|
|
||||||
<a href="javascript:;" class="close fa fa-times" title="Close"></a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<section></section>
|
|
||||||
</div>
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
<div>
|
|
||||||
<input type="checkbox" id="autohide" title="Auto-hide">
|
|
||||||
<select data-name="thread" title="Create a new thread / Reply">
|
|
||||||
<option value="new">New thread</option>
|
|
||||||
</select>
|
|
||||||
<span class="move"></span>
|
|
||||||
<a href="javascript:;" class="close fa fa-times" title="Close"></a>
|
|
||||||
</div>
|
|
||||||
<form>
|
|
||||||
<div class="persona">
|
|
||||||
<input type="button" id="dump-button" title="Dump list" value="+">
|
|
||||||
<input data-name="name" name="name" list="list-name" placeholder="Name" class="field">
|
|
||||||
<input data-name="email" name="email" list="list-email" placeholder="E-mail" class="field">
|
|
||||||
<input data-name="sub" name="sub" list="list-sub" placeholder="Subject" class="field">
|
|
||||||
</div>
|
|
||||||
<div id="dump-list"></div>
|
|
||||||
<a href="javascript:;" id="add-post" class="fa fa-plus" title="Add a post"></a>
|
|
||||||
<div class="textarea">
|
|
||||||
<textarea data-name="com" placeholder="Comment" class="field"></textarea>
|
|
||||||
<span id="char-count"></span>
|
|
||||||
</div>
|
|
||||||
<div id="file-n-submit">
|
|
||||||
<input type="file" hidden multiple>
|
|
||||||
<input type="submit">
|
|
||||||
<input type="button" id="qr-file-button" value="Choose files">
|
|
||||||
<span id="qr-no-file">No selected file</span>
|
|
||||||
<input id="qr-filename" data-name="filename" spellcheck="false">
|
|
||||||
<span id="qr-filesize"></span>
|
|
||||||
<a href="javascript:;" id="qr-filerm" class="fa fa-times-circle" title="Remove file"></a>
|
|
||||||
<input type="checkbox" id="qr-file-spoiler" title="Spoiler image">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<datalist id="list-name"></datalist>
|
|
||||||
<datalist id="list-email"></datalist>
|
|
||||||
<datalist id="list-sub"></datalist>
|
|
||||||
@ -114,6 +114,6 @@
|
|||||||
"https": true,
|
"https": true,
|
||||||
"withCredentials": true,
|
"withCredentials": true,
|
||||||
"software": "foolfuuka",
|
"software": "foolfuuka",
|
||||||
"boards": ["a", "biz", "co", "d", "diy", "gd", "jp", "m", "mlp", "s4s", "sci", "sp", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
|
"boards": ["a", "biz", "co", "d", "diy", "gd", "jp", "m", "s4s", "sci", "sp", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
|
||||||
"files": ["a", "biz", "d", "diy", "gd", "jp", "m", "s4s", "sci", "tg", "u", "vg", "vp", "vr", "wsg"]
|
"files": ["a", "biz", "d", "diy", "gd", "jp", "m", "s4s", "sci", "tg", "u", "vg", "vp", "vr", "wsg"]
|
||||||
}]
|
}]
|
||||||
|
|||||||
@ -30,13 +30,13 @@
|
|||||||
"font-awesome": "~4.0.3",
|
"font-awesome": "~4.0.3",
|
||||||
"grunt": "~0.4.2",
|
"grunt": "~0.4.2",
|
||||||
"grunt-bump": "~0.0.13",
|
"grunt-bump": "~0.0.13",
|
||||||
"grunt-concurrent": "~0.4.3",
|
"grunt-concurrent": "~0.5.0",
|
||||||
"grunt-contrib-clean": "~0.5.0",
|
"grunt-contrib-clean": "~0.5.0",
|
||||||
"grunt-contrib-coffee": "~0.10.0",
|
"grunt-contrib-coffee": "~0.10.0",
|
||||||
"grunt-contrib-compress": "~0.7.0",
|
"grunt-contrib-compress": "~0.7.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.6.0",
|
||||||
"grunt-shell": "~0.6.4",
|
"grunt-shell": "~0.6.4",
|
||||||
"load-grunt-tasks": "~0.4.0"
|
"load-grunt-tasks": "~0.4.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -148,6 +148,7 @@ PostHiding =
|
|||||||
el: $.el 'a', href: 'javascript:;'
|
el: $.el 'a', href: 'javascript:;'
|
||||||
order: 20
|
order: 20
|
||||||
open: (post) ->
|
open: (post) ->
|
||||||
|
return false if post.isReply
|
||||||
@el.textContent = if post.isHidden
|
@el.textContent = if post.isHidden
|
||||||
'Unhide thread'
|
'Unhide thread'
|
||||||
else
|
else
|
||||||
|
|||||||
@ -181,7 +181,7 @@ Build =
|
|||||||
''
|
''
|
||||||
|
|
||||||
if isOP and g.VIEW is 'index'
|
if isOP and g.VIEW is 'index'
|
||||||
pageNum = Index.liveThreadIDs.indexOf(postID) // Index.threadsNumPerPage
|
pageNum = Index.liveThreadData.keys.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
|
||||||
@ -237,11 +237,11 @@ Build =
|
|||||||
|
|
||||||
catalogThread: (thread) ->
|
catalogThread: (thread) ->
|
||||||
{staticPath, gifIcon} = Build
|
{staticPath, gifIcon} = Build
|
||||||
data = Index.liveThreadData[Index.liveThreadIDs.indexOf thread.ID]
|
data = Index.liveThreadData[thread.ID]
|
||||||
|
|
||||||
postCount = data.replies + 1
|
postCount = data.replies + 1
|
||||||
fileCount = data.images + !!data.ext
|
fileCount = data.images + !!data.ext
|
||||||
pageCount = Index.liveThreadIDs.indexOf(thread.ID) // Index.threadsNumPerPage
|
pageCount = Index.liveThreadData.keys.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>"
|
||||||
|
|||||||
@ -13,10 +13,6 @@ Config =
|
|||||||
false
|
false
|
||||||
'Link to external catalog instead of the internal one.'
|
'Link to external catalog instead of the internal one.'
|
||||||
]
|
]
|
||||||
'Announcement Hiding': [
|
|
||||||
true
|
|
||||||
'Add button to hide 4chan announcements.'
|
|
||||||
]
|
|
||||||
'Desktop Notifications': [
|
'Desktop Notifications': [
|
||||||
false
|
false
|
||||||
'Enables desktop notifications across various <%= meta.name %> features.'
|
'Enables desktop notifications across various <%= meta.name %> features.'
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
Header =
|
Header =
|
||||||
init: ->
|
init: ->
|
||||||
|
|
||||||
@menu = new UI.Menu 'header'
|
@menu = new UI.Menu 'header'
|
||||||
|
|
||||||
menuButton = $.el 'span',
|
menuButton = $.el 'span',
|
||||||
@ -245,25 +246,13 @@ Header =
|
|||||||
|
|
||||||
setBarVisibility: (hide) ->
|
setBarVisibility: (hide) ->
|
||||||
Header.headerToggler.checked = hide
|
Header.headerToggler.checked = hide
|
||||||
$.event 'CloseMenu'
|
|
||||||
(if hide then $.addClass else $.rmClass) Header.bar, 'autohide'
|
(if hide then $.addClass else $.rmClass) Header.bar, 'autohide'
|
||||||
(if hide then $.addClass else $.rmClass) doc, 'autohide'
|
|
||||||
|
|
||||||
toggleBarVisibility: ->
|
toggleBarVisibility: (e) ->
|
||||||
hide = if @nodeName is 'INPUT'
|
hide = @checked
|
||||||
@checked
|
Conf['Header auto-hide'] = hide
|
||||||
else
|
$.set 'Header auto-hide', hide
|
||||||
!$.hasClass Header.bar, 'autohide'
|
|
||||||
# set checked status if called from keybind
|
|
||||||
@checked = hide
|
|
||||||
|
|
||||||
$.set 'Header auto-hide', Conf['Header auto-hide'] = hide
|
|
||||||
Header.setBarVisibility hide
|
Header.setBarVisibility hide
|
||||||
message = "The header bar will #{if hide
|
|
||||||
'automatically hide itself.'
|
|
||||||
else
|
|
||||||
'remain visible.'}"
|
|
||||||
new Notice 'info', message, 2
|
|
||||||
|
|
||||||
setHideBarOnScroll: (hide) ->
|
setHideBarOnScroll: (hide) ->
|
||||||
Header.scrollHeaderToggler.checked = hide
|
Header.scrollHeaderToggler.checked = hide
|
||||||
|
|||||||
@ -96,7 +96,7 @@ Index =
|
|||||||
|
|
||||||
@searchInput = $ '#index-search', @navLinks
|
@searchInput = $ '#index-search', @navLinks
|
||||||
|
|
||||||
@searchTest()
|
@searchTest true
|
||||||
|
|
||||||
@hideLabel = $ '#hidden-label', @navLinks
|
@hideLabel = $ '#hidden-label', @navLinks
|
||||||
@selectMode = $ '#index-mode', @navLinks
|
@selectMode = $ '#index-mode', @navLinks
|
||||||
@ -153,8 +153,8 @@ Index =
|
|||||||
$.after $.id('delform'), Index.pagelist
|
$.after $.id('delform'), Index.pagelist
|
||||||
$.rmClass doc, 'index-loading'
|
$.rmClass doc, 'index-loading'
|
||||||
|
|
||||||
scroll: $.debounce 100, ->
|
scroll: ->
|
||||||
return if Index.req or Conf['Index Mode'] isnt 'infinite' or (doc.scrollTop <= doc.scrollHeight - (300 + window.innerHeight)) or g.VIEW is 'thread'
|
return if Index.req or Conf['Index Mode'] isnt 'infinite' or (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight)) or g.VIEW is 'thread'
|
||||||
Index.pageNum = (Index.pageNum or Index.getCurrentPage()) + 1 # Avoid having to pushState to keep track of the current page
|
Index.pageNum = (Index.pageNum or Index.getCurrentPage()) + 1 # Avoid having to pushState to keep track of the current page
|
||||||
|
|
||||||
return Index.endNotice() if Index.pageNum >= Index.pagesNum
|
return Index.endNotice() if Index.pageNum >= Index.pagesNum
|
||||||
@ -270,11 +270,15 @@ Index =
|
|||||||
{hash} = window.location
|
{hash} = window.location
|
||||||
window.location = './' + hash
|
window.location = './' + hash
|
||||||
|
|
||||||
searchTest: ->
|
searchTest: (init) ->
|
||||||
return unless hash = window.location.hash
|
return false unless hash = window.location.hash
|
||||||
return unless match = hash.match /s=([\w]+)/
|
return false unless match = hash.match /s=([\w]+)/
|
||||||
@searchInput.value = match[1]
|
@searchInput.value = match[1]
|
||||||
$.on d, '4chanXInitFinished', @onSearchInput
|
if init
|
||||||
|
$.on d, '4chanXInitFinished', Index.onSearchInput
|
||||||
|
else
|
||||||
|
Index.onSearchInput()
|
||||||
|
return true
|
||||||
|
|
||||||
setupNavLinks: ->
|
setupNavLinks: ->
|
||||||
for el in $$ '.navLinks.desktop > a'
|
for el in $$ '.navLinks.desktop > a'
|
||||||
@ -410,7 +414,7 @@ Index =
|
|||||||
Index.pageNav pageNum
|
Index.pageNav pageNum
|
||||||
|
|
||||||
pageNav: (pageNum) ->
|
pageNav: (pageNum) ->
|
||||||
return if Index.currentPage is pageNum
|
return if Index.currentPage is pageNum and not Index.root.parentElement
|
||||||
history.pushState null, '', if pageNum is 0 then './' else pageNum
|
history.pushState null, '', if pageNum is 0 then './' else pageNum
|
||||||
Index.pageLoad pageNum
|
Index.pageLoad pageNum
|
||||||
|
|
||||||
@ -475,7 +479,7 @@ Index =
|
|||||||
updateHideLabel: ->
|
updateHideLabel: ->
|
||||||
hiddenCount = 0
|
hiddenCount = 0
|
||||||
for threadID, thread of g.BOARD.threads when thread.isHidden
|
for threadID, thread of g.BOARD.threads when thread.isHidden
|
||||||
hiddenCount++ if thread.ID in Index.liveThreadIDs
|
hiddenCount++ if thread.ID in Index.liveThreadData.keys
|
||||||
unless hiddenCount
|
unless hiddenCount
|
||||||
Index.hideLabel.hidden = true
|
Index.hideLabel.hidden = true
|
||||||
Index.cb.toggleHiddenThreads() if Index.showHiddenThreads
|
Index.cb.toggleHiddenThreads() if Index.showHiddenThreads
|
||||||
@ -496,6 +500,10 @@ Index =
|
|||||||
delete Index.pageNum
|
delete Index.pageNum
|
||||||
Index.req?.abort()
|
Index.req?.abort()
|
||||||
Index.notice?.close()
|
Index.notice?.close()
|
||||||
|
|
||||||
|
{sortedThreads} = Index
|
||||||
|
if sortedThreads
|
||||||
|
board = sortedThreads[0].board.ID
|
||||||
|
|
||||||
# This notice only displays if Index Refresh is taking too long
|
# This notice only displays if Index Refresh is taking too long
|
||||||
now = Date.now()
|
now = Date.now()
|
||||||
@ -507,11 +515,11 @@ Index =
|
|||||||
|
|
||||||
pageNum = null if typeof pageNum isnt 'number' # event
|
pageNum = null if typeof pageNum isnt 'number' # event
|
||||||
onload = (e) -> Index.load e, pageNum
|
onload = (e) -> Index.load e, pageNum
|
||||||
Index.req = $.ajax "//a.4cdn.org/#{g.BOARD}/catalog.json",
|
Index.req = $.ajax "//a.4cdn.org/#{g.BOARD.ID}/catalog.json",
|
||||||
onabort: onload
|
onabort: onload
|
||||||
onloadend: onload
|
onloadend: onload
|
||||||
,
|
,
|
||||||
whenModified: Index.board is "#{g.BOARD}"
|
whenModified: board is g.BOARD.ID
|
||||||
$.addClass Index.button, 'fa-spin'
|
$.addClass Index.button, 'fa-spin'
|
||||||
|
|
||||||
load: (e, pageNum) ->
|
load: (e, pageNum) ->
|
||||||
@ -539,13 +547,11 @@ Index =
|
|||||||
|
|
||||||
Navigate.title()
|
Navigate.title()
|
||||||
|
|
||||||
Index.board = "#{g.BOARD}"
|
|
||||||
|
|
||||||
try
|
try
|
||||||
if req.status is 200
|
if req.status is 200
|
||||||
Index.parse req.response, pageNum
|
Index.parse req.response, pageNum
|
||||||
else if req.status is 304 and pageNum?
|
else if req.status is 304
|
||||||
Index.pageNav pageNum
|
Index.pageNav pageNum or 0
|
||||||
catch err
|
catch err
|
||||||
c.error "Index failure: #{err.message}", err.stack
|
c.error "Index failure: #{err.message}", err.stack
|
||||||
# network error or non-JSON content for example.
|
# network error or non-JSON content for example.
|
||||||
@ -574,26 +580,25 @@ Index =
|
|||||||
parseThreadList: (pages) ->
|
parseThreadList: (pages) ->
|
||||||
Index.threadsNumPerPage = pages[0].threads.length
|
Index.threadsNumPerPage = pages[0].threads.length
|
||||||
|
|
||||||
live = []
|
live = new SimpleDict()
|
||||||
i = 0
|
i = 0
|
||||||
while page = pages[i++]
|
while page = pages[i++]
|
||||||
live = live.concat page.threads
|
j = 0
|
||||||
|
{threads} = page
|
||||||
|
while thread = threads[j++]
|
||||||
|
live.push thread.no, thread
|
||||||
|
|
||||||
data = []
|
Index.liveThreadData = live
|
||||||
i = 0
|
|
||||||
while thread = live[i++]
|
|
||||||
data.push thread.no
|
|
||||||
|
|
||||||
Index.liveThreadData = live
|
|
||||||
Index.liveThreadIDs = data
|
|
||||||
|
|
||||||
g.BOARD.threads.forEach (thread) ->
|
g.BOARD.threads.forEach (thread) ->
|
||||||
thread.collect() unless thread.ID in Index.liveThreadIDs
|
thread.collect() unless thread.ID in Index.liveThreadData.keys
|
||||||
|
|
||||||
buildThreads: ->
|
buildThreads: ->
|
||||||
threads = []
|
threads = []
|
||||||
posts = []
|
posts = []
|
||||||
for threadData, i in Index.liveThreadData
|
errors = null
|
||||||
|
|
||||||
|
Index.liveThreadData.forEach (threadData) ->
|
||||||
threadRoot = Build.thread g.BOARD, threadData
|
threadRoot = Build.thread g.BOARD, threadData
|
||||||
if thread = g.BOARD.threads[threadData.no]
|
if thread = g.BOARD.threads[threadData.no]
|
||||||
thread.setPage i // Index.threadsNumPerPage
|
thread.setPage i // Index.threadsNumPerPage
|
||||||
@ -601,52 +606,48 @@ Index =
|
|||||||
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
|
||||||
thread.setStatus 'Closed', !!threadData.closed
|
thread.setStatus 'Closed', !!threadData.closed
|
||||||
|
|
||||||
else
|
else
|
||||||
thread = new Thread threadData.no, g.BOARD
|
thread = new Thread threadData.no, g.BOARD
|
||||||
threads.push thread
|
threads.push thread
|
||||||
continue if thread.ID of thread.posts
|
|
||||||
|
return if thread.ID of thread.posts
|
||||||
|
|
||||||
try
|
try
|
||||||
posts.push new Post $('.opContainer', threadRoot), thread, g.BOARD
|
posts.push new Post $('.opContainer', threadRoot), thread, g.BOARD
|
||||||
|
|
||||||
catch err
|
catch err
|
||||||
# Skip posts that we failed to parse.
|
# Skip posts that we failed to parse.
|
||||||
errors = [] unless errors
|
errors = [] unless errors
|
||||||
errors.push
|
errors.push
|
||||||
message: "Parsing of Thread No.#{thread} failed. Thread will be skipped."
|
message: "Parsing of Thread No.#{thread} failed. Thread will be skipped."
|
||||||
error: err
|
error: err
|
||||||
Main.handleErrors errors if errors
|
|
||||||
|
|
||||||
|
Main.handleErrors errors if errors
|
||||||
Main.callbackNodes Thread, threads
|
Main.callbackNodes Thread, threads
|
||||||
Main.callbackNodes Post, posts
|
Main.callbackNodes Post, posts
|
||||||
Index.updateHideLabel()
|
Index.updateHideLabel()
|
||||||
|
|
||||||
$.event 'IndexRefresh'
|
$.event 'IndexRefresh'
|
||||||
|
|
||||||
buildHRs: (threadRoots) ->
|
buildReplies: (thread) ->
|
||||||
nodes = []
|
|
||||||
i = 0
|
|
||||||
while node = threadRoots[i++]
|
|
||||||
nodes.push node, $.el 'hr'
|
|
||||||
nodes
|
|
||||||
|
|
||||||
buildReplies: (threads) ->
|
|
||||||
return unless Conf['Show Replies']
|
return unless Conf['Show Replies']
|
||||||
posts = []
|
posts = []
|
||||||
for thread in threads
|
return unless lastReplies = Index.liveThreadData[thread.ID].last_replies
|
||||||
i = Index.liveThreadIDs.indexOf thread.ID
|
nodes = []
|
||||||
continue unless lastReplies = Index.liveThreadData[i].last_replies
|
for data in lastReplies
|
||||||
nodes = []
|
if post = thread.posts[data.no]
|
||||||
for data in lastReplies
|
nodes.push post.nodes.root
|
||||||
if post = thread.posts[data.no]
|
continue
|
||||||
nodes.push post.nodes.root
|
nodes.push node = Build.postFromObject data, thread.board.ID
|
||||||
continue
|
try
|
||||||
nodes.push node = Build.postFromObject data, thread.board.ID
|
posts.push new Post node, thread, thread.board
|
||||||
try
|
catch err
|
||||||
posts.push new Post node, thread, thread.board
|
# Skip posts that we failed to parse.
|
||||||
catch err
|
errors = [] unless errors
|
||||||
# Skip posts that we failed to parse.
|
errors.push
|
||||||
errors = [] unless errors
|
message: "Parsing of Post No.#{data.no} failed. Post will be skipped."
|
||||||
errors.push
|
error: err
|
||||||
message: "Parsing of Post No.#{data.no} failed. Post will be skipped."
|
|
||||||
error: err
|
|
||||||
$.add thread.OP.nodes.root.parentNode, nodes
|
$.add thread.OP.nodes.root.parentNode, nodes
|
||||||
|
|
||||||
Main.handleErrors errors if errors
|
Main.handleErrors errors if errors
|
||||||
@ -679,11 +680,14 @@ Index =
|
|||||||
sortedThreads = []
|
sortedThreads = []
|
||||||
sortedThreadIDs = []
|
sortedThreadIDs = []
|
||||||
|
|
||||||
|
liveData = []
|
||||||
|
Index.liveThreadData.forEach (data) -> liveData.push data
|
||||||
|
|
||||||
{
|
{
|
||||||
'bump': ->
|
'bump': ->
|
||||||
sortedThreadIDs = Index.liveThreadIDs
|
sortedThreadIDs = Index.liveThreadData.keys
|
||||||
'lastreply': ->
|
'lastreply': ->
|
||||||
liveData = [Index.liveThreadData...].sort (a, b) ->
|
liveData.sort (a, b) ->
|
||||||
[..., a] = a.last_replies if 'last_replies' of a
|
[..., a] = a.last_replies if 'last_replies' of a
|
||||||
[..., b] = b.last_replies if 'last_replies' of b
|
[..., b] = b.last_replies if 'last_replies' of b
|
||||||
b.no - a.no
|
b.no - a.no
|
||||||
@ -692,15 +696,17 @@ Index =
|
|||||||
sortedThreadIDs.push data.no
|
sortedThreadIDs.push data.no
|
||||||
return
|
return
|
||||||
'birth': ->
|
'birth': ->
|
||||||
sortedThreadIDs = [Index.liveThreadIDs...].sort (a, b) -> b - a
|
sortedThreadIDs = [Index.liveThreadData.keys...].sort (a, b) -> b - a
|
||||||
'replycount': ->
|
'replycount': ->
|
||||||
liveData = [Index.liveThreadData...].sort((a, b) -> b.replies - a.replies)
|
liveData.sort (a, b) -> b.replies - a.replies
|
||||||
i = 0
|
i = 0
|
||||||
while data = liveData[i++]
|
while data = liveData[i++]
|
||||||
sortedThreadIDs.push data.no
|
sortedThreadIDs.push data.no
|
||||||
return
|
return
|
||||||
'filecount': ->
|
'filecount': ->
|
||||||
liveData = [Index.liveThreadData...].sort((a, b) -> b.images - a.images)
|
liveData = []
|
||||||
|
Index.liveThreadData.forEach (data) -> liveData.push data
|
||||||
|
liveData.sort (a, b) -> b.images - a.images
|
||||||
i = 0
|
i = 0
|
||||||
while data = liveData[i++]
|
while data = liveData[i++]
|
||||||
sortedThreadIDs.push data.no
|
sortedThreadIDs.push data.no
|
||||||
@ -730,6 +736,7 @@ Index =
|
|||||||
return
|
return
|
||||||
|
|
||||||
buildIndex: (infinite) ->
|
buildIndex: (infinite) ->
|
||||||
|
{sortedThreads} = Index
|
||||||
switch Conf['Index Mode']
|
switch Conf['Index Mode']
|
||||||
when 'paged', 'infinite'
|
when 'paged', 'infinite'
|
||||||
pageNum = Index.getCurrentPage()
|
pageNum = Index.getCurrentPage()
|
||||||
@ -738,21 +745,30 @@ Index =
|
|||||||
Index.pageNav Index.getMaxPageNum()
|
Index.pageNav Index.getMaxPageNum()
|
||||||
return
|
return
|
||||||
threadsPerPage = Index.getThreadsNumPerPage()
|
threadsPerPage = Index.getThreadsNumPerPage()
|
||||||
threads = Index.sortedThreads[threadsPerPage * pageNum ... threadsPerPage * (pageNum + 1)]
|
|
||||||
nodes = []
|
nodes = []
|
||||||
nodes.push thread.OP.nodes.root.parentNode for thread in threads
|
threads = []
|
||||||
Index.buildReplies threads
|
i = threadsPerPage * pageNum
|
||||||
nodes = Index.buildHRs nodes
|
max = i + threadsPerPage
|
||||||
|
while i < max and thread = sortedThreads[i++]
|
||||||
|
threads.push thread
|
||||||
|
nodes.push thread.OP.nodes.root.parentNode, $.el 'hr'
|
||||||
|
Index.buildReplies thread
|
||||||
|
|
||||||
Index.buildPagelist()
|
Index.buildPagelist()
|
||||||
Index.setPage()
|
Index.setPage()
|
||||||
|
|
||||||
when 'catalog'
|
when 'catalog'
|
||||||
nodes = Index.buildCatalogViews()
|
nodes = Index.buildCatalogViews()
|
||||||
Index.sizeCatalogViews nodes
|
Index.sizeCatalogViews nodes
|
||||||
|
|
||||||
else
|
else
|
||||||
nodes = []
|
nodes = []
|
||||||
nodes.push thread.OP.nodes.root.parentNode for thread in Index.sortedThreads
|
i = 0
|
||||||
Index.buildReplies Index.sortedThreads
|
while thread = sortedThreads[i++]
|
||||||
nodes = Index.buildHRs nodes
|
nodes.push thread.OP.nodes.root.parentNode, $.el 'hr'
|
||||||
|
Index.buildReplies thread
|
||||||
|
|
||||||
$.rmAll Index.root unless infinite
|
$.rmAll Index.root unless infinite
|
||||||
$.add Index.root, nodes
|
$.add Index.root, nodes
|
||||||
$.event 'IndexBuild', nodes
|
$.event 'IndexBuild', nodes
|
||||||
|
|||||||
@ -11,7 +11,7 @@ Navigate =
|
|||||||
|
|
||||||
@title = -> return
|
@title = -> return
|
||||||
|
|
||||||
@el = $.el 'div',
|
@el = $.el 'span',
|
||||||
id: 'breadCrumb'
|
id: 'breadCrumb'
|
||||||
|
|
||||||
Thread.callbacks.push
|
Thread.callbacks.push
|
||||||
@ -165,14 +165,16 @@ Navigate =
|
|||||||
|
|
||||||
navigate: (e) ->
|
navigate: (e) ->
|
||||||
return if @hostname isnt 'boards.4chan.org' or window.location.hostname is 'rs.4chan.org'
|
return if @hostname isnt 'boards.4chan.org' or window.location.hostname is 'rs.4chan.org'
|
||||||
return if e and (e.shiftKey or e.ctrlKey or (e.type is 'click' and e.button isnt 0)) # Not simply a left click
|
if e
|
||||||
|
if e.shiftKey or e.ctrlKey or (e.type is 'click' and e.button isnt 0) # Not simply a left click
|
||||||
|
return
|
||||||
|
|
||||||
if @pathname is Navigate.path
|
if @pathname is Navigate.path
|
||||||
if g.VIEW is 'thread'
|
if g.VIEW is 'thread'
|
||||||
ThreadUpdater.update()
|
ThreadUpdater.update()
|
||||||
else
|
else
|
||||||
Index.update()
|
unless Index.searchTest()
|
||||||
|
Index.update()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@ -77,11 +77,19 @@ body > hr {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* Index Features */
|
/* Index Features */
|
||||||
|
#index-menu {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
:root.thread #index-menu,
|
:root.thread #index-menu,
|
||||||
:root.index-loading .navLinks,
|
:root.index-loading .navLinks,
|
||||||
:root.index-loading .board,
|
:root.index-loading .board,
|
||||||
:root.index-loading .pagelist,
|
:root.index-loading .pagelist,
|
||||||
.index #returnlink {
|
:root.thread .pagelist {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
:root:not(.catalog-mode) #index-size,
|
||||||
|
:root:not(.catalog-mode) #index-size + .selectrice,
|
||||||
|
.index:not(.catalog-mode) #returnlink {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#index-menu .selectrice {
|
#index-menu .selectrice {
|
||||||
@ -107,23 +115,6 @@ body > hr {
|
|||||||
#index-search:not([data-searching]) + #index-search-clear {
|
#index-search:not([data-searching]) + #index-search-clear {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.index #returnlink,
|
|
||||||
.index #bottomlink,
|
|
||||||
.thread #index-last-refresh,
|
|
||||||
.thread #index-search-clear,
|
|
||||||
.thread #index-search {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#returnlink::before,
|
|
||||||
#bottomlink::before,
|
|
||||||
#index-last-refresh::before {
|
|
||||||
content: '[';
|
|
||||||
}
|
|
||||||
#returnlink::after,
|
|
||||||
#bottomlink::after,
|
|
||||||
#index-last-refresh::after {
|
|
||||||
content: ']';
|
|
||||||
}
|
|
||||||
.catalog-mode .board {
|
.catalog-mode .board {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|||||||
1553
src/General/css/style.css
Executable file
1553
src/General/css/style.css
Executable file
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,10 @@
|
|||||||
<span class=brackets-wrap id=returnlink><a href=.././>Return</a></span>
|
|
||||||
<span class=brackets-wrap id=bottomlink><a href="#bottom">Bottom</a></span>
|
|
||||||
<span id="index-menu">
|
<span id="index-menu">
|
||||||
<input type="search" id="index-search" class="field" placeholder="Search">
|
<input type="search" id="index-search" class="field" placeholder="Search">
|
||||||
<a id="index-search-clear" class="fa fa-times-circle" href="javascript:;"></a>
|
<a id="index-search-clear" class="fa fa-times-circle" href="javascript:;"></a>
|
||||||
|
|
||||||
<time id="index-last-refresh" title="Last index refresh">...</time>
|
<time id="index-last-refresh" title="Last index refresh">...</time>
|
||||||
<span id="hidden-label" hidden> — <span id="hidden-count"></span> <span id="hidden-toggle">[<a href="javascript:;">Show</a>]</span></span>
|
<span id="hidden-label" hidden> — <span id="hidden-count"></span> <span id="hidden-toggle">[<a href="javascript:;">Show</a>]</span></span>
|
||||||
|
<span style='flex: 1'></span>
|
||||||
<select id="index-mode" name="Index Mode">
|
<select id="index-mode" name="Index Mode">
|
||||||
<option disabled>Index Mode</option>
|
<option disabled>Index Mode</option>
|
||||||
<option value="paged">Paged</option>
|
<option value="paged">Paged</option>
|
||||||
@ -26,4 +25,6 @@
|
|||||||
<option value="small">Small</option>
|
<option value="small">Small</option>
|
||||||
<option value="large">Large</option>
|
<option value="large">Large</option>
|
||||||
</select>
|
</select>
|
||||||
</span>
|
</span>
|
||||||
|
<span class=brackets-wrap id=returnlink><a href=.././>Return</a></span>
|
||||||
|
<span class=brackets-wrap id=bottomlink><a href="#bottom">Bottom</a></span>
|
||||||
@ -23,6 +23,8 @@ Linkify =
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
return unless Linkify.regString.test @info.comment
|
||||||
|
|
||||||
test = /[^\s'"]+/g
|
test = /[^\s'"]+/g
|
||||||
space = /[\s'"]/
|
space = /[\s'"]/
|
||||||
|
|
||||||
|
|||||||
@ -35,4 +35,5 @@ Menu =
|
|||||||
clone
|
clone
|
||||||
|
|
||||||
toggle: (e) ->
|
toggle: (e) ->
|
||||||
Menu.menu.toggle e, @, Get.postFromNode @
|
fullID = $.x('ancestor::*[@data-full-i-d]', @).dataset.fullID
|
||||||
|
Menu.menu.toggle e, @, g.posts[fullID]
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
PSAHiding =
|
PSAHiding =
|
||||||
init: ->
|
init: ->
|
||||||
return unless Conf['Announcement Hiding']
|
|
||||||
$.addClass doc, 'hide-announcement'
|
$.addClass doc, 'hide-announcement'
|
||||||
$.on d, '4chanXInitFinished', @setup
|
$.on d, '4chanXInitFinished', @setup
|
||||||
|
|
||||||
|
|||||||
@ -40,7 +40,7 @@ ThreadStats =
|
|||||||
if Conf['Updater and Stats in Header']
|
if Conf['Updater and Stats in Header']
|
||||||
Header.rmShortcut @dialog
|
Header.rmShortcut @dialog
|
||||||
else
|
else
|
||||||
$.rm d.body, sc
|
$.rm @dialog
|
||||||
|
|
||||||
clearTimeout @timeout # a possible race condition might be that this won't clear in time, but the resulting error will prevent issues anyways.
|
clearTimeout @timeout # a possible race condition might be that this won't clear in time, but the resulting error will prevent issues anyways.
|
||||||
|
|
||||||
|
|||||||
@ -606,6 +606,7 @@ QR =
|
|||||||
|
|
||||||
flagsInput: ->
|
flagsInput: ->
|
||||||
{nodes} = QR
|
{nodes} = QR
|
||||||
|
return unless nodes
|
||||||
if nodes.flag
|
if nodes.flag
|
||||||
$.rm nodes.flag
|
$.rm nodes.flag
|
||||||
delete nodes.flag
|
delete nodes.flag
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user