Merge branch 'mayhem' into v3
Conflicts: CHANGELOG.md CONTRIBUTING.md css/style.css html/General/Settings-section-Main.html json/archives.json package.json src/Archive/Redirect.coffee src/General/Header.coffee src/General/Main.coffee src/General/Settings.coffee src/General/lib/$.coffee src/General/lib/thread.class src/Linkification/Linkify.coffee src/Miscellaneous/AnnouncementHiding.coffee src/Monitoring/ThreadStats.coffee
This commit is contained in:
commit
b6749b91a5
@ -1,5 +1,7 @@
|
|||||||
### v1.3.2
|
**MayhemYDG**:
|
||||||
*2014-01-12*
|
- Added a `Reset Settings` button in the settings.
|
||||||
|
- More stability update.
|
||||||
|
- Stability update.
|
||||||
|
|
||||||
**seaweedchan**:
|
**seaweedchan**:
|
||||||
- Fix Menu errors on older Firefox versions, such as the ESR
|
- Fix Menu errors on older Firefox versions, such as the ESR
|
||||||
|
|||||||
48
CONTRIBUTING.md
Normal file
48
CONTRIBUTING.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
## Reporting bugs and suggestions
|
||||||
|
|
||||||
|
Reporting bugs:
|
||||||
|
|
||||||
|
1. Make sure both your **browser** and **4chan X** are up to date.<br>
|
||||||
|
Only **Chrome**, **Firefox** and **Opera** are supported.<br>
|
||||||
|
**SRWare Iron**, **Firefox ESR**, **Pale Moon**, **Waterfox**, and other derivatives are not supported, use them at your own risk.
|
||||||
|
2. Look at the list of [known problems and solutions](https://github.com/MayhemYDG/4chan-x/wiki/FAQ#known-problems).
|
||||||
|
3. Disable your other extensions & scripts to identify conflicts.
|
||||||
|
4. If your issue persists, open a [new issue](https://github.com/MayhemYDG/4chan-x/issues) with the following information:
|
||||||
|
1. Precise steps to reproduce the problem, with the expected and actual results.
|
||||||
|
2. [Console errors](https://github.com/MayhemYDG/4chan-x/wiki/FAQ#console-errors), if any.
|
||||||
|
3. 4chan X version, browser variant, browser version, and Greasemonkey version if you are using it.
|
||||||
|
4. Your exported settings. If your settings contains sensible information (e.g. personas), edit the text file manually.
|
||||||
|
|
||||||
|
Respect these guidelines:
|
||||||
|
- Describe the issue clearly, put some effort into it. A one-liner isn't a good enough description.
|
||||||
|
- If you want to get your suggestion implemented sooner, make it convincing.
|
||||||
|
- If you want to criticize, make it convincing and constructive.
|
||||||
|
- Be mature. Act like an idiot and you will be blocked without warning.
|
||||||
|
|
||||||
|
## Development & Contribution
|
||||||
|
|
||||||
|
### Get started
|
||||||
|
|
||||||
|
- Install [node.js](http://nodejs.org/).
|
||||||
|
- Install [Grunt's CLI](http://gruntjs.com/) with `npm install -g grunt-cli`.
|
||||||
|
- Clone 4chan X.
|
||||||
|
- `cd` into it.
|
||||||
|
- Install/Update 4chan X dependencies with `npm install`.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
- Build with `grunt`.
|
||||||
|
- Continuously build with `grunt watch`.
|
||||||
|
|
||||||
|
### Release
|
||||||
|
|
||||||
|
- Update the version with `grunt patch`, `grunt minor` or `grunt major`.
|
||||||
|
- Release with `grunt release`.
|
||||||
|
|
||||||
|
Note: this is only used to release new 4chan X versions, and is **not** needed or wanted in pull requests.
|
||||||
|
|
||||||
|
### Contribute
|
||||||
|
|
||||||
|
- Edit the sources.
|
||||||
|
- If the edits affect regular users, edit the changelog.
|
||||||
|
- Open a pull request.
|
||||||
2
LICENSE
2
LICENSE
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* 4chan X - Version 1.3.2 - 2014-01-21
|
* 4chan X - Version 1.3.2 - 2014-01-22
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name 4chan X
|
// @name 4chan X
|
||||||
// @version 1.3.2
|
// @version 1.3.2
|
||||||
// @minGMVer 1.13
|
// @minGMVer 1.14
|
||||||
// @minFFVer 26
|
// @minFFVer 26
|
||||||
// @namespace 4chan-X
|
// @namespace 4chan-X
|
||||||
// @description Cross-browser userscript for maximum lurking on 4chan.
|
// @description Cross-browser userscript for maximum lurking on 4chan.
|
||||||
@ -13,6 +13,7 @@
|
|||||||
// @grant GM_getValue
|
// @grant GM_getValue
|
||||||
// @grant GM_setValue
|
// @grant GM_setValue
|
||||||
// @grant GM_deleteValue
|
// @grant GM_deleteValue
|
||||||
|
// @grant GM_listValues
|
||||||
// @grant GM_openInTab
|
// @grant GM_openInTab
|
||||||
// @run-at document-start
|
// @run-at document-start
|
||||||
// @updateURL https://github.com/seaweedchan/4chan-x/raw/stable/builds/4chan-X.meta.js
|
// @updateURL https://github.com/seaweedchan/4chan-x/raw/stable/builds/4chan-X.meta.js
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
18
package.json
18
package.json
@ -21,22 +21,22 @@
|
|||||||
"min": {
|
"min": {
|
||||||
"chrome": "31",
|
"chrome": "31",
|
||||||
"firefox": "26",
|
"firefox": "26",
|
||||||
"greasemonkey": "1.13"
|
"greasemonkey": "1.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"font-awesome": "https://github.com/FortAwesome/Font-Awesome/archive/v4.0.3.tar.gz",
|
"font-awesome": "~4.0.3",
|
||||||
"grunt": "~0.4.1",
|
"grunt": "~0.4.2",
|
||||||
"grunt-bump": "~0.0.11",
|
"grunt-bump": "~0.0.13",
|
||||||
"grunt-concurrent": "~0.4.0",
|
"grunt-concurrent": "~0.4.3",
|
||||||
"grunt-contrib-clean": "~0.5.0",
|
"grunt-contrib-clean": "~0.5.0",
|
||||||
"grunt-contrib-coffee": "~0.8.0",
|
"grunt-contrib-coffee": "~0.8.2",
|
||||||
"grunt-contrib-compress": "~0.5.2",
|
"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.0",
|
"grunt-shell": "~0.6.3",
|
||||||
"load-grunt-tasks": "~0.2.0"
|
"load-grunt-tasks": "~0.2.1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
Redirect =
|
Redirect =
|
||||||
|
|
||||||
init: ->
|
init: ->
|
||||||
o =
|
o =
|
||||||
thread: {}
|
thread: {}
|
||||||
@ -52,8 +51,8 @@ Redirect =
|
|||||||
software: "foolfuuka"
|
software: "foolfuuka"
|
||||||
,
|
,
|
||||||
name: "4plebs"
|
name: "4plebs"
|
||||||
boards: ["hr", "o", "pol", "s4s", "tg", "tv", "x"]
|
boards: ["adv", "hr", "o", "pol", "s4s", "tg", "tv", "x"]
|
||||||
files: ["hr", "o", "pol", "s4s", "tg", "tv", "x"]
|
files: ["adv", "hr", "o", "pol", "s4s", "tg", "tv", "x"]
|
||||||
data:
|
data:
|
||||||
domain: "archive.4plebs.org"
|
domain: "archive.4plebs.org"
|
||||||
http: true
|
http: true
|
||||||
@ -68,6 +67,15 @@ Redirect =
|
|||||||
http: true
|
http: true
|
||||||
https: true
|
https: true
|
||||||
software: "foolfuuka"
|
software: "foolfuuka"
|
||||||
|
,
|
||||||
|
name: "Love is Over"
|
||||||
|
boards: ["d", "i"],
|
||||||
|
files: ["d", "i"]
|
||||||
|
data:
|
||||||
|
domain: "loveisover.me"
|
||||||
|
http: true
|
||||||
|
https: true
|
||||||
|
software: "foolfuuka"
|
||||||
,
|
,
|
||||||
name: "Install Gentoo"
|
name: "Install Gentoo"
|
||||||
boards: ["diy", "g", "sci"]
|
boards: ["diy", "g", "sci"]
|
||||||
@ -82,7 +90,7 @@ Redirect =
|
|||||||
boards: ["cgl", "g", "mu", "w"]
|
boards: ["cgl", "g", "mu", "w"]
|
||||||
files: ["cgl", "g", "mu", "w"]
|
files: ["cgl", "g", "mu", "w"]
|
||||||
data:
|
data:
|
||||||
domain: "rbt.asia"
|
domain: "archive.rebeccablacktech.com"
|
||||||
http: true
|
http: true
|
||||||
https: true
|
https: true
|
||||||
software: "fuuka"
|
software: "fuuka"
|
||||||
@ -100,9 +108,33 @@ Redirect =
|
|||||||
files: ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "tg", "vr"]
|
files: ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "tg", "vr"]
|
||||||
data:
|
data:
|
||||||
domain: "fuuka.warosu.org"
|
domain: "fuuka.warosu.org"
|
||||||
http: true
|
|
||||||
https: true
|
https: true
|
||||||
software: "fuuka"
|
software: "fuuka"
|
||||||
|
,
|
||||||
|
name: "fgts"
|
||||||
|
boards: ["soc"]
|
||||||
|
files: ["soc"]
|
||||||
|
data:
|
||||||
|
domain: "fgts.eu"
|
||||||
|
http: true
|
||||||
|
https: true
|
||||||
|
software: "foolfuuka"
|
||||||
|
,
|
||||||
|
name: "maware"
|
||||||
|
boards: ["t"]
|
||||||
|
files: ["t"]
|
||||||
|
data:
|
||||||
|
domain: "archive.mawa.re"
|
||||||
|
http: true
|
||||||
|
software: "foolfuuka"
|
||||||
|
,
|
||||||
|
name: "installgentoo.com"
|
||||||
|
boards: ["g", "t"]
|
||||||
|
files: ["g", "t"]
|
||||||
|
data:
|
||||||
|
domain: "chan.installgentoo.com"
|
||||||
|
http: true
|
||||||
|
software: "foolfuuka"
|
||||||
,
|
,
|
||||||
name: "Foolz Beta"
|
name: "Foolz Beta"
|
||||||
boards: ["a", "co", "d", "gd", "h", "jp", "m", "mlp", "sp", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
|
boards: ["a", "co", "d", "gd", "h", "jp", "m", "mlp", "sp", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
|
||||||
@ -113,15 +145,6 @@ Redirect =
|
|||||||
https: true
|
https: true
|
||||||
withCredentials: true
|
withCredentials: true
|
||||||
software: "foolfuuka"
|
software: "foolfuuka"
|
||||||
,
|
|
||||||
name: "Love is Over"
|
|
||||||
boards: ["d", "i"],
|
|
||||||
files: ["d", "i"]
|
|
||||||
data:
|
|
||||||
domain: "loveisover.me"
|
|
||||||
http: true
|
|
||||||
https: true
|
|
||||||
software: "foolfuuka"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
to: (dest, data) ->
|
to: (dest, data) ->
|
||||||
|
|||||||
@ -58,7 +58,7 @@ ThreadHiding =
|
|||||||
$.cache "//a.4cdn.org/#{g.BOARD}/threads.json", ->
|
$.cache "//a.4cdn.org/#{g.BOARD}/threads.json", ->
|
||||||
return unless @status is 200
|
return unless @status is 200
|
||||||
threads = {}
|
threads = {}
|
||||||
for page in JSON.parse @response
|
for page in @response
|
||||||
for thread in page.threads
|
for thread in page.threads
|
||||||
if thread.no of hiddenThreadsOnCatalog
|
if thread.no of hiddenThreadsOnCatalog
|
||||||
threads[thread.no] = hiddenThreadsOnCatalog[thread.no]
|
threads[thread.no] = hiddenThreadsOnCatalog[thread.no]
|
||||||
|
|||||||
@ -80,6 +80,7 @@ Get =
|
|||||||
$.cache url,
|
$.cache url,
|
||||||
-> Get.archivedPost @, boardID, postID, root, context
|
-> Get.archivedPost @, boardID, postID, root, context
|
||||||
,
|
,
|
||||||
|
responseType: 'json'
|
||||||
withCredentials: url.archive.withCredentials
|
withCredentials: url.archive.withCredentials
|
||||||
insert: (post, root, context) ->
|
insert: (post, root, context) ->
|
||||||
# Stop here if the container has been removed while loading.
|
# Stop here if the container has been removed while loading.
|
||||||
@ -118,7 +119,7 @@ Get =
|
|||||||
"Error #{req.statusText} (#{req.status})."
|
"Error #{req.statusText} (#{req.status})."
|
||||||
return
|
return
|
||||||
|
|
||||||
posts = JSON.parse(req.response).posts
|
{posts} = req.response
|
||||||
Build.spoilerRange[boardID] = posts[0].custom_spoiler
|
Build.spoilerRange[boardID] = posts[0].custom_spoiler
|
||||||
for post in posts
|
for post in posts
|
||||||
break if post.no is postID # we found it!
|
break if post.no is postID # we found it!
|
||||||
@ -149,7 +150,7 @@ Get =
|
|||||||
Get.insert post, root, context
|
Get.insert post, root, context
|
||||||
return
|
return
|
||||||
|
|
||||||
data = JSON.parse req.response
|
data = req.response
|
||||||
if data.error
|
if data.error
|
||||||
$.addClass root, 'warning'
|
$.addClass root, 'warning'
|
||||||
root.textContent = data.error
|
root.textContent = data.error
|
||||||
@ -227,4 +228,4 @@ Get =
|
|||||||
'[/moot]': '</div>'
|
'[/moot]': '</div>'
|
||||||
'[banned]': '<strong style="color: red;">'
|
'[banned]': '<strong style="color: red;">'
|
||||||
'[/banned]': '</strong>'
|
'[/banned]': '</strong>'
|
||||||
}[text] or text.replace ':lit', ''
|
}[text] or text.replace ':lit', ''
|
||||||
|
|||||||
@ -305,17 +305,15 @@ Header =
|
|||||||
|
|
||||||
toggleHideBarOnScroll: (e) ->
|
toggleHideBarOnScroll: (e) ->
|
||||||
hide = @checked
|
hide = @checked
|
||||||
$.set 'Header auto-hide on scroll', hide
|
$.cb.checked.call @
|
||||||
Header.setHideBarOnScroll hide
|
Header.setHideBarOnScroll hide
|
||||||
|
|
||||||
hideBarOnScroll: ->
|
hideBarOnScroll: ->
|
||||||
offsetY = window.pageYOffset
|
offsetY = window.pageYOffset
|
||||||
if offsetY > (Header.previousOffset or 0)
|
if offsetY > (Header.previousOffset or 0)
|
||||||
$.addClass Header.bar, 'autohide'
|
$.addClass Header.bar, 'autohide', 'scroll'
|
||||||
$.addClass Header.bar, 'scroll'
|
|
||||||
else
|
else
|
||||||
$.rmClass Header.bar, 'autohide'
|
$.rmClass Header.bar, 'autohide', 'scroll'
|
||||||
$.rmClass Header.bar, 'scroll'
|
|
||||||
Header.previousOffset = offsetY
|
Header.previousOffset = offsetY
|
||||||
|
|
||||||
setBarPosition: (bottom) ->
|
setBarPosition: (bottom) ->
|
||||||
@ -389,9 +387,21 @@ Header =
|
|||||||
scrollTo: (root, down, needed) ->
|
scrollTo: (root, down, needed) ->
|
||||||
if down
|
if down
|
||||||
x = Header.getBottomOf root
|
x = Header.getBottomOf root
|
||||||
|
if Conf['Header auto-hide on scroll'] and Conf['Bottom header']
|
||||||
|
{height} = Header.bar.getBoundingClientRect()
|
||||||
|
if x <= 0
|
||||||
|
x += height if !Header.isHidden()
|
||||||
|
else
|
||||||
|
x -= height if Header.isHidden()
|
||||||
window.scrollBy 0, -x unless needed and x >= 0
|
window.scrollBy 0, -x unless needed and x >= 0
|
||||||
else
|
else
|
||||||
x = Header.getTopOf root
|
x = Header.getTopOf root
|
||||||
|
if Conf['Header auto-hide on scroll'] and !Conf['Bottom header']
|
||||||
|
{height} = Header.bar.getBoundingClientRect()
|
||||||
|
if x >= 0
|
||||||
|
x += height if !Header.isHidden()
|
||||||
|
else
|
||||||
|
x -= height if Header.isHidden()
|
||||||
window.scrollBy 0, x unless needed and x >= 0
|
window.scrollBy 0, x unless needed and x >= 0
|
||||||
|
|
||||||
scrollToIfNeeded: (root, down) ->
|
scrollToIfNeeded: (root, down) ->
|
||||||
@ -411,6 +421,12 @@ Header =
|
|||||||
headRect = Header.toggle.getBoundingClientRect()
|
headRect = Header.toggle.getBoundingClientRect()
|
||||||
bottom -= clientHeight - headRect.bottom + headRect.height
|
bottom -= clientHeight - headRect.bottom + headRect.height
|
||||||
bottom
|
bottom
|
||||||
|
isHidden: ->
|
||||||
|
{top} = Header.bar.getBoundingClientRect()
|
||||||
|
if Conf['Bottom header']
|
||||||
|
top is doc.clientHeight
|
||||||
|
else
|
||||||
|
top < 0
|
||||||
|
|
||||||
addShortcut: (el) ->
|
addShortcut: (el) ->
|
||||||
shortcut = $.el 'span',
|
shortcut = $.el 'span',
|
||||||
|
|||||||
@ -279,7 +279,7 @@ Index =
|
|||||||
|
|
||||||
try
|
try
|
||||||
if req.status is 200
|
if req.status is 200
|
||||||
Index.parse JSON.parse(req.response), pageNum
|
Index.parse req.response, pageNum
|
||||||
else if req.status is 304 and pageNum?
|
else if req.status is 304 and pageNum?
|
||||||
Index.pageNav pageNum
|
Index.pageNav pageNum
|
||||||
catch err
|
catch err
|
||||||
@ -475,6 +475,7 @@ Index =
|
|||||||
else
|
else
|
||||||
pageNum = Index.getCurrentPage()
|
pageNum = Index.getCurrentPage()
|
||||||
else
|
else
|
||||||
|
return unless Index.searchInput.dataset.searching
|
||||||
pageNum = Index.pageBeforeSearch
|
pageNum = Index.pageBeforeSearch
|
||||||
delete Index.pageBeforeSearch
|
delete Index.pageBeforeSearch
|
||||||
<% if (type === 'userscript') { %>
|
<% if (type === 'userscript') { %>
|
||||||
|
|||||||
@ -78,16 +78,9 @@ Main =
|
|||||||
return if !Main.isThisPageLegit() or $.hasClass doc, 'fourchan-x'
|
return if !Main.isThisPageLegit() or $.hasClass doc, 'fourchan-x'
|
||||||
# disable the mobile layout
|
# disable the mobile layout
|
||||||
$('link[href*=mobile]', d.head)?.disabled = true
|
$('link[href*=mobile]', d.head)?.disabled = true
|
||||||
<% if (type === 'crx') { %>
|
$.addClass doc, 'fourchan-x', 'seaweedchan', g.VIEW, '<% if (type === 'crx') { %>blink<% } else { %>gecko<% } %>'
|
||||||
$.addClass doc, 'blink'
|
|
||||||
<% } else { %>
|
|
||||||
$.addClass doc, 'gecko'
|
|
||||||
<% } %>
|
|
||||||
$.addClass doc, 'fourchan-x'
|
|
||||||
$.addClass doc, 'seaweedchan'
|
|
||||||
$.addClass doc, g.VIEW
|
|
||||||
$.addStyle Main.css
|
$.addStyle Main.css
|
||||||
|
|
||||||
Main.setClass()
|
Main.setClass()
|
||||||
|
|
||||||
setClass: ->
|
setClass: ->
|
||||||
@ -124,6 +117,7 @@ Main =
|
|||||||
# Something might have gone wrong!
|
# Something might have gone wrong!
|
||||||
Main.initStyle()
|
Main.initStyle()
|
||||||
|
|
||||||
|
# 4chan Pass Link
|
||||||
if styleSelector = $.id 'styleSelector'
|
if styleSelector = $.id 'styleSelector'
|
||||||
passLink = $.el 'a',
|
passLink = $.el 'a',
|
||||||
textContent: '4chan Pass'
|
textContent: '4chan Pass'
|
||||||
@ -134,12 +128,18 @@ Main =
|
|||||||
'left=0,top=0,width=500,height=255,toolbar=0,resizable=0'
|
'left=0,top=0,width=500,height=255,toolbar=0,resizable=0'
|
||||||
$.before styleSelector.previousSibling, [$.tn '['; passLink, $.tn ']\u00A0\u00A0']
|
$.before styleSelector.previousSibling, [$.tn '['; passLink, $.tn ']\u00A0\u00A0']
|
||||||
|
|
||||||
|
# Parse HTML or skip it and start building from JSON.
|
||||||
unless Conf['JSON Navigation'] and g.VIEW is 'index'
|
unless Conf['JSON Navigation'] and g.VIEW is 'index'
|
||||||
Main.initThread()
|
Main.initThread()
|
||||||
else
|
else
|
||||||
$.event '4chanXInitFinished'
|
$.event '4chanXInitFinished'
|
||||||
|
|
||||||
<% if (type === 'userscript') { %>
|
<% if (type === 'userscript') { %>
|
||||||
|
test = $.el 'span'
|
||||||
|
test.classList.add 'a', 'b'
|
||||||
|
if test.className isnt 'a b'
|
||||||
|
new Notice 'warning', "Your version of Firefox is outdated (v<%= meta.min.firefox %> minimum) and <%= meta.name %> may not operate correctly.", 30
|
||||||
|
|
||||||
GMver = GM_info.version.split '.'
|
GMver = GM_info.version.split '.'
|
||||||
for v, i in "<%= meta.min.greasemonkey %>".split '.'
|
for v, i in "<%= meta.min.greasemonkey %>".split '.'
|
||||||
continue if v is GMver[i]
|
continue if v is GMver[i]
|
||||||
@ -176,6 +176,17 @@ Main =
|
|||||||
Main.callbackNodesDB Post, posts, ->
|
Main.callbackNodesDB Post, posts, ->
|
||||||
$.event '4chanXInitFinished'
|
$.event '4chanXInitFinished'
|
||||||
|
|
||||||
|
$.get 'previousversion', null, ({previousversion}) ->
|
||||||
|
return if previousversion is g.VERSION
|
||||||
|
if previousversion
|
||||||
|
changelog = '<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md'
|
||||||
|
el = $.el 'span',
|
||||||
|
innerHTML: "<%= meta.name %> has been updated to <a href='#{changelog}' target=_blank>version #{g.VERSION}</a>."
|
||||||
|
new Notice 'info', el, 15
|
||||||
|
else
|
||||||
|
Settings.open()
|
||||||
|
$.set 'previousversion', g.VERSION
|
||||||
|
|
||||||
callbackNodes: (klass, nodes) ->
|
callbackNodes: (klass, nodes) ->
|
||||||
i = 0
|
i = 0
|
||||||
cb = klass.callbacks
|
cb = klass.callbacks
|
||||||
|
|||||||
@ -249,7 +249,7 @@ Navigate =
|
|||||||
Navigate.title()
|
Navigate.title()
|
||||||
|
|
||||||
try
|
try
|
||||||
Navigate.parse JSON.parse(req.response).posts
|
Navigate.parse req.response.posts
|
||||||
catch err
|
catch err
|
||||||
console.error 'Navigate failure:'
|
console.error 'Navigate failure:'
|
||||||
console.log err
|
console.log err
|
||||||
|
|||||||
@ -9,19 +9,6 @@ Settings =
|
|||||||
|
|
||||||
Header.addShortcut link
|
Header.addShortcut link
|
||||||
|
|
||||||
$.get 'previousversion', null, (item) ->
|
|
||||||
if previous = item['previousversion']
|
|
||||||
return if previous is g.VERSION
|
|
||||||
|
|
||||||
changelog = '<%= meta.repo %>blob/<%= meta.mainBranch %>/CHANGELOG.md'
|
|
||||||
el = $.el 'span',
|
|
||||||
innerHTML: "<%= meta.name %> has been updated to <a href='#{changelog}' target=_blank>version #{g.VERSION}</a>."
|
|
||||||
if Conf['Show Updated Notifications']
|
|
||||||
new Notice 'info', el, 30
|
|
||||||
else
|
|
||||||
$.on d, '4chanXInitFinished', Settings.open
|
|
||||||
$.set 'previousversion', g.VERSION
|
|
||||||
|
|
||||||
Settings.addSection 'Main', Settings.main
|
Settings.addSection 'Main', Settings.main
|
||||||
Settings.addSection 'Filter', Settings.filter
|
Settings.addSection 'Filter', Settings.filter
|
||||||
Settings.addSection 'Sauce', Settings.sauce
|
Settings.addSection 'Sauce', Settings.sauce
|
||||||
@ -37,7 +24,6 @@ Settings =
|
|||||||
localStorage.setItem '4chan-settings', JSON.stringify settings
|
localStorage.setItem '4chan-settings', JSON.stringify settings
|
||||||
|
|
||||||
open: (openSection) ->
|
open: (openSection) ->
|
||||||
$.off d, '4chanXInitFinished', Settings.open
|
|
||||||
return if Settings.dialog
|
return if Settings.dialog
|
||||||
$.event 'CloseMenu'
|
$.event 'CloseMenu'
|
||||||
|
|
||||||
@ -53,6 +39,7 @@ Settings =
|
|||||||
|
|
||||||
$.on $('.export', Settings.dialog), 'click', Settings.export
|
$.on $('.export', Settings.dialog), 'click', Settings.export
|
||||||
$.on $('.import', Settings.dialog), 'click', Settings.import
|
$.on $('.import', Settings.dialog), 'click', Settings.import
|
||||||
|
$.on $('.reset', Settings.dialog), 'click', Settings.reset
|
||||||
$.on $('input', Settings.dialog), 'change', Settings.onImport
|
$.on $('input', Settings.dialog), 'change', Settings.onImport
|
||||||
|
|
||||||
links = []
|
links = []
|
||||||
@ -124,56 +111,39 @@ Settings =
|
|||||||
div = $.el 'div',
|
div = $.el 'div',
|
||||||
innerHTML: "<button></button><span class=description>: Clear manually-hidden threads and posts on all boards. Reload the page to apply."
|
innerHTML: "<button></button><span class=description>: Clear manually-hidden threads and posts on all boards. Reload the page to apply."
|
||||||
button = $ 'button', div
|
button = $ 'button', div
|
||||||
hiddenNum = 0
|
$.get {hiddenThreads: {}, hiddenPosts: {}}, ({hiddenThreads, hiddenPosts}) ->
|
||||||
$.get 'hiddenThreads', boards: {}, (item) ->
|
hiddenNum = 0
|
||||||
for ID, board of item.hiddenThreads.boards
|
for ID, board of hiddenThreads.boards
|
||||||
|
hiddenNum += Object.keys(board).length
|
||||||
|
for ID, board of hiddenPosts.boards
|
||||||
for ID, thread of board
|
for ID, thread of board
|
||||||
hiddenNum++
|
hiddenNum += Object.keys(thread).length
|
||||||
button.textContent = "Hidden: #{hiddenNum}"
|
|
||||||
$.get 'hiddenPosts', boards: {}, (item) ->
|
|
||||||
for ID, board of item.hiddenPosts.boards
|
|
||||||
for ID, thread of board
|
|
||||||
for ID, post of thread
|
|
||||||
hiddenNum++
|
|
||||||
button.textContent = "Hidden: #{hiddenNum}"
|
button.textContent = "Hidden: #{hiddenNum}"
|
||||||
$.on button, 'click', ->
|
$.on button, 'click', ->
|
||||||
@textContent = 'Hidden: 0'
|
@textContent = 'Hidden: 0'
|
||||||
$.get 'hiddenThreads', boards: {}, (item) ->
|
$.get 'hiddenThreads', {}, ({hiddenThreads}) ->
|
||||||
for boardID of item.hiddenThreads.boards
|
for boardID of hiddenThreads.boards
|
||||||
localStorage.removeItem "4chan-hide-t-#{boardID}"
|
localStorage.removeItem "4chan-hide-t-#{boardID}"
|
||||||
$.delete ['hiddenThreads', 'hiddenPosts']
|
$.delete ['hiddenThreads', 'hiddenPosts']
|
||||||
$.after $('input[name="Stubs"]', section).parentNode.parentNode, div
|
$.after $('input[name="Stubs"]', section).parentNode.parentNode, div
|
||||||
export: (now, data) ->
|
export: ->
|
||||||
unless typeof now is 'number'
|
# Make sure to export the most recent data.
|
||||||
now = Date.now()
|
$.get Conf, (Conf) ->
|
||||||
data =
|
# XXX don't export archives.
|
||||||
version: g.VERSION
|
delete Conf['archives']
|
||||||
date: now
|
Settings.downloadExport {version: g.VERSION, date: Date.now(), Conf}
|
||||||
for db in DataBoard.keys
|
downloadExport: (data) ->
|
||||||
Conf[db] = boards: {}
|
|
||||||
# Make sure to export the most recent data.
|
|
||||||
$.get Conf, (Conf) ->
|
|
||||||
# XXX don't export archives.
|
|
||||||
delete Conf['archives']
|
|
||||||
data.Conf = Conf
|
|
||||||
Settings.export now, data
|
|
||||||
return
|
|
||||||
a = $.el 'a',
|
a = $.el 'a',
|
||||||
className: 'warning'
|
download: "<%= meta.name %> v#{g.VERSION}-#{data.date}.json"
|
||||||
textContent: 'Save me!'
|
|
||||||
download: "<%= meta.name %> v#{g.VERSION}-#{now}.json"
|
|
||||||
href: "data:application/json;base64,#{btoa unescape encodeURIComponent JSON.stringify data, null, 2}"
|
href: "data:application/json;base64,#{btoa unescape encodeURIComponent JSON.stringify data, null, 2}"
|
||||||
target: '_blank'
|
|
||||||
<% if (type === 'userscript') { %>
|
<% if (type === 'userscript') { %>
|
||||||
# XXX Firefox won't let us download automatically.
|
|
||||||
p = $ '.imp-exp-result', Settings.dialog
|
p = $ '.imp-exp-result', Settings.dialog
|
||||||
$.rmAll p
|
$.rmAll p
|
||||||
$.add p, a
|
$.add p, a
|
||||||
<% } else { %>
|
|
||||||
a.click()
|
|
||||||
<% } %>
|
<% } %>
|
||||||
|
a.click()
|
||||||
import: ->
|
import: ->
|
||||||
@nextElementSibling.click()
|
$('input', @parentNode).click()
|
||||||
onImport: ->
|
onImport: ->
|
||||||
return unless file = @files[0]
|
return unless file = @files[0]
|
||||||
output = $('.imp-exp-result')
|
output = $('.imp-exp-result')
|
||||||
@ -183,8 +153,7 @@ Settings =
|
|||||||
reader = new FileReader()
|
reader = new FileReader()
|
||||||
reader.onload = (e) ->
|
reader.onload = (e) ->
|
||||||
try
|
try
|
||||||
data = JSON.parse e.target.result
|
Settings.loadSettings JSON.parse e.target.result
|
||||||
Settings.loadSettings data
|
|
||||||
if confirm 'Import successful. Reload now?'
|
if confirm 'Import successful. Reload now?'
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
catch err
|
catch err
|
||||||
@ -194,6 +163,11 @@ Settings =
|
|||||||
loadSettings: (data) ->
|
loadSettings: (data) ->
|
||||||
version = data.version.split '.'
|
version = data.version.split '.'
|
||||||
if version[0] is '2'
|
if version[0] is '2'
|
||||||
|
convertSettings = (data, map) ->
|
||||||
|
for prevKey, newKey of map
|
||||||
|
data.Conf[newKey] = data.Conf[prevKey] if newKey
|
||||||
|
delete data.Conf[prevKey]
|
||||||
|
data
|
||||||
data = Settings.convertSettings data,
|
data = Settings.convertSettings data,
|
||||||
# General confs
|
# General confs
|
||||||
'Disable 4chan\'s extension': ''
|
'Disable 4chan\'s extension': ''
|
||||||
@ -265,11 +239,9 @@ Settings =
|
|||||||
data.Conf['watchedThreads'] = boards: ThreadWatcher.convert data.Conf['WatchedThreads']
|
data.Conf['watchedThreads'] = boards: ThreadWatcher.convert data.Conf['WatchedThreads']
|
||||||
delete data.Conf['WatchedThreads']
|
delete data.Conf['WatchedThreads']
|
||||||
$.set data.Conf
|
$.set data.Conf
|
||||||
convertSettings: (data, map) ->
|
reset: ->
|
||||||
for prevKey, newKey of map
|
if confirm 'Your current settings will be entirely wiped, are you sure?'
|
||||||
data.Conf[newKey] = data.Conf[prevKey] if newKey
|
$.clear -> window.location.reload() if confirm 'Reset successful. Reload now?'
|
||||||
delete data.Conf[prevKey]
|
|
||||||
data
|
|
||||||
|
|
||||||
filter: (section) ->
|
filter: (section) ->
|
||||||
section.innerHTML = <%= importHTML('Settings/Filter-select') %>
|
section.innerHTML = <%= importHTML('Settings/Filter-select') %>
|
||||||
|
|||||||
@ -157,6 +157,9 @@ UI = do ->
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
|
onFocus: (e) =>
|
||||||
|
e.stopPropagation()
|
||||||
|
@focus e.target
|
||||||
focus: (entry) ->
|
focus: (entry) ->
|
||||||
while focused = $.x 'parent::*/child::*[contains(@class,"focused")]', entry
|
while focused = $.x 'parent::*/child::*[contains(@class,"focused")]', entry
|
||||||
$.rmClass focused, 'focused'
|
$.rmClass focused, 'focused'
|
||||||
@ -199,10 +202,7 @@ UI = do ->
|
|||||||
parseEntry: (entry) ->
|
parseEntry: (entry) ->
|
||||||
{el, subEntries} = entry
|
{el, subEntries} = entry
|
||||||
$.addClass el, 'entry'
|
$.addClass el, 'entry'
|
||||||
$.on el, 'focus mouseover', ((e) ->
|
$.on el, 'focus mouseover', @onFocus
|
||||||
e.stopPropagation()
|
|
||||||
@focus el
|
|
||||||
).bind @
|
|
||||||
el.style.order = entry.order or 100
|
el.style.order = entry.order or 100
|
||||||
return unless subEntries
|
return unless subEntries
|
||||||
$.addClass el, 'has-submenu'
|
$.addClass el, 'has-submenu'
|
||||||
|
|||||||
@ -653,6 +653,15 @@ span.hide-announcement {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: 1px dashed;
|
border-bottom: 1px dashed;
|
||||||
}
|
}
|
||||||
|
@supports (text-decoration-style: dashed) or (-moz-text-decoration-style: dashed) {
|
||||||
|
.quotelink.forwardlink,
|
||||||
|
.backlink.forwardlink {
|
||||||
|
text-decoration: underline;
|
||||||
|
-moz-text-decoration-style: dashed;
|
||||||
|
text-decoration-style: dashed;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
.filtered {
|
.filtered {
|
||||||
text-decoration: underline line-through;
|
text-decoration: underline line-through;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,11 +4,12 @@
|
|||||||
<div class=credits>
|
<div class=credits>
|
||||||
<a class=export>Export</a> |
|
<a class=export>Export</a> |
|
||||||
<a class=import>Import</a> |
|
<a class=import>Import</a> |
|
||||||
<input type=file style='display: none;'>
|
<button class="reset">Reset Settings</button> |
|
||||||
|
<input type=file hidden>
|
||||||
<a href='<%= meta.page %>' target=_blank><%= meta.name %></a> |
|
<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 %>/CHANGELOG.md' target=_blank>#{g.VERSION}</a> |
|
||||||
<a href='<%= meta.repo %>blob/<%= meta.mainBranch %>/README.md#reporting-bugs-and-suggestions' target=_blank>Issues</a> |
|
<a href='<%= meta.repo %>blob/<%= meta.mainBranch %>/README.md#reporting-bugs-and-suggestions' target=_blank>Issues</a> |
|
||||||
<a href=javascript:; class=close title=Close>×</a>
|
<a href=javascript:; class='fa fa-times' title=Close></a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class=section-container><section></section></div>
|
<div class=section-container><section></section></div>
|
||||||
@ -54,6 +54,8 @@ $.ajax = do ->
|
|||||||
if whenModified
|
if whenModified
|
||||||
r.setRequestHeader 'If-Modified-Since', lastModified[url] if url of lastModified
|
r.setRequestHeader 'If-Modified-Since', lastModified[url] if url of lastModified
|
||||||
$.on r, 'load', -> lastModified[url] = r.getResponseHeader 'Last-Modified'
|
$.on r, 'load', -> lastModified[url] = r.getResponseHeader 'Last-Modified'
|
||||||
|
if /\.json$/.test url
|
||||||
|
r.responseType = 'json'
|
||||||
$.extend r, options
|
$.extend r, options
|
||||||
$.extend r.upload, upCallbacks
|
$.extend r.upload, upCallbacks
|
||||||
r.send form
|
r.send form
|
||||||
@ -113,11 +115,11 @@ $.X = (path, root) ->
|
|||||||
# XPathResult.ORDERED_NODE_SNAPSHOT_TYPE === 7
|
# XPathResult.ORDERED_NODE_SNAPSHOT_TYPE === 7
|
||||||
d.evaluate path, root, null, 7, null
|
d.evaluate path, root, null, 7, null
|
||||||
|
|
||||||
$.addClass = (el, className) ->
|
$.addClass = (el, className...) ->
|
||||||
el.classList.add className
|
el.classList.add className...
|
||||||
|
|
||||||
$.rmClass = (el, className) ->
|
$.rmClass = (el, className...) ->
|
||||||
el.classList.remove className
|
el.classList.remove className...
|
||||||
|
|
||||||
$.toggleClass = (el, className) ->
|
$.toggleClass = (el, className) ->
|
||||||
el.classList.toggle className
|
el.classList.toggle className
|
||||||
@ -332,29 +334,50 @@ $.get = (key, val, cb) ->
|
|||||||
chrome.storage.sync.get syncItems, done
|
chrome.storage.sync.get syncItems, done
|
||||||
|
|
||||||
$.set = do ->
|
$.set = do ->
|
||||||
items = {}
|
items =
|
||||||
localItems = {}
|
sync: {}
|
||||||
|
local: {}
|
||||||
|
timeout = {}
|
||||||
|
|
||||||
set = $.debounce $.SECOND, ->
|
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
|
||||||
|
for key, val of data when key not of items[area]
|
||||||
|
items[area][key] = val
|
||||||
|
timeout[area] = setTimeout setArea, $.MINUTE, area
|
||||||
|
return
|
||||||
|
delete timeout[area]
|
||||||
|
|
||||||
|
setAll = $.debounce $.SECOND, ->
|
||||||
for key in $.localKeys
|
for key in $.localKeys
|
||||||
if key of items
|
if key of items.sync
|
||||||
(localItems or= {})[key] = items[key]
|
items.local[key] = items.sync[key]
|
||||||
delete items[key]
|
delete items.sync[key]
|
||||||
try
|
try
|
||||||
chrome.storage.local.set localItems
|
setArea 'local'
|
||||||
chrome.storage.sync.set items
|
setArea 'sync'
|
||||||
items = {}
|
|
||||||
localItems = {}
|
|
||||||
catch err
|
catch err
|
||||||
c.error err.stack
|
c.error err.stack
|
||||||
|
|
||||||
(key, val) ->
|
(key, val) ->
|
||||||
if typeof key is 'string'
|
if typeof key is 'string'
|
||||||
items[key] = val
|
items.sync[key] = val
|
||||||
else
|
else
|
||||||
$.extend items, key
|
$.extend items.sync, key
|
||||||
set()
|
setAll()
|
||||||
|
$.clear = (cb) ->
|
||||||
|
count = 2
|
||||||
|
done = ->
|
||||||
|
if chrome.runtime.lastError
|
||||||
|
c.error chrome.runtime.lastError.message
|
||||||
|
return
|
||||||
|
cb?() unless --count
|
||||||
|
chrome.storage.local.clear done
|
||||||
|
chrome.storage.sync.clear done
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
|
|
||||||
# http://wiki.greasespot.net/Main_Page
|
# http://wiki.greasespot.net/Main_Page
|
||||||
@ -402,6 +425,9 @@ $.set = do ->
|
|||||||
for key, val of keys
|
for key, val of keys
|
||||||
set key, val
|
set key, val
|
||||||
return
|
return
|
||||||
|
$.clear = (cb) ->
|
||||||
|
$.delete GM_listValues().map (key) -> key.replace g.NAMESPACE, ''
|
||||||
|
cb?()
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
$$ = (selector, root=d.body) ->
|
$$ = (selector, root=d.body) ->
|
||||||
|
|||||||
@ -78,7 +78,7 @@ class DataBoard
|
|||||||
return
|
return
|
||||||
board = @data.boards[boardID]
|
board = @data.boards[boardID]
|
||||||
threads = {}
|
threads = {}
|
||||||
for page in JSON.parse e.target.response
|
for page in e.target.response
|
||||||
for thread in page.threads
|
for thread in page.threads
|
||||||
if thread.no of board
|
if thread.no of board
|
||||||
threads[thread.no] = board[thread.no]
|
threads[thread.no] = board[thread.no]
|
||||||
@ -93,4 +93,4 @@ class DataBoard
|
|||||||
disconnect: ->
|
disconnect: ->
|
||||||
$.desync @key
|
$.desync @key
|
||||||
delete @sync
|
delete @sync
|
||||||
delete @data
|
delete @data
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
// @grant GM_getValue
|
// @grant GM_getValue
|
||||||
// @grant GM_setValue
|
// @grant GM_setValue
|
||||||
// @grant GM_deleteValue
|
// @grant GM_deleteValue
|
||||||
|
// @grant GM_listValues
|
||||||
// @grant GM_openInTab
|
// @grant GM_openInTab
|
||||||
// @run-at document-start
|
// @run-at document-start
|
||||||
// @updateURL <%= meta.repo %>raw/stable/builds/<%= meta.files.metajs %>
|
// @updateURL <%= meta.repo %>raw/stable/builds/<%= meta.files.metajs %>
|
||||||
|
|||||||
@ -153,10 +153,19 @@ ImageExpand =
|
|||||||
return
|
return
|
||||||
|
|
||||||
timeoutID = setTimeout ImageExpand.expand, 10000, post
|
timeoutID = setTimeout ImageExpand.expand, 10000, post
|
||||||
|
<% if (type === 'crx') { %>
|
||||||
|
$.ajax @src,
|
||||||
|
onloadend: ->
|
||||||
|
return if @status isnt 404
|
||||||
|
clearTimeout timeoutID
|
||||||
|
post.kill true
|
||||||
|
,
|
||||||
|
type: 'head'
|
||||||
|
<% } else { %>
|
||||||
# XXX CORS for i.4cdn.org WHEN?
|
# XXX CORS for i.4cdn.org WHEN?
|
||||||
$.ajax "//a.4cdn.org/#{post.board}/res/#{post.thread}.json", onload: ->
|
$.ajax "//a.4cdn.org/#{post.board}/res/#{post.thread}.json", onload: ->
|
||||||
return if @status isnt 200
|
return if @status isnt 200
|
||||||
for postObj in JSON.parse(@response).posts
|
for postObj in @response.posts
|
||||||
break if postObj.no is post.ID
|
break if postObj.no is post.ID
|
||||||
if postObj.no isnt post.ID
|
if postObj.no isnt post.ID
|
||||||
clearTimeout timeoutID
|
clearTimeout timeoutID
|
||||||
@ -164,6 +173,7 @@ ImageExpand =
|
|||||||
else if postObj.filedeleted
|
else if postObj.filedeleted
|
||||||
clearTimeout timeoutID
|
clearTimeout timeoutID
|
||||||
post.kill true
|
post.kill true
|
||||||
|
<% } %>
|
||||||
|
|
||||||
menu:
|
menu:
|
||||||
init: ->
|
init: ->
|
||||||
|
|||||||
@ -38,10 +38,19 @@ ImageHover =
|
|||||||
return
|
return
|
||||||
|
|
||||||
timeoutID = setTimeout (=> @src = post.file.URL + '?' + Date.now()), 3000
|
timeoutID = setTimeout (=> @src = post.file.URL + '?' + Date.now()), 3000
|
||||||
|
<% if (type === 'crx') { %>
|
||||||
|
$.ajax @src,
|
||||||
|
onloadend: ->
|
||||||
|
return if @status isnt 404
|
||||||
|
clearTimeout timeoutID
|
||||||
|
post.kill true
|
||||||
|
,
|
||||||
|
type: 'head'
|
||||||
|
<% } else { %>
|
||||||
# XXX CORS for i.4cdn.org WHEN?
|
# XXX CORS for i.4cdn.org WHEN?
|
||||||
$.ajax "//a.4cdn.org/#{post.board}/res/#{post.thread}.json", onload: ->
|
$.ajax "//a.4cdn.org/#{post.board}/res/#{post.thread}.json", onload: ->
|
||||||
return if @status isnt 200
|
return if @status isnt 200
|
||||||
for postObj in JSON.parse(@response).posts
|
for postObj in @response.posts
|
||||||
break if postObj.no is post.ID
|
break if postObj.no is post.ID
|
||||||
if postObj.no isnt post.ID
|
if postObj.no isnt post.ID
|
||||||
clearTimeout timeoutID
|
clearTimeout timeoutID
|
||||||
@ -49,3 +58,4 @@ ImageHover =
|
|||||||
else if postObj.filedeleted
|
else if postObj.filedeleted
|
||||||
clearTimeout timeoutID
|
clearTimeout timeoutID
|
||||||
post.kill true
|
post.kill true
|
||||||
|
<% } %>
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
PSAHiding =
|
PSAHiding =
|
||||||
init: ->
|
init: ->
|
||||||
return if !Conf['Announcement Hiding']
|
return if !Conf['Announcement Hiding']
|
||||||
|
|
||||||
$.addClass doc, 'hide-announcement'
|
$.addClass doc, 'hide-announcement'
|
||||||
|
|
||||||
$.on d, '4chanXInitFinished', @setup
|
$.on d, '4chanXInitFinished', @setup
|
||||||
|
|
||||||
setup: ->
|
setup: ->
|
||||||
$.off d, '4chanXInitFinished', PSAHiding.setup
|
$.off d, '4chanXInitFinished', PSAHiding.setup
|
||||||
|
|
||||||
|
|||||||
@ -77,13 +77,13 @@ ExpandThread =
|
|||||||
a.textContent = "Error #{req.statusText} (#{req.status})"
|
a.textContent = "Error #{req.statusText} (#{req.status})"
|
||||||
return
|
return
|
||||||
|
|
||||||
data = JSON.parse(req.response).posts
|
Build.spoilerRange[thread.board] = req.response.posts[0].custom_spoiler
|
||||||
Build.spoilerRange[thread.board] = data.shift().custom_spoiler
|
|
||||||
|
|
||||||
posts = []
|
posts = []
|
||||||
postsRoot = []
|
postsRoot = []
|
||||||
filesCount = 0
|
filesCount = 0
|
||||||
for postData in data
|
for postData in req.response.posts
|
||||||
|
continue if postData.no is thread.ID
|
||||||
if post = thread.posts[postData.no]
|
if post = thread.posts[postData.no]
|
||||||
filesCount++ if 'file' of post
|
filesCount++ if 'file' of post
|
||||||
postsRoot.push post.nodes.root
|
postsRoot.push post.nodes.root
|
||||||
|
|||||||
@ -77,9 +77,8 @@ ThreadStats =
|
|||||||
|
|
||||||
onThreadsLoad: ->
|
onThreadsLoad: ->
|
||||||
return unless Conf["Page Count in Stats"] and @status is 200
|
return unless Conf["Page Count in Stats"] and @status is 200
|
||||||
pages = JSON.parse @response
|
for page in @response
|
||||||
for page in pages
|
|
||||||
for thread in page.threads when thread.no is ThreadStats.thread.ID
|
for thread in page.threads when thread.no is ThreadStats.thread.ID
|
||||||
ThreadStats.pageCountEl.textContent = page.page
|
ThreadStats.pageCountEl.textContent = page.page
|
||||||
(if page.page is pages.length - 1 then $.addClass else $.rmClass) ThreadStats.pageCountEl, 'warning'
|
(if page.page is @response.length - 1 then $.addClass else $.rmClass) ThreadStats.pageCountEl, 'warning'
|
||||||
return
|
return
|
||||||
@ -158,7 +158,7 @@ ThreadUpdater =
|
|||||||
switch req.status
|
switch req.status
|
||||||
when 200
|
when 200
|
||||||
g.DEAD = false
|
g.DEAD = false
|
||||||
ThreadUpdater.parse JSON.parse(req.response).posts
|
ThreadUpdater.parse req.response.posts
|
||||||
ThreadUpdater.setInterval()
|
ThreadUpdater.setInterval()
|
||||||
when 404
|
when 404
|
||||||
g.DEAD = true
|
g.DEAD = true
|
||||||
|
|||||||
@ -670,7 +670,7 @@ QR =
|
|||||||
# Too many frequent mistyped captchas will auto-ban you!
|
# Too many frequent mistyped captchas will auto-ban you!
|
||||||
# On connection error, the post most likely didn't go through.
|
# On connection error, the post most likely didn't go through.
|
||||||
QR.cooldown.set delay: 2
|
QR.cooldown.set delay: 2
|
||||||
else if err.textContent and m = err.textContent.match /wait\s(\d+)\ssecond/i
|
else if err.textContent and m = err.textContent.match /wait\s+(\d+)\s+second/i
|
||||||
QR.cooldown.auto = if QR.captcha.isEnabled
|
QR.cooldown.auto = if QR.captcha.isEnabled
|
||||||
!!QR.captcha.captchas.length
|
!!QR.captcha.captchas.length
|
||||||
else
|
else
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user