diff --git a/CHANGELOG.md b/CHANGELOG.md index c9189a341..c574372bc 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,28 +1,29 @@ **MayhemYDG**: - - Tiny posting cooldown adjustment: - * You can post an image reply immediately after a non-image reply. - - Update posting cooldown timers to match 4chan settings: - * Cooldown may vary between inter-thread and intra-thread replies. - * Cooldown may vary when posting a file or not. - * Cooldown does not take sageing into account anymore. - * Timers vary across boards. - - Updated post and deletion cooldown timers to match 4chan changes: they are now twice longer. - - Added support for the flag selector on /pol/. +- Tiny posting cooldown adjustment: + * You can post an image reply immediately after a non-image reply. +- Update posting cooldown timers to match 4chan settings: + * Cooldown may vary between inter-thread and intra-thread replies. + * Cooldown may vary when posting a file or not. + * Cooldown does not take sageing into account anymore. + * Timers vary across boards. +- Updated post and deletion cooldown timers to match 4chan changes: they are now twice longer. +- Added support for the flag selector on /pol/. +- Minor Chrome 30 fix. ### v1.2.39 *2013-09-19* **seaweedchan**: - - Fix thread updater bug introduced in last version +- Fix thread updater bug introduced in last version ### v1.2.38 *2013-09-19* **MayhemYDG**: - - Update posting cooldown timers to match 4chan settings: - - Cooldown may vary between inter-thread and intra-thread replies. - - Cooldown may vary when posting a file or not. - - Cooldown does not take sageing into account anymore. - - Timers vary across boards. +- Update posting cooldown timers to match 4chan settings: + - Cooldown may vary between inter-thread and intra-thread replies. + - Cooldown may vary when posting a file or not. + - Cooldown does not take sageing into account anymore. + - Timers vary across boards. ### v1.2.37 *2013-09-12* @@ -37,10 +38,10 @@ - New desktop notification: * The QR will now warn you when you are running low on cached captchas while auto-posting. - **seaweedchan**: +**seaweedchan**: - Visual overhaul for gallery mode - **Zixaphir**: +**Zixaphir**: - Fix an issue with the file dialog randomly opening multiple times (with seaweedchan) ![Gallery](src/General/img/changelog/2.3.6.png) - Add new feature: `Gallery`. diff --git a/LICENSE b/LICENSE index f86c6c33f..06b2ec002 100755 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.2.39 - 2013-09-24 +* 4chan X - Version 1.2.39 - 2013-10-13 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 559e6b2b9..c59086b17 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -22,7 +22,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.2.39 - 2013-09-24 +* 4chan X - Version 1.2.39 - 2013-10-13 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -104,7 +104,7 @@ 'use strict'; (function() { - var $, $$, Anonymize, ArchiveLink, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, + var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, __slice = [].slice, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, @@ -845,7 +845,7 @@ })(); Thread = (function() { - Thread.prototype.callbacks = []; + Thread.callbacks = []; Thread.prototype.toString = function() { return this.ID; @@ -869,7 +869,7 @@ })(); Post = (function() { - Post.prototype.callbacks = []; + Post.callbacks = []; Post.prototype.toString = function() { return this.ID; @@ -2763,7 +2763,7 @@ if (g.VIEW === 'catalog' || !Conf['Anonymize']) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Anonymize', cb: this.node }); @@ -2854,7 +2854,7 @@ if (!Object.keys(this.filters).length) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Filter', cb: this.node }); @@ -3084,7 +3084,7 @@ $.addClass(doc, "reply-hide"); } this.db = new DataBoard('hiddenPosts'); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Reply Hiding', cb: this.node }); @@ -3387,7 +3387,7 @@ if (g.VIEW === 'catalog') { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Recursive', cb: this.node }); @@ -3458,7 +3458,7 @@ } this.db = new DataBoard('hiddenThreads'); this.syncCatalog(); - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Hiding', cb: this.node }); @@ -3727,11 +3727,11 @@ format = Conf['backlink'].replace(/%id/g, "' + id + '"); this.funk = Function('id', "return '" + format + "'"); this.containers = {}; - Post.prototype.callbacks.push({ + Post.callbacks.push({ name: 'Quote Backlinking Part 1', cb: this.firstNode }); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quote Backlinking Part 2', cb: this.secondNode }); @@ -3806,7 +3806,7 @@ ExpandComment.callbacks.push(this.node); } this.text = '\u00A0(Cross-thread)'; - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Mark Cross-thread Quotes', cb: this.node }); @@ -3867,7 +3867,7 @@ if (Conf['Comment Expansion']) { ExpandComment.callbacks.push(this.node); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quote Inlining', cb: this.node }); @@ -3969,7 +3969,7 @@ ExpandComment.callbacks.push(this.node); } this.text = '\u00A0(OP)'; - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Mark OP Quotes', cb: this.node }); @@ -4012,7 +4012,7 @@ if (Conf['Comment Expansion']) { ExpandComment.callbacks.push(this.node); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quote Previewing', cb: this.node }); @@ -4095,7 +4095,7 @@ if (g.VIEW === 'catalog' || !Conf['Reply Hiding Buttons'] && !Conf['Reply Hiding Link'] && !Conf['Filter']) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Strike-through Quotes', cb: this.node }); @@ -4141,7 +4141,7 @@ order: 98 }); $.on(d, '4chanXInitFinished', this.setup); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quote Threading', cb: this.node }); @@ -4278,7 +4278,8 @@ if (Conf['Comment Expansion']) { ExpandComment.callbacks.push(this.node); } - return Post.prototype.callbacks.push({ + this.text = '\u00A0(You)'; + return Post.callbacks.push({ name: 'Mark Quotes of You', cb: this.node }); @@ -4301,7 +4302,7 @@ if (!(QR.db.get(Get.postDataFromLink(quotelink)))) { continue; } - $.add(quotelink, $.tn('\u00A0(You)')); + $.add(quotelink, $.tn(QuoteYou.text)); $.addClass(quotelink, 'you'); $.addClass(this.nodes.root, 'quotesYou'); } @@ -4358,7 +4359,7 @@ if (Conf['Comment Expansion']) { ExpandComment.callbacks.push(this.node); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Resurrect Quotes', cb: this.node }); @@ -4450,6 +4451,15 @@ } }, fixDeadlink: function(deadlink) { + var el, green; + + if (!(el = deadlink.previousSibling) || el.nodeName === 'BR') { + green = $.el('span', { + className: 'quote' + }); + $.before(deadlink, green); + $.add(green, deadlink); + } return $.replace(deadlink, __slice.call(deadlink.childNodes)); } }; @@ -4466,7 +4476,7 @@ if (Conf['Title Link']) { $.sync('CachedTitles', Linkify.titleSync); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Linkify', cb: this.node }); @@ -4958,7 +4968,7 @@ $.ready(this.persist); } } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quick Reply', cb: this.node }); @@ -5479,8 +5489,7 @@ } e.preventDefault(); QR.open(); - QR.handleFiles(e.dataTransfer.files); - return $.addClass(QR.nodes.el, 'dump'); + return QR.handleFiles(e.dataTransfer.files); }, paste: function(e) { var blob, files, item, _i, _len, _ref; @@ -6409,6 +6418,10 @@ threadID: threadID, postID: postID }); + $.event('QRPostSuccessful_', { + threadID: threadID, + postID: postID + }); postsCount = QR.posts.length - 1; QR.cooldown.auto = postsCount && isReply; if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) { @@ -6460,6 +6473,40 @@ } }; + AutoGIF = { + init: function() { + var _ref; + + if (g.VIEW === 'catalog' || !Conf['Auto-GIF'] || ((_ref = g.BOARD.ID) === 'gif' || _ref === 'wsg')) { + return; + } + return Post.callbacks.push({ + name: 'Auto-GIF', + cb: this.node + }); + }, + node: function() { + var URL, gif, style, thumb, _ref, _ref1; + + if (this.isClone || this.isHidden || this.thread.isHidden || !((_ref = this.file) != null ? _ref.isImage : void 0)) { + return; + } + _ref1 = this.file, thumb = _ref1.thumb, URL = _ref1.URL; + if (!(/gif$/.test(URL) && !/spoiler/.test(thumb.src))) { + return; + } + if (this.file.isSpoiler) { + style = thumb.style; + style.maxHeight = style.maxWidth = this.isReply ? '125px' : '250px'; + } + gif = $.el('img'); + $.on(gif, 'load', function() { + return thumb.src = URL; + }); + return gif.src = URL; + } + }; + FappeTyme = { init: function() { var el, input; @@ -6493,7 +6540,7 @@ order: 98 }); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Fappe Tyme', cb: this.node }); @@ -6532,7 +6579,7 @@ }); $.on(el, 'click', this.cb.toggle); Header.addShortcut(el); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Gallery', cb: this.node }); @@ -6832,7 +6879,7 @@ }); $.on(this.EAI, 'click', ImageExpand.cb.toggleAll); Header.addShortcut(this.EAI, 2); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Image Expansion', cb: this.node }); @@ -7091,7 +7138,7 @@ if (g.VIEW === 'catalog' || !Conf['Image Hover']) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Image Hover', cb: this.node }); @@ -7186,7 +7233,7 @@ if (!(Conf["Image Prefetching"] || Conf["Replace JPG"] || Conf["Replace PNG"] || Conf["Replace GIF"])) { return; } - Post.prototype.callbacks.push({ + Post.callbacks.push({ name: 'Image Replace', cb: this.node }); @@ -7245,8 +7292,7 @@ if (g.VIEW === 'catalog' || !Conf['Reveal Spoiler Thumbnails']) { return; } - return Post.prototype.callbacks.push({ - name: 'Reveal Spoiler Thumbnails', + return Post.callbacks.push({ cb: this.node }); }, @@ -7288,7 +7334,7 @@ this.link = $.el('a', { target: '_blank' }); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Sauce', cb: this.node }); @@ -7582,7 +7628,7 @@ return; } this.menu = new UI.Menu('post'); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Menu', cb: this.node }); @@ -7716,7 +7762,7 @@ if (g.VIEW !== 'thread' || !Conf['Thread Excerpt']) { return; } - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Excerpt', cb: this.node }); @@ -7752,7 +7798,7 @@ this.postCountEl = $('#post-count', sc); this.fileCountEl = $('#file-count', sc); this.pageCountEl = $('#page-count', sc); - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Stats', cb: this.node }); @@ -7897,7 +7943,7 @@ order: 110, subEntries: subEntries }); - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Updater', cb: this.node }); @@ -8262,7 +8308,7 @@ ThreadWatcher.fetchAllStatus(); this.db.save(); } - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Watcher', cb: this.node }); @@ -8722,7 +8768,7 @@ }); this.posts = []; this.postsQuotingYou = []; - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Unread', cb: this.node }); @@ -8855,6 +8901,7 @@ } Unread.postsQuotingYou.push(post); Unread.openNotification(post); + return; } }, openNotification: function(post) { @@ -9432,7 +9479,7 @@ return; } this.ids = {}; - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Color User IDs', cb: this.node }); @@ -9506,7 +9553,7 @@ if (g.BOARD.ID !== 'tg' || g.VIEW === 'catalog' || !Conf['Show Dice Roll']) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Show Dice Roll', cb: this.node }); @@ -9588,7 +9635,7 @@ if (g.BOARD.ID === 'sci') { this.callbacks.push(Fourchan.math); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Comment Expansion', cb: this.node }); @@ -9684,7 +9731,7 @@ if (g.VIEW !== 'index' || !Conf['Thread Expansion']) { return; } - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Expansion', cb: this.node }); @@ -9840,7 +9887,7 @@ return; } this.funk = this.createFunc(Conf['fileInfo']); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'File Info Formatting', cb: this.node }); @@ -9947,14 +9994,14 @@ board = g.BOARD.ID; if (board === 'g') { $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML);\n}, false);"); - Post.prototype.callbacks.push({ + Post.callbacks.push({ name: 'Parse /g/ code', cb: this.code }); } if (board === 'sci') { $.globalEval("window.addEventListener('jsmath', function(e) {\n if (jsMath.loaded) {\n // process one post\n jsMath.ProcessBeforeShowing(e.detail);\n } else {\n // load jsMath and process whole document\n jsMath.Autoload.Script.Push('ProcessBeforeShowing', [null]);\n jsMath.Autoload.LoadJsMath();\n }\n}, false);"); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Parse /sci/ math', cb: this.math }); @@ -9988,6 +10035,54 @@ } }; + IDColor = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Color User IDs']) { + return; + } + this.ids = {}; + return Post.callbacks.push({ + name: 'Color User IDs', + cb: this.node + }); + }, + node: function() { + var rgb, span, style, uid; + + if (this.isClone || !(uid = this.info.uniqueID)) { + return; + } + rgb = IDColor.compute(uid); + span = this.nodes.uniqueID; + style = span.style; + style.color = rgb[3]; + style.backgroundColor = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")"; + $.addClass(span, 'painted'); + span.textContent = uid; + return span.title = 'Highlight posts by this ID'; + }, + compute: function(uniqueID) { + var hash, rgb; + + if (uniqueID in IDColor.ids) { + return IDColor.ids[uniqueID]; + } + hash = this.hash(uniqueID); + rgb = [(hash >> 24) & 0xFF, (hash >> 16) & 0xFF, (hash >> 8) & 0xFF]; + rgb.push((rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) > 170 ? 'black' : 'white'); + return this.ids[uniqueID] = rgb; + }, + hash: function(uniqueID) { + var i, msg, _i, _ref; + + msg = 0; + for (i = _i = 0, _ref = uniqueID.length; _i < _ref; i = _i += 1) { + msg = (msg << 5) - msg + uniqueID.charCodeAt(i); + } + return msg; + } + }; + Keybinds = { init: function() { var init; @@ -10442,7 +10537,7 @@ } $.on(d, 'visibilitychange ThreadUpdate', this.flush); this.flush(); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Relative Post Dates', cb: this.node }); @@ -10526,7 +10621,7 @@ return "[spoiler]" + text + "[/spoiler]"; }; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Reveal Spoilers', cb: this.node }); @@ -10582,7 +10677,7 @@ return; } this.funk = this.createFunc(Conf['time']); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Time Formatting', cb: this.node }); @@ -11616,7 +11711,7 @@ var callback, err, errors, i, len, node, _i, _len, _ref; len = nodes.length; - _ref = klass.prototype.callbacks; + _ref = klass.callbacks; for (_i = 0, _len = _ref.length; _i < _len; _i++) { callback = _ref[_i]; i = 0; @@ -11715,7 +11810,7 @@ return; } obj.callback.isAddon = true; - return Klass.prototype.callbacks.push(obj.callback); + return Klass.callbacks.push(obj.callback); }, handleErrors: function(errors) { var div, error, logs, _i, _len; diff --git a/builds/crx/script.js b/builds/crx/script.js index c4cc33f96..1163a0867 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.2.39 - 2013-09-24 +* 4chan X - Version 1.2.39 - 2013-10-13 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -82,7 +82,7 @@ 'use strict'; (function() { - var $, $$, Anonymize, ArchiveLink, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, + var $, $$, Anonymize, ArchiveLink, AutoGIF, Banner, Board, Build, CatalogLinks, Clone, Conf, Config, CustomCSS, DataBoard, DeleteLink, Dice, DownloadLink, Emoji, ExpandComment, ExpandThread, FappeTyme, Favicon, FileInfo, Filter, Fourchan, Gallery, Get, Header, IDColor, ImageExpand, ImageHover, ImageLoader, Keybinds, Linkify, Main, Menu, Nav, Notice, PSAHiding, Polyfill, Post, PostHiding, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, Recursive, Redirect, RelativeDates, RemoveSpoilers, Report, ReportLink, RevealSpoilers, Sauce, Settings, Thread, ThreadExcerpt, ThreadHiding, ThreadStats, ThreadUpdater, ThreadWatcher, Time, UI, Unread, c, d, doc, g, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, __slice = [].slice, __hasProp = {}.hasOwnProperty, @@ -854,7 +854,7 @@ })(); Thread = (function() { - Thread.prototype.callbacks = []; + Thread.callbacks = []; Thread.prototype.toString = function() { return this.ID; @@ -878,7 +878,7 @@ })(); Post = (function() { - Post.prototype.callbacks = []; + Post.callbacks = []; Post.prototype.toString = function() { return this.ID; @@ -2770,7 +2770,7 @@ if (g.VIEW === 'catalog' || !Conf['Anonymize']) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Anonymize', cb: this.node }); @@ -2861,7 +2861,7 @@ if (!Object.keys(this.filters).length) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Filter', cb: this.node }); @@ -3091,7 +3091,7 @@ $.addClass(doc, "reply-hide"); } this.db = new DataBoard('hiddenPosts'); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Reply Hiding', cb: this.node }); @@ -3394,7 +3394,7 @@ if (g.VIEW === 'catalog') { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Recursive', cb: this.node }); @@ -3465,7 +3465,7 @@ } this.db = new DataBoard('hiddenThreads'); this.syncCatalog(); - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Hiding', cb: this.node }); @@ -3734,11 +3734,11 @@ format = Conf['backlink'].replace(/%id/g, "' + id + '"); this.funk = Function('id', "return '" + format + "'"); this.containers = {}; - Post.prototype.callbacks.push({ + Post.callbacks.push({ name: 'Quote Backlinking Part 1', cb: this.firstNode }); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quote Backlinking Part 2', cb: this.secondNode }); @@ -3813,7 +3813,7 @@ ExpandComment.callbacks.push(this.node); } this.text = '\u00A0(Cross-thread)'; - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Mark Cross-thread Quotes', cb: this.node }); @@ -3874,7 +3874,7 @@ if (Conf['Comment Expansion']) { ExpandComment.callbacks.push(this.node); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quote Inlining', cb: this.node }); @@ -3976,7 +3976,7 @@ ExpandComment.callbacks.push(this.node); } this.text = '\u00A0(OP)'; - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Mark OP Quotes', cb: this.node }); @@ -4019,7 +4019,7 @@ if (Conf['Comment Expansion']) { ExpandComment.callbacks.push(this.node); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quote Previewing', cb: this.node }); @@ -4102,7 +4102,7 @@ if (g.VIEW === 'catalog' || !Conf['Reply Hiding Buttons'] && !Conf['Reply Hiding Link'] && !Conf['Filter']) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Strike-through Quotes', cb: this.node }); @@ -4148,7 +4148,7 @@ order: 98 }); $.on(d, '4chanXInitFinished', this.setup); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quote Threading', cb: this.node }); @@ -4285,7 +4285,8 @@ if (Conf['Comment Expansion']) { ExpandComment.callbacks.push(this.node); } - return Post.prototype.callbacks.push({ + this.text = '\u00A0(You)'; + return Post.callbacks.push({ name: 'Mark Quotes of You', cb: this.node }); @@ -4308,7 +4309,7 @@ if (!(QR.db.get(Get.postDataFromLink(quotelink)))) { continue; } - $.add(quotelink, $.tn('\u00A0(You)')); + $.add(quotelink, $.tn(QuoteYou.text)); $.addClass(quotelink, 'you'); $.addClass(this.nodes.root, 'quotesYou'); } @@ -4365,7 +4366,7 @@ if (Conf['Comment Expansion']) { ExpandComment.callbacks.push(this.node); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Resurrect Quotes', cb: this.node }); @@ -4457,6 +4458,15 @@ } }, fixDeadlink: function(deadlink) { + var el, green; + + if (!(el = deadlink.previousSibling) || el.nodeName === 'BR') { + green = $.el('span', { + className: 'quote' + }); + $.before(deadlink, green); + $.add(green, deadlink); + } return $.replace(deadlink, __slice.call(deadlink.childNodes)); } }; @@ -4473,7 +4483,7 @@ if (Conf['Title Link']) { $.sync('CachedTitles', Linkify.titleSync); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Linkify', cb: this.node }); @@ -4965,7 +4975,7 @@ $.ready(this.persist); } } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Quick Reply', cb: this.node }); @@ -5491,8 +5501,7 @@ } e.preventDefault(); QR.open(); - QR.handleFiles(e.dataTransfer.files); - return $.addClass(QR.nodes.el, 'dump'); + return QR.handleFiles(e.dataTransfer.files); }, paste: function(e) { var blob, files, item, _i, _len, _ref; @@ -6396,6 +6405,10 @@ threadID: threadID, postID: postID }); + $.event('QRPostSuccessful_', { + threadID: threadID, + postID: postID + }); postsCount = QR.posts.length - 1; QR.cooldown.auto = postsCount && isReply; if (QR.cooldown.auto && QR.captcha.isEnabled && (captchasCount = QR.captcha.captchas.length) < 3 && captchasCount < postsCount) { @@ -6447,6 +6460,40 @@ } }; + AutoGIF = { + init: function() { + var _ref; + + if (g.VIEW === 'catalog' || !Conf['Auto-GIF'] || ((_ref = g.BOARD.ID) === 'gif' || _ref === 'wsg')) { + return; + } + return Post.callbacks.push({ + name: 'Auto-GIF', + cb: this.node + }); + }, + node: function() { + var URL, gif, style, thumb, _ref, _ref1; + + if (this.isClone || this.isHidden || this.thread.isHidden || !((_ref = this.file) != null ? _ref.isImage : void 0)) { + return; + } + _ref1 = this.file, thumb = _ref1.thumb, URL = _ref1.URL; + if (!(/gif$/.test(URL) && !/spoiler/.test(thumb.src))) { + return; + } + if (this.file.isSpoiler) { + style = thumb.style; + style.maxHeight = style.maxWidth = this.isReply ? '125px' : '250px'; + } + gif = $.el('img'); + $.on(gif, 'load', function() { + return thumb.src = URL; + }); + return gif.src = URL; + } + }; + FappeTyme = { init: function() { var el, input; @@ -6480,7 +6527,7 @@ order: 98 }); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Fappe Tyme', cb: this.node }); @@ -6519,7 +6566,7 @@ }); $.on(el, 'click', this.cb.toggle); Header.addShortcut(el); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Gallery', cb: this.node }); @@ -6819,7 +6866,7 @@ }); $.on(this.EAI, 'click', ImageExpand.cb.toggleAll); Header.addShortcut(this.EAI, 2); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Image Expansion', cb: this.node }); @@ -7078,7 +7125,7 @@ if (g.VIEW === 'catalog' || !Conf['Image Hover']) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Image Hover', cb: this.node }); @@ -7173,7 +7220,7 @@ if (!(Conf["Image Prefetching"] || Conf["Replace JPG"] || Conf["Replace PNG"] || Conf["Replace GIF"])) { return; } - Post.prototype.callbacks.push({ + Post.callbacks.push({ name: 'Image Replace', cb: this.node }); @@ -7232,8 +7279,7 @@ if (g.VIEW === 'catalog' || !Conf['Reveal Spoiler Thumbnails']) { return; } - return Post.prototype.callbacks.push({ - name: 'Reveal Spoiler Thumbnails', + return Post.callbacks.push({ cb: this.node }); }, @@ -7275,7 +7321,7 @@ this.link = $.el('a', { target: '_blank' }); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Sauce', cb: this.node }); @@ -7569,7 +7615,7 @@ return; } this.menu = new UI.Menu('post'); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Menu', cb: this.node }); @@ -7703,7 +7749,7 @@ if (g.VIEW !== 'thread' || !Conf['Thread Excerpt']) { return; } - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Excerpt', cb: this.node }); @@ -7739,7 +7785,7 @@ this.postCountEl = $('#post-count', sc); this.fileCountEl = $('#file-count', sc); this.pageCountEl = $('#page-count', sc); - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Stats', cb: this.node }); @@ -7884,7 +7930,7 @@ order: 110, subEntries: subEntries }); - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Updater', cb: this.node }); @@ -8249,7 +8295,7 @@ ThreadWatcher.fetchAllStatus(); this.db.save(); } - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Watcher', cb: this.node }); @@ -8709,7 +8755,7 @@ }); this.posts = []; this.postsQuotingYou = []; - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Unread', cb: this.node }); @@ -8842,6 +8888,7 @@ } Unread.postsQuotingYou.push(post); Unread.openNotification(post); + return; } }, openNotification: function(post) { @@ -9425,7 +9472,7 @@ return; } this.ids = {}; - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Color User IDs', cb: this.node }); @@ -9499,7 +9546,7 @@ if (g.BOARD.ID !== 'tg' || g.VIEW === 'catalog' || !Conf['Show Dice Roll']) { return; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Show Dice Roll', cb: this.node }); @@ -9581,7 +9628,7 @@ if (g.BOARD.ID === 'sci') { this.callbacks.push(Fourchan.math); } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Comment Expansion', cb: this.node }); @@ -9677,7 +9724,7 @@ if (g.VIEW !== 'index' || !Conf['Thread Expansion']) { return; } - return Thread.prototype.callbacks.push({ + return Thread.callbacks.push({ name: 'Thread Expansion', cb: this.node }); @@ -9833,7 +9880,7 @@ return; } this.funk = this.createFunc(Conf['fileInfo']); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'File Info Formatting', cb: this.node }); @@ -9940,14 +9987,14 @@ board = g.BOARD.ID; if (board === 'g') { $.globalEval("window.addEventListener('prettyprint', function(e) {\n var pre = e.detail;\n pre.innerHTML = prettyPrintOne(pre.innerHTML);\n}, false);"); - Post.prototype.callbacks.push({ + Post.callbacks.push({ name: 'Parse /g/ code', cb: this.code }); } if (board === 'sci') { $.globalEval("window.addEventListener('jsmath', function(e) {\n if (jsMath.loaded) {\n // process one post\n jsMath.ProcessBeforeShowing(e.detail);\n } else {\n // load jsMath and process whole document\n jsMath.Autoload.Script.Push('ProcessBeforeShowing', [null]);\n jsMath.Autoload.LoadJsMath();\n }\n}, false);"); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Parse /sci/ math', cb: this.math }); @@ -9981,6 +10028,54 @@ } }; + IDColor = { + init: function() { + if (g.VIEW === 'catalog' || !Conf['Color User IDs']) { + return; + } + this.ids = {}; + return Post.callbacks.push({ + name: 'Color User IDs', + cb: this.node + }); + }, + node: function() { + var rgb, span, style, uid; + + if (this.isClone || !(uid = this.info.uniqueID)) { + return; + } + rgb = IDColor.compute(uid); + span = this.nodes.uniqueID; + style = span.style; + style.color = rgb[3]; + style.backgroundColor = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")"; + $.addClass(span, 'painted'); + span.textContent = uid; + return span.title = 'Highlight posts by this ID'; + }, + compute: function(uniqueID) { + var hash, rgb; + + if (uniqueID in IDColor.ids) { + return IDColor.ids[uniqueID]; + } + hash = this.hash(uniqueID); + rgb = [(hash >> 24) & 0xFF, (hash >> 16) & 0xFF, (hash >> 8) & 0xFF]; + rgb.push((rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) > 170 ? 'black' : 'white'); + return this.ids[uniqueID] = rgb; + }, + hash: function(uniqueID) { + var i, msg, _i, _ref; + + msg = 0; + for (i = _i = 0, _ref = uniqueID.length; _i < _ref; i = _i += 1) { + msg = (msg << 5) - msg + uniqueID.charCodeAt(i); + } + return msg; + } + }; + Keybinds = { init: function() { var init; @@ -10435,7 +10530,7 @@ } $.on(d, 'visibilitychange ThreadUpdate', this.flush); this.flush(); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Relative Post Dates', cb: this.node }); @@ -10519,7 +10614,7 @@ return "[spoiler]" + text + "[/spoiler]"; }; } - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Reveal Spoilers', cb: this.node }); @@ -10575,7 +10670,7 @@ return; } this.funk = this.createFunc(Conf['time']); - return Post.prototype.callbacks.push({ + return Post.callbacks.push({ name: 'Time Formatting', cb: this.node }); @@ -11607,7 +11702,7 @@ var callback, err, errors, i, len, node, _i, _len, _ref; len = nodes.length; - _ref = klass.prototype.callbacks; + _ref = klass.callbacks; for (_i = 0, _len = _ref.length; _i < _len; _i++) { callback = _ref[_i]; i = 0; @@ -11706,7 +11801,7 @@ return; } obj.callback.isAddon = true; - return Klass.prototype.callbacks.push(obj.callback); + return Klass.callbacks.push(obj.callback); }, handleErrors: function(errors) { var div, error, logs, _i, _len; diff --git a/html/General/Settings-section-Rice.html b/html/General/Settings-section-Rice.html new file mode 100644 index 000000000..c4fa71ec4 --- /dev/null +++ b/html/General/Settings-section-Rice.html @@ -0,0 +1,60 @@ +
+ Custom Board Navigation is disabled. +
+
In the following, board can translate to a board ID (a, b, etc...), the current board (current), or the Twitter link (@).
+
Board link: board
+
Title link: board-title
+
Board link (Replace with title when on that board): board-replace
+
Full text link: board-full
+
Custom text link: board-text:"VIP Board"
+
Index-only link: board-index
+
Catalog-only link: board-catalog
+
Combinations are possible: board-index-text:"VIP Index"
+
Full board list toggle: toggle-all
+
+ +
+ Time Formatting is disabled. +
:
+
Supported format specifiers:
+
Day: %a, %A, %d, %e
+
Month: %m, %b, %B
+
Year: %y
+
Hour: %k, %H, %l, %I, %p, %P
+
Minute: %M
+
Second: %S
+
+ +
+ Quote Backlinks formatting is disabled. +
:
+
+ +
+ File Info Formatting is disabled. +
:
+
Link: %l (truncated), %L (untruncated), %T (Unix timestamp)
+
Original file name: %n (truncated), %N (untruncated), %t (Unix timestamp)
+
Spoiler indicator: %p
+
Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
+
Resolution: %r (Displays 'PDF' for PDF files)
+
+ +
+ Unread Tab Icon is disabled. + + +
+ +
+ + + + + +
diff --git a/img/changelog/3.9.0/0.png b/img/changelog/3.9.0/0.png new file mode 100644 index 000000000..36509d96d Binary files /dev/null and b/img/changelog/3.9.0/0.png differ diff --git a/json/archives.json b/json/archives.json index e2654302b..6a3291d10 100644 --- a/json/archives.json +++ b/json/archives.json @@ -43,15 +43,6 @@ "software": "foolfuuka", "boards": ["c", "w", "wg"], "files": ["c", "w", "wg"] -}, { - "uid": 11, - "name": "Foolz a Shit", - "domain": "archive.foolzashit.com", - "http": true, - "https": true, - "software": "foolfuuka", - "boards": ["adv", "asp", "cm", "d", "e", "i", "lgbt", "n", "o", "p", "pol", "s", "s4s", "t", "trv", "y"], - "files": ["cm", "d", "e", "i", "n", "o", "p", "s", "trv", "y"] }, { "uid": 12, "name": "FapArchive", @@ -59,8 +50,8 @@ "http": true, "https": true, "software": "foolfuuka", - "boards": ["b", "e", "h", "hc", "p", "s", "soc", "sp", "u"], - "files": ["b", "e", "h", "hc", "p", "s", "soc", "sp", "u"] + "boards": ["b", "con", "e", "h", "hc", "p", "s", "soc", "sp", "u"], + "files": ["b", "con", "e", "h", "hc", "p", "s", "soc", "sp", "u"] }, { "uid": 7, "name": "Install Gentoo", @@ -77,8 +68,8 @@ "http": true, "https": true, "software": "fuuka", - "boards": ["cgl", "g", "mu", "w"], - "files": ["cgl", "g", "mu", "w"] + "boards": ["cgl", "con", "g", "mu", "w"], + "files": ["cgl", "con", "g", "mu", "w"] }, { "uid": 9, "name": "Heinessen", diff --git a/package.json b/package.json index 5beac892b..1cfa6bde2 100755 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "font-awesome": "git://github.com/MayhemYDG/Font-Awesome.git#df4285951124f9ca1f3907438462e5ba9e464bcb", "grunt": "~0.4.1", "grunt-bump": "~0.0.11", - "grunt-concurrent": "~0.3.1", + "grunt-concurrent": "~0.4.0", "grunt-contrib-clean": "~0.5.0", "grunt-contrib-coffee": "~0.7.0", "grunt-contrib-compress": "~0.5.2", diff --git a/src/Filtering/Anonymize.coffee b/src/Filtering/Anonymize.coffee index d5b80f99c..414c428e5 100755 --- a/src/Filtering/Anonymize.coffee +++ b/src/Filtering/Anonymize.coffee @@ -2,7 +2,7 @@ Anonymize = init: -> return if g.VIEW is 'catalog' or !Conf['Anonymize'] - Post::callbacks.push + Post.callbacks.push name: 'Anonymize' cb: @node node: -> diff --git a/src/Filtering/Filter.coffee b/src/Filtering/Filter.coffee index e3f190edc..bab221ec4 100755 --- a/src/Filtering/Filter.coffee +++ b/src/Filtering/Filter.coffee @@ -67,7 +67,7 @@ Filter = delete @filters[key] return unless Object.keys(@filters).length - Post::callbacks.push + Post.callbacks.push name: 'Filter' cb: @node diff --git a/src/Filtering/PostHiding.coffee b/src/Filtering/PostHiding.coffee index a5efd70b6..9d3f409c8 100755 --- a/src/Filtering/PostHiding.coffee +++ b/src/Filtering/PostHiding.coffee @@ -6,7 +6,7 @@ PostHiding = $.addClass doc, "reply-hide" @db = new DataBoard 'hiddenPosts' - Post::callbacks.push + Post.callbacks.push name: 'Reply Hiding' cb: @node diff --git a/src/Filtering/Recursive.coffee b/src/Filtering/Recursive.coffee index 6af82976c..71a27713b 100755 --- a/src/Filtering/Recursive.coffee +++ b/src/Filtering/Recursive.coffee @@ -3,7 +3,7 @@ Recursive = init: -> return if g.VIEW is 'catalog' - Post::callbacks.push + Post.callbacks.push name: 'Recursive' cb: @node @@ -35,4 +35,4 @@ Recursive = for ID, post of g.posts if post.quotes.contains fullID recursive post, args... - return \ No newline at end of file + return diff --git a/src/Filtering/ThreadHiding.coffee b/src/Filtering/ThreadHiding.coffee index cc990e51e..4e8ef7bcd 100755 --- a/src/Filtering/ThreadHiding.coffee +++ b/src/Filtering/ThreadHiding.coffee @@ -4,7 +4,7 @@ ThreadHiding = @db = new DataBoard 'hiddenThreads' @syncCatalog() - Thread::callbacks.push + Thread.callbacks.push name: 'Thread Hiding' cb: @node diff --git a/src/General/Main.coffee b/src/General/Main.coffee index 50303d0af..c10daf517 100755 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -234,7 +234,7 @@ Main = callbackNodes: (klass, nodes) -> # get the nodes' length only once len = nodes.length - for callback in klass::callbacks + for callback in klass.callbacks # c.profile callback.name i = 0 while i < len @@ -301,7 +301,7 @@ Main = else return obj.callback.isAddon = true - Klass::callbacks.push obj.callback + Klass.callbacks.push obj.callback handleErrors: (errors) -> unless errors instanceof Array diff --git a/src/General/lib/post.class b/src/General/lib/post.class index aee4cce71..fe573ed79 100755 --- a/src/General/lib/post.class +++ b/src/General/lib/post.class @@ -1,5 +1,5 @@ class Post - callbacks: [] + @callbacks = [] toString: -> @ID constructor: (root, @thread, @board, that={}) -> diff --git a/src/General/lib/thread.class b/src/General/lib/thread.class index 57d82a316..1f15bf714 100755 --- a/src/General/lib/thread.class +++ b/src/General/lib/thread.class @@ -1,5 +1,5 @@ class Thread - callbacks: [] + @callbacks = [] toString: -> @ID constructor: (@ID, @board) -> diff --git a/src/Images/AutoGIF.coffee b/src/Images/AutoGIF.coffee new file mode 100644 index 000000000..71ccc7d8e --- /dev/null +++ b/src/Images/AutoGIF.coffee @@ -0,0 +1,20 @@ +AutoGIF = + init: -> + return if g.VIEW is 'catalog' or !Conf['Auto-GIF'] or g.BOARD.ID in ['gif', 'wsg'] + + Post.callbacks.push + name: 'Auto-GIF' + cb: @node + node: -> + return if @isClone or @isHidden or @thread.isHidden or !@file?.isImage + {thumb, URL} = @file + return unless /gif$/.test(URL) and !/spoiler/.test thumb.src + if @file.isSpoiler + # Revealed spoilers do not have height/width set, this fixes auto-gifs dimensions. + {style} = thumb + style.maxHeight = style.maxWidth = if @isReply then '125px' else '250px' + gif = $.el 'img' + $.on gif, 'load', -> + # Replace the thumbnail once the GIF has finished loading. + thumb.src = URL + gif.src = URL diff --git a/src/Images/FappeTyme.coffee b/src/Images/FappeTyme.coffee index 304eb2e03..29ebf2d30 100755 --- a/src/Images/FappeTyme.coffee +++ b/src/Images/FappeTyme.coffee @@ -30,7 +30,7 @@ FappeTyme = el: el order: 98 - Post::callbacks.push + Post.callbacks.push name: 'Fappe Tyme' cb: @node diff --git a/src/Images/Gallery.coffee b/src/Images/Gallery.coffee index 50de13643..1397ac21e 100644 --- a/src/Images/Gallery.coffee +++ b/src/Images/Gallery.coffee @@ -13,7 +13,7 @@ Gallery = Header.addShortcut el - Post::callbacks.push + Post.callbacks.push name: 'Gallery' cb: @node diff --git a/src/Images/ImageExpand.coffee b/src/Images/ImageExpand.coffee index a44eae537..600d4990e 100755 --- a/src/Images/ImageExpand.coffee +++ b/src/Images/ImageExpand.coffee @@ -10,7 +10,7 @@ ImageExpand = $.on @EAI, 'click', ImageExpand.cb.toggleAll Header.addShortcut @EAI, 2 - Post::callbacks.push + Post.callbacks.push name: 'Image Expansion' cb: @node node: -> diff --git a/src/Images/ImageHover.coffee b/src/Images/ImageHover.coffee index 5356f50c3..9ac26e045 100755 --- a/src/Images/ImageHover.coffee +++ b/src/Images/ImageHover.coffee @@ -2,7 +2,7 @@ ImageHover = init: -> return if g.VIEW is 'catalog' or !Conf['Image Hover'] - Post::callbacks.push + Post.callbacks.push name: 'Image Hover' cb: @node node: -> diff --git a/src/Images/ImageLoader.coffee b/src/Images/ImageLoader.coffee index b4df767d2..66220873e 100755 --- a/src/Images/ImageLoader.coffee +++ b/src/Images/ImageLoader.coffee @@ -3,7 +3,7 @@ ImageLoader = return if g.VIEW is 'catalog' return unless Conf["Image Prefetching"] or Conf["Replace JPG"] or Conf["Replace PNG"] or Conf["Replace GIF"] - Post::callbacks.push + Post.callbacks.push name: 'Image Replace' cb: @node diff --git a/src/Images/RevealSpoilers.coffee b/src/Images/RevealSpoilers.coffee index 8a884dd8b..b528036da 100755 --- a/src/Images/RevealSpoilers.coffee +++ b/src/Images/RevealSpoilers.coffee @@ -2,11 +2,11 @@ RevealSpoilers = init: -> return if g.VIEW is 'catalog' or !Conf['Reveal Spoiler Thumbnails'] - Post::callbacks.push - name: 'Reveal Spoiler Thumbnails' + Post.callbacks.push cb: @node + node: -> return if @isClone or !@file?.isSpoiler {thumb} = @file thumb.removeAttribute 'style' - thumb.src = @file.thumbURL \ No newline at end of file + thumb.src = @file.thumbURL diff --git a/src/Images/Sauce.coffee b/src/Images/Sauce.coffee index 92abea063..d182615bc 100755 --- a/src/Images/Sauce.coffee +++ b/src/Images/Sauce.coffee @@ -11,7 +11,7 @@ Sauce = return unless links.length @links = links @link = $.el 'a', target: '_blank' - Post::callbacks.push + Post.callbacks.push name: 'Sauce' cb: @node createSauceLink: (link) -> diff --git a/src/Linkification/Linkify.coffee b/src/Linkification/Linkify.coffee index a7aab6a2e..923c66613 100755 --- a/src/Linkification/Linkify.coffee +++ b/src/Linkification/Linkify.coffee @@ -26,7 +26,7 @@ Linkify = if Conf['Title Link'] $.sync 'CachedTitles', Linkify.titleSync - Post::callbacks.push + Post.callbacks.push name: 'Linkify' cb: @node diff --git a/src/Menu/Menu.coffee b/src/Menu/Menu.coffee index a02e56ee4..3589ac5b2 100755 --- a/src/Menu/Menu.coffee +++ b/src/Menu/Menu.coffee @@ -3,7 +3,7 @@ Menu = return if g.VIEW is 'catalog' or !Conf['Menu'] @menu = new UI.Menu 'post' - Post::callbacks.push + Post.callbacks.push name: 'Menu' cb: @node diff --git a/src/Miscellaneous/ColorUserIDs.coffee b/src/Miscellaneous/ColorUserIDs.coffee index c47d0cbcd..acb1b9b6c 100755 --- a/src/Miscellaneous/ColorUserIDs.coffee +++ b/src/Miscellaneous/ColorUserIDs.coffee @@ -3,7 +3,7 @@ IDColor = return if g.VIEW is 'catalog' or not Conf['Color User IDs'] @ids = {} - Post::callbacks.push + Post.callbacks.push name: 'Color User IDs' cb: @node diff --git a/src/Miscellaneous/Dice.coffee b/src/Miscellaneous/Dice.coffee index 7b7a3c386..d02698344 100755 --- a/src/Miscellaneous/Dice.coffee +++ b/src/Miscellaneous/Dice.coffee @@ -1,7 +1,7 @@ Dice = init: -> return if g.BOARD.ID isnt 'tg' or g.VIEW is 'catalog' or !Conf['Show Dice Roll'] - Post::callbacks.push + Post.callbacks.push name: 'Show Dice Roll' cb: @node node: -> diff --git a/src/Miscellaneous/ExpandComment.coffee b/src/Miscellaneous/ExpandComment.coffee index f5d194e6f..db55f37ba 100755 --- a/src/Miscellaneous/ExpandComment.coffee +++ b/src/Miscellaneous/ExpandComment.coffee @@ -2,14 +2,13 @@ ExpandComment = init: -> return if g.VIEW isnt 'index' or !Conf['Comment Expansion'] - if g.BOARD.ID is 'g' - @callbacks.push Fourchan.code - if g.BOARD.ID is 'sci' - @callbacks.push Fourchan.math + @callbacks.push Fourchan.code if g.BOARD.ID is 'g' + @callbacks.push Fourchan.math if g.BOARD.ID is 'sci' - Post::callbacks.push + Post.callbacks.push name: 'Comment Expansion' cb: @node + node: -> if a = $ '.abbr > a:not([onclick])', @nodes.comment $.on a, 'click', ExpandComment.cb diff --git a/src/Miscellaneous/ExpandThread.coffee b/src/Miscellaneous/ExpandThread.coffee index 5ea898fc7..0f0853f5f 100755 --- a/src/Miscellaneous/ExpandThread.coffee +++ b/src/Miscellaneous/ExpandThread.coffee @@ -2,7 +2,7 @@ ExpandThread = init: -> return if g.VIEW isnt 'index' or !Conf['Thread Expansion'] - Thread::callbacks.push + Thread.callbacks.push name: 'Thread Expansion' cb: @node diff --git a/src/Miscellaneous/FileInfo.coffee b/src/Miscellaneous/FileInfo.coffee index 38cff4ff4..89d694313 100755 --- a/src/Miscellaneous/FileInfo.coffee +++ b/src/Miscellaneous/FileInfo.coffee @@ -3,7 +3,7 @@ FileInfo = return if g.VIEW is 'catalog' or !Conf['File Info Formatting'] @funk = @createFunc Conf['fileInfo'] - Post::callbacks.push + Post.callbacks.push name: 'File Info Formatting' cb: @node node: -> @@ -48,4 +48,4 @@ FileInfo = B: -> FileInfo.convertUnit @file.sizeInBytes, 'B' K: -> FileInfo.convertUnit @file.sizeInBytes, 'KB' M: -> FileInfo.convertUnit @file.sizeInBytes, 'MB' - r: -> if @file.isImage then @file.dimensions else 'PDF' \ No newline at end of file + r: -> if @file.isImage then @file.dimensions else 'PDF' diff --git a/src/Miscellaneous/Fourchan.coffee b/src/Miscellaneous/Fourchan.coffee index 95f418ab4..64b1f4562 100755 --- a/src/Miscellaneous/Fourchan.coffee +++ b/src/Miscellaneous/Fourchan.coffee @@ -10,7 +10,7 @@ Fourchan = pre.innerHTML = prettyPrintOne(pre.innerHTML); }, false); """ - Post::callbacks.push + Post.callbacks.push name: 'Parse /g/ code' cb: @code if board is 'sci' @@ -27,7 +27,7 @@ Fourchan = } }, false); """ - Post::callbacks.push + Post.callbacks.push name: 'Parse /sci/ math' cb: @math code: -> diff --git a/src/Miscellaneous/IDColor.coffee b/src/Miscellaneous/IDColor.coffee new file mode 100644 index 000000000..1fbdd5718 --- /dev/null +++ b/src/Miscellaneous/IDColor.coffee @@ -0,0 +1,40 @@ +IDColor = + init: -> + return if g.VIEW is 'catalog' or !Conf['Color User IDs'] + @ids = {} + + Post.callbacks.push + name: 'Color User IDs' + cb: @node + + node: -> + return if @isClone or !(uid = @info.uniqueID) + rgb = IDColor.compute uid + span = @nodes.uniqueID + {style} = span + style.color = rgb[3] + style.backgroundColor = "rgb(#{rgb[0]},#{rgb[1]},#{rgb[2]})" + $.addClass span, 'painted' + span.textContent = uid + span.title = 'Highlight posts by this ID' + + compute: (uniqueID) -> + if uniqueID of IDColor.ids + return IDColor.ids[uniqueID] + hash = @hash uniqueID + rgb = [ + (hash >> 24) & 0xFF + (hash >> 16) & 0xFF + (hash >> 8) & 0xFF + ] + rgb.push if (rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) > 170 + 'black' + else + 'white' + @ids[uniqueID] = rgb + + hash: (uniqueID) -> + msg = 0 + for i in [0...uniqueID.length] by 1 + msg = (msg << 5) - msg + uniqueID.charCodeAt i + msg diff --git a/src/Miscellaneous/RelativeDates.coffee b/src/Miscellaneous/RelativeDates.coffee index 81f85285c..d678ecb23 100755 --- a/src/Miscellaneous/RelativeDates.coffee +++ b/src/Miscellaneous/RelativeDates.coffee @@ -9,7 +9,7 @@ RelativeDates = # Start the timeout. @flush() - Post::callbacks.push + Post.callbacks.push name: 'Relative Post Dates' cb: @node node: -> @@ -104,4 +104,4 @@ RelativeDates = markStale = -> RelativeDates.stale.push update # Kick off initial timeout. - update new Date() \ No newline at end of file + update new Date() diff --git a/src/Miscellaneous/RemoveSpoilers.coffee b/src/Miscellaneous/RemoveSpoilers.coffee index b9e5d0e58..5518f88bf 100755 --- a/src/Miscellaneous/RemoveSpoilers.coffee +++ b/src/Miscellaneous/RemoveSpoilers.coffee @@ -9,7 +9,7 @@ RemoveSpoilers = @wrapper = (text) -> "[spoiler]#{text}[/spoiler]" - Post::callbacks.push + Post.callbacks.push name: 'Reveal Spoilers' cb: @node diff --git a/src/Miscellaneous/Time.coffee b/src/Miscellaneous/Time.coffee index 540cfb637..40d581179 100755 --- a/src/Miscellaneous/Time.coffee +++ b/src/Miscellaneous/Time.coffee @@ -3,7 +3,7 @@ Time = return if g.VIEW is 'catalog' or !Conf['Time Formatting'] @funk = @createFunc Conf['time'] - Post::callbacks.push + Post.callbacks.push name: 'Time Formatting' cb: @node node: -> diff --git a/src/Monitoring/ThreadExcerpt.coffee b/src/Monitoring/ThreadExcerpt.coffee index ed67edfa4..dc55c1b04 100755 --- a/src/Monitoring/ThreadExcerpt.coffee +++ b/src/Monitoring/ThreadExcerpt.coffee @@ -2,8 +2,8 @@ ThreadExcerpt = init: -> return if g.VIEW isnt 'thread' or !Conf['Thread Excerpt'] - Thread::callbacks.push + Thread.callbacks.push name: 'Thread Excerpt' cb: @node node: -> - d.title = Get.threadExcerpt @ \ No newline at end of file + d.title = Get.threadExcerpt @ diff --git a/src/Monitoring/ThreadStats.coffee b/src/Monitoring/ThreadStats.coffee index 452caf4cd..e154535da 100755 --- a/src/Monitoring/ThreadStats.coffee +++ b/src/Monitoring/ThreadStats.coffee @@ -19,7 +19,7 @@ ThreadStats = @fileCountEl = $ '#file-count', sc @pageCountEl = $ '#page-count', sc - Thread::callbacks.push + Thread.callbacks.push name: 'Thread Stats' cb: @node diff --git a/src/Monitoring/ThreadUpdater.coffee b/src/Monitoring/ThreadUpdater.coffee index 85850db95..ee731e212 100755 --- a/src/Monitoring/ThreadUpdater.coffee +++ b/src/Monitoring/ThreadUpdater.coffee @@ -54,7 +54,7 @@ ThreadUpdater = order: 110 subEntries: subEntries - Thread::callbacks.push + Thread.callbacks.push name: 'Thread Updater' cb: @node diff --git a/src/Monitoring/ThreadWatcher.coffee b/src/Monitoring/ThreadWatcher.coffee index 7f1712559..8ea86cddb 100755 --- a/src/Monitoring/ThreadWatcher.coffee +++ b/src/Monitoring/ThreadWatcher.coffee @@ -31,7 +31,7 @@ ThreadWatcher = ThreadWatcher.fetchAllStatus() @db.save() - Thread::callbacks.push + Thread.callbacks.push name: 'Thread Watcher' cb: @node diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee index 90a279ee8..76e3e30d0 100755 --- a/src/Monitoring/Unread.coffee +++ b/src/Monitoring/Unread.coffee @@ -8,7 +8,7 @@ Unread = @posts = [] @postsQuotingYou = [] - Thread::callbacks.push + Thread.callbacks.push name: 'Unread' cb: @node @@ -90,7 +90,7 @@ Unread = for quotelink in post.nodes.quotelinks when QR.db.get Get.postDataFromLink quotelink Unread.postsQuotingYou.push post Unread.openNotification post - return + return openNotification: (post) -> return unless Header.areNotificationsEnabled diff --git a/src/Posting/QuickReply.coffee b/src/Posting/QuickReply.coffee index a585c6b48..e9152c782 100755 --- a/src/Posting/QuickReply.coffee +++ b/src/Posting/QuickReply.coffee @@ -33,7 +33,7 @@ QR = else $.ready @persist - Post::callbacks.push + Post.callbacks.push name: 'Quick Reply' cb: @node @@ -445,7 +445,6 @@ QR = e.preventDefault() QR.open() QR.handleFiles e.dataTransfer.files - $.addClass QR.nodes.el, 'dump' paste: (e) -> files = [] @@ -1223,6 +1222,7 @@ QR = threadID postID } + $.event 'QRPostSuccessful_', {threadID, postID} # Enable auto-posting if we have stuff left to post, disable it otherwise. postsCount = QR.posts.length - 1 diff --git a/src/Quotelinks/QuoteBacklink.coffee b/src/Quotelinks/QuoteBacklink.coffee index ae4a4b433..a5de2fa96 100755 --- a/src/Quotelinks/QuoteBacklink.coffee +++ b/src/Quotelinks/QuoteBacklink.coffee @@ -16,10 +16,10 @@ QuoteBacklink = format = Conf['backlink'].replace /%id/g, "' + id + '" @funk = Function 'id', "return '#{format}'" @containers = {} - Post::callbacks.push + Post.callbacks.push name: 'Quote Backlinking Part 1' cb: @firstNode - Post::callbacks.push + Post.callbacks.push name: 'Quote Backlinking Part 2' cb: @secondNode firstNode: -> @@ -55,4 +55,4 @@ QuoteBacklink = $.add @nodes.info, container getContainer: (id) -> @containers[id] or= - $.el 'span', className: 'container' \ No newline at end of file + $.el 'span', className: 'container' diff --git a/src/Quotelinks/QuoteCT.coffee b/src/Quotelinks/QuoteCT.coffee index b0618d487..953c7e20f 100755 --- a/src/Quotelinks/QuoteCT.coffee +++ b/src/Quotelinks/QuoteCT.coffee @@ -7,7 +7,7 @@ QuoteCT = # \u00A0 is nbsp @text = '\u00A0(Cross-thread)' - Post::callbacks.push + Post.callbacks.push name: 'Mark Cross-thread Quotes' cb: @node node: -> diff --git a/src/Quotelinks/QuoteInline.coffee b/src/Quotelinks/QuoteInline.coffee index 95a225e38..3aa3fd455 100755 --- a/src/Quotelinks/QuoteInline.coffee +++ b/src/Quotelinks/QuoteInline.coffee @@ -18,7 +18,7 @@ QuoteInline = if Conf['Comment Expansion'] ExpandComment.callbacks.push @node - Post::callbacks.push + Post.callbacks.push name: 'Quote Inlining' cb: @node diff --git a/src/Quotelinks/QuoteOP.coffee b/src/Quotelinks/QuoteOP.coffee index 721688a6b..1f5554dfe 100755 --- a/src/Quotelinks/QuoteOP.coffee +++ b/src/Quotelinks/QuoteOP.coffee @@ -7,7 +7,7 @@ QuoteOP = # \u00A0 is nbsp @text = '\u00A0(OP)' - Post::callbacks.push + Post.callbacks.push name: 'Mark OP Quotes' cb: @node diff --git a/src/Quotelinks/QuotePreview.coffee b/src/Quotelinks/QuotePreview.coffee index 15fd65f64..17c9e1b0c 100755 --- a/src/Quotelinks/QuotePreview.coffee +++ b/src/Quotelinks/QuotePreview.coffee @@ -5,7 +5,7 @@ QuotePreview = if Conf['Comment Expansion'] ExpandComment.callbacks.push @node - Post::callbacks.push + Post.callbacks.push name: 'Quote Previewing' cb: @node diff --git a/src/Quotelinks/QuoteStrikeThrough.coffee b/src/Quotelinks/QuoteStrikeThrough.coffee index 53d4e0fc1..0a7098f39 100755 --- a/src/Quotelinks/QuoteStrikeThrough.coffee +++ b/src/Quotelinks/QuoteStrikeThrough.coffee @@ -2,7 +2,7 @@ QuoteStrikeThrough = init: -> return if g.VIEW is 'catalog' or !Conf['Reply Hiding Buttons'] and !Conf['Reply Hiding Link'] and !Conf['Filter'] - Post::callbacks.push + Post.callbacks.push name: 'Strike-through Quotes' cb: @node @@ -12,4 +12,4 @@ QuoteStrikeThrough = {boardID, postID} = Get.postDataFromLink quotelink if g.posts["#{boardID}.#{postID}"]?.isHidden $.addClass quotelink, 'filtered' - return \ No newline at end of file + return diff --git a/src/Quotelinks/QuoteThreading.coffee b/src/Quotelinks/QuoteThreading.coffee index f977a82a3..ec28ddfcb 100755 --- a/src/Quotelinks/QuoteThreading.coffee +++ b/src/Quotelinks/QuoteThreading.coffee @@ -20,7 +20,7 @@ QuoteThreading = $.on d, '4chanXInitFinished', @setup - Post::callbacks.push + Post.callbacks.push name: 'Quote Threading' cb: @node diff --git a/src/Quotelinks/QuoteYou.coffee b/src/Quotelinks/QuoteYou.coffee index bcd74eab9..876c7d318 100755 --- a/src/Quotelinks/QuoteYou.coffee +++ b/src/Quotelinks/QuoteYou.coffee @@ -11,7 +11,9 @@ QuoteYou = if Conf['Comment Expansion'] ExpandComment.callbacks.push @node - Post::callbacks.push + # \u00A0 is nbsp + @text = '\u00A0(You)' + Post.callbacks.push name: 'Mark Quotes of You' cb: @node @@ -25,7 +27,7 @@ QuoteYou = return unless @quotes.length for quotelink in @nodes.quotelinks when QR.db.get Get.postDataFromLink quotelink - $.add quotelink, $.tn '\u00A0(You)' + $.add quotelink, $.tn QuoteYou.text $.addClass quotelink, 'you' $.addClass @nodes.root, 'quotesYou' return diff --git a/src/Quotelinks/Quotify.coffee b/src/Quotelinks/Quotify.coffee index c8679c17e..3fd3fc2bb 100755 --- a/src/Quotelinks/Quotify.coffee +++ b/src/Quotelinks/Quotify.coffee @@ -5,7 +5,7 @@ Quotify = if Conf['Comment Expansion'] ExpandComment.callbacks.push @node - Post::callbacks.push + Post.callbacks.push name: 'Resurrect Quotes' cb: @node node: -> @@ -81,4 +81,9 @@ Quotify = @nodes.quotelinks.push a fixDeadlink: (deadlink) -> + if !(el = deadlink.previousSibling) or el.nodeName is 'BR' + green = $.el 'span', + className: 'quote' + $.before deadlink, green + $.add green, deadlink $.replace deadlink, [deadlink.childNodes...]