diff --git a/4chan_x.user.js b/4chan_x.user.js index 9dd7b7d11..d3c0d9bde 100644 --- a/4chan_x.user.js +++ b/4chan_x.user.js @@ -3907,17 +3907,20 @@ req = ThreadUpdater.req; switch (req.status) { case 200: + g.DEAD = false; ThreadUpdater.parse(JSON.parse(req.response).posts); ThreadUpdater.lastModified = req.getResponseHeader('Last-Modified'); ThreadUpdater.set('timer', ThreadUpdater.getInterval()); break; case 404: + g.DEAD = true; ThreadUpdater.set('timer', null); ThreadUpdater.set('status', '404', 'warning'); clearTimeout(ThreadUpdater.timeoutID); ThreadUpdater.thread.kill(); $.event('ThreadUpdate', { - 404: true + 404: true, + thread: ThreadUpdater.thread }); break; default: @@ -4052,6 +4055,7 @@ } return $.event('ThreadUpdate', { 404: false, + thread: ThreadUpdater.thread, newPosts: posts, deletedPosts: deletedPosts, deletedFiles: deletedFiles @@ -4104,6 +4108,13 @@ return QR.hide(); } }); + $.on(d, 'ThreadUpdate', function() { + if (g.DEAD) { + return QR.abort(); + } else { + return QR.status(); + } + }); return Post.prototype.callbacks.push({ name: 'Quick Reply', cb: this.node @@ -4145,7 +4156,7 @@ if (!Conf['Remember Spoiler'] && (spoiler = $.id('spoiler')).checked) { spoiler.click(); } - return QR.cleanNotification(); + return QR.cleanNotifications(); }, hide: function() { d.activeElement.blur(); @@ -4178,14 +4189,17 @@ if (d.hidden) { alert(el.textContent); } - return QR.lastNotification = new Notification('warning', el); + return QR.lastNotifications.push(new Notification('warning', el)); }, - cleanNotification: function() { - var _ref; - if ((_ref = QR.lastNotification) != null) { - _ref.close(); + lastNotifications: [], + cleanNotifications: function() { + var notification, _i, _len, _ref; + _ref = QR.lastNotifications; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + notification = _ref[_i]; + notification.close(); } - return delete QR.lastNotification; + return QR.lastNotification = []; }, status: function(data) { var disabled, input, value; @@ -4377,7 +4391,7 @@ }, fileInput: function() { var file, _i, _len, _ref; - QR.cleanNotification(); + QR.cleanNotifications(); if (this.files.length === 1) { file = this.files[0]; if (file.size > this.max) { @@ -4395,11 +4409,9 @@ for (_i = 0, _len = _ref.length; _i < _len; _i++) { file = _ref[_i]; if (file.size > this.max) { - QR.error("File " + file.name + " is too large."); - break; + QR.error("File " + file.name + " is too large (" + ($.bytesToString(file.size)) + ")."); } else if (-1 === QR.mimeTypes.indexOf(file.type)) { QR.error("" + file.name + ": Unsupported file type."); - break; } if (!QR.replies[QR.replies.length - 1].file) { QR.replies[QR.replies.length - 1].setFile(file); @@ -4868,7 +4880,7 @@ QR.error(err); return; } - QR.cleanNotification(); + QR.cleanNotifications(); QR.cooldown.auto = QR.replies.length > 1; if (Conf['Auto Hide QR'] && !QR.cooldown.auto) { QR.hide(); @@ -4927,6 +4939,7 @@ }, response: function(html) { var ban, board, err, h1, persona, postID, reply, threadID, tmpDoc, _, _ref, _ref1; + delete QR.ajax; tmpDoc = d.implementation.createHTMLDocument(''); tmpDoc.documentElement.innerHTML = html; if (ban = $('.banType', tmpDoc)) { @@ -4958,7 +4971,8 @@ return; } h1 = $('h1', tmpDoc); - QR.lastNotification = new Notification('success', h1.textContent, 5); + QR.cleanNotifications(); + QR.lastNotifications.push(new Notification('success', h1.textContent, 5)); reply = QR.replies[0]; persona = $.get('QR.persona', {}); persona = { @@ -4991,11 +5005,11 @@ return QR.resetFileInput(); }, abort: function() { - var _ref; - if ((_ref = QR.ajax) != null) { - _ref.abort(); + if (QR.ajax) { + QR.ajax.abort(); + delete QR.ajax; + QR.error('QR upload aborted.'); } - delete QR.ajax; return QR.status(); } }; diff --git a/src/features.coffee b/src/features.coffee index c1f6adfe0..2695fbfdb 100644 --- a/src/features.coffee +++ b/src/features.coffee @@ -2410,21 +2410,24 @@ ThreadUpdater = {req} = ThreadUpdater switch req.status when 200 + g.DEAD = false ThreadUpdater.parse JSON.parse(req.response).posts ThreadUpdater.lastModified = req.getResponseHeader 'Last-Modified' ThreadUpdater.set 'timer', ThreadUpdater.getInterval() when 404 + g.DEAD = true ThreadUpdater.set 'timer', null ThreadUpdater.set 'status', '404', 'warning' clearTimeout ThreadUpdater.timeoutID ThreadUpdater.thread.kill() - $.event 'ThreadUpdate', 404: true + $.event 'ThreadUpdate', + 404: true + thread: ThreadUpdater.thread # if Conf['Unread Count'] # Unread.title = Unread.title.match(/^.+-/)[0] + ' 404' # else # d.title = d.title.match(/^.+-/)[0] + ' 404' # Unread.update true - # QR.abort() else ThreadUpdater.outdateCount++ ThreadUpdater.set 'timer', ThreadUpdater.getInterval() @@ -2536,6 +2539,7 @@ ThreadUpdater = $.event 'ThreadUpdate', 404: false + thread: ThreadUpdater.thread newPosts: posts deletedPosts: deletedPosts deletedFiles: deletedFiles diff --git a/src/qr.coffee b/src/qr.coffee index 56ead95f5..d2a2fa110 100644 --- a/src/qr.coffee +++ b/src/qr.coffee @@ -32,6 +32,11 @@ QR = return unless Conf['Persistent QR'] QR.open() QR.hide() if Conf['Auto Hide QR'] + $.on d, 'ThreadUpdate', -> + if g.DEAD + QR.abort() + else + QR.status() Post::callbacks.push name: 'Quick Reply' @@ -64,7 +69,7 @@ QR = QR.resetFileInput() if not Conf['Remember Spoiler'] and (spoiler = $.id 'spoiler').checked spoiler.click() - QR.cleanNotification() + QR.cleanNotifications() hide: -> d.activeElement.blur() $.addClass QR.el, 'autohide' @@ -89,10 +94,12 @@ QR = # Focus the captcha input on captcha error. $('[autocomplete]', QR.el).focus() alert el.textContent if d.hidden - QR.lastNotification = new Notification 'warning', el - cleanNotification: -> - QR.lastNotification?.close() - delete QR.lastNotification + QR.lastNotifications.push new Notification 'warning', el + lastNotifications: [] + cleanNotifications: -> + for notification in QR.lastNotifications + notification.close() + QR.lastNotification = [] status: (data={}) -> return unless QR.el @@ -278,7 +285,7 @@ QR = QR.fileInput.call e.dataTransfer $.addClass QR.el, 'dump' fileInput: -> - QR.cleanNotification() + QR.cleanNotifications() # Set or change current reply's file. if @files.length is 1 file = @files[0] @@ -294,11 +301,9 @@ QR = # Create new replies with these files. for file in @files if file.size > @max - QR.error "File #{file.name} is too large." - break + QR.error "File #{file.name} is too large (#{$.bytesToString file.size})." else if -1 is QR.mimeTypes.indexOf file.type QR.error "#{file.name}: Unsupported file type." - break unless QR.replies[QR.replies.length - 1].file # set last reply's file QR.replies[QR.replies.length - 1].setFile file @@ -668,7 +673,7 @@ QR = QR.status() QR.error err return - QR.cleanNotification() + QR.cleanNotifications() # Enable auto-posting if we have stuff to post, disable it otherwise. QR.cooldown.auto = QR.replies.length > 1 @@ -722,6 +727,8 @@ QR = QR.ajax = $.ajax $.id('postForm').parentNode.action, callbacks, opts response: (html) -> + delete QR.ajax + tmpDoc = d.implementation.createHTMLDocument '' tmpDoc.documentElement.innerHTML = html if ban = $ '.banType', tmpDoc # banned/warning @@ -763,7 +770,8 @@ QR = return h1 = $ 'h1', tmpDoc - QR.lastNotification = new Notification 'success', h1.textContent, 5 + QR.cleanNotifications() + QR.lastNotifications.push new Notification 'success', h1.textContent, 5 reply = QR.replies[0] @@ -803,6 +811,8 @@ QR = QR.resetFileInput() abort: -> - QR.ajax?.abort() - delete QR.ajax + if QR.ajax + QR.ajax.abort() + delete QR.ajax + QR.error 'QR upload aborted.' QR.status()