diff --git a/4chan_x.user.js b/4chan_x.user.js
index 26b98a863..16e57db55 100644
--- a/4chan_x.user.js
+++ b/4chan_x.user.js
@@ -2246,6 +2246,7 @@
Unread.foresee.push(postID);
}
if (g.REPLY && Conf['Thread Updater'] && Conf['Auto Update This']) {
+ Updater.unsuccessfulFetchCount = 0;
Updater.update();
}
QR.status();
@@ -2567,7 +2568,7 @@
Updater = {
init: function() {
var checkbox, checked, dialog, html, input, name, title, _i, _len, _ref;
- html = "
-" + Conf['Interval'] + "
";
+ html = '
';
checkbox = Config.updater.checkbox;
for (name in checkbox) {
title = checkbox[name][1];
@@ -2575,11 +2576,13 @@
html += "";
}
checked = Conf['Auto Update'] ? 'checked' : '';
- html += " ";
+ html += " ";
dialog = UI.dialog('updater', 'bottom: 0; right: 0;', html);
this.count = $('#count', dialog);
this.timer = $('#timer', dialog);
this.thread = $.id("t" + g.THREAD_ID);
+ this.unsuccessfulFetchCount = 0;
+ this.lastModified = '0';
_ref = $$('input', dialog);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
input = _ref[_i];
@@ -2598,21 +2601,22 @@
Conf[input.name] = input.checked;
}
} else if (input.name === 'Interval') {
+ input.value = Conf['Interval'];
$.on(input, 'input', this.cb.interval);
+ this.cb.interval.call(input);
} else if (input.type === 'button') {
$.on(input, 'click', this.update);
}
}
- $.add(d.body, dialog);
- this.retryCoef = 10;
- return this.lastModified = 0;
+ return $.add(d.body, dialog);
},
cb: {
interval: function() {
var val;
val = parseInt(this.value, 10);
- this.value = val > 0 ? val : 1;
- return $.cb.value.call(this);
+ this.value = val > 5 ? val : 5;
+ $.cb.value.call(this);
+ return Updater.timer.textContent = "-" + (Updater.getInterval());
},
verbose: function() {
if (Conf['Verbose']) {
@@ -2641,7 +2645,7 @@
};
},
update: function() {
- var count, doc, id, lastPost, nodes, reply, scroll, _i, _len, _ref, _ref1;
+ var count, doc, id, lastPost, nodes, reply, scroll, _i, _len, _ref, _ref1, _ref2;
if (this.status === 404) {
Updater.timer.textContent = '';
Updater.count.textContent = 404;
@@ -2658,15 +2662,15 @@
return;
}
if ((_ref = this.status) !== 0 && _ref !== 200 && _ref !== 304) {
- Updater.retryCoef += 10 * (Updater.retryCoef < 120);
if (Conf['Verbose']) {
Updater.count.textContent = this.statusText;
Updater.count.className = 'warning';
}
+ Updater.unsuccessfulFetchCount++;
return;
}
- Updater.retryCoef = 10;
- Updater.timer.textContent = "-" + Conf['Interval'];
+ Updater.unsuccessfulFetchCount++;
+ Updater.timer.textContent = "-" + (Updater.getInterval());
/*
Status Code 304: Not modified
By sending the `If-Modified-Since` header we get a proper status code, and no response.
@@ -2674,7 +2678,7 @@
and won't load images and scripts when parsing the response.
*/
- if (this.status === 304) {
+ if ((_ref1 = this.status) === 0 || _ref1 === 304) {
if (Conf['Verbose']) {
Updater.count.textContent = '+0';
Updater.count.className = null;
@@ -2687,44 +2691,52 @@
lastPost = Updater.thread.lastElementChild;
id = lastPost.id.slice(2);
nodes = [];
- _ref1 = $$('.replyContainer', doc).reverse();
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
- reply = _ref1[_i];
+ _ref2 = $$('.replyContainer', doc).reverse();
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+ reply = _ref2[_i];
if (reply.id.slice(2) <= id) {
break;
}
nodes.push(reply);
}
count = nodes.length;
- scroll = Conf['Scrolling'] && Updater.scrollBG() && count && lastPost.getBoundingClientRect().bottom - d.documentElement.clientHeight < 25;
if (Conf['Verbose']) {
Updater.count.textContent = "+" + count;
Updater.count.className = count ? 'new' : null;
}
+ if (!count) {
+ return;
+ }
+ Updater.unsuccessfulFetchCount = 0;
+ Updater.timer.textContent = "-" + (Updater.getInterval());
+ scroll = Conf['Scrolling'] && Updater.scrollBG() && lastPost.getBoundingClientRect().bottom - d.documentElement.clientHeight < 25;
$.add(Updater.thread, nodes.reverse());
if (scroll) {
return nodes[0].scrollIntoView();
}
}
},
+ getInterval: function() {
+ var i, j;
+ i = +Conf['Interval'];
+ j = Math.min(this.unsuccessfulFetchCount, 9);
+ return Math.max(i, [5, 10, 15, 20, 30, 60, 90, 120, 300, 600][j]);
+ },
timeout: function() {
var n;
Updater.timeoutID = setTimeout(Updater.timeout, 1000);
n = 1 + Number(Updater.timer.textContent);
if (n === 0) {
return Updater.update();
- } else if (n === Updater.retryCoef) {
- Updater.retryCoef += 10 * (Updater.retryCoef < 120);
- return Updater.retry();
+ } else if (n === Updater.getInterval()) {
+ Updater.unsuccessfulFetchCount++;
+ Updater.count.textContent = 'Retry';
+ Updater.count.className = null;
+ return Updater.update();
} else {
return Updater.timer.textContent = n;
}
},
- retry: function() {
- this.count.textContent = 'Retry';
- this.count.className = null;
- return this.update();
- },
update: function() {
var url, _ref;
Updater.timer.textContent = 0;
@@ -5087,6 +5099,9 @@ body.unscroll {\
border: none;\
background: transparent;\
}\
+#updater input[type=number] {\
+ width: 4em;\
+}\
.new {\
background: lime;\
}\
diff --git a/changelog b/changelog
index 8e462e5c9..00bcd8b04 100644
--- a/changelog
+++ b/changelog
@@ -1,4 +1,7 @@
master
+- Mayhem
+ The updater's refresh interval will now increase gradually in inactive threads.
+ The updater's refresh interval is now limited to 5 seconds minimum.
2.33.8
- Mayhem
diff --git a/script.coffee b/script.coffee
index 9091549f9..696b4d779 100644
--- a/script.coffee
+++ b/script.coffee
@@ -1715,6 +1715,7 @@ QR =
if g.REPLY and (Conf['Unread Count'] or Conf['Unread Favicon'])
Unread.foresee.push postID
if g.REPLY and Conf['Thread Updater'] and Conf['Auto Update This']
+ Updater.unsuccessfulFetchCount = 0
Updater.update()
QR.status()
@@ -2000,7 +2001,7 @@ Options =
Updater =
init: ->
- html = " -#{Conf['Interval']}
"
+ html = '
'
{checkbox} = Config.updater
for name of checkbox
title = checkbox[name][1]
@@ -2010,7 +2011,7 @@ Updater =
checked = if Conf['Auto Update'] then 'checked' else ''
html += "
-
+
"
dialog = UI.dialog 'updater', 'bottom: 0; right: 0;', html
@@ -2019,6 +2020,9 @@ Updater =
@timer = $ '#timer', dialog
@thread = $.id "t#{g.THREAD_ID}"
+ @unsuccessfulFetchCount = 0
+ @lastModified = '0'
+
for input in $$ 'input', dialog
if input.type is 'checkbox'
$.on input, 'click', $.cb.checked
@@ -2034,20 +2038,20 @@ Updater =
# Required for the QR's update after posting.
Conf[input.name] = input.checked
else if input.name is 'Interval'
+ input.value = Conf['Interval']
$.on input, 'input', @cb.interval
+ @cb.interval.call input
else if input.type is 'button'
$.on input, 'click', @update
$.add d.body, dialog
- @retryCoef = 10
- @lastModified = 0
-
cb:
interval: ->
val = parseInt @value, 10
- @value = if val > 0 then val else 1
+ @value = if val > 5 then val else 5
$.cb.value.call @
+ Updater.timer.textContent = "-#{Updater.getInterval()}"
verbose: ->
if Conf['Verbose']
Updater.count.textContent = '+0'
@@ -2084,14 +2088,14 @@ Updater =
return
unless @status in [0, 200, 304]
# XXX 304 -> 0 in Opera
- Updater.retryCoef += 10 * (Updater.retryCoef < 120)
if Conf['Verbose']
Updater.count.textContent = @statusText
Updater.count.className = 'warning'
+ Updater.unsuccessfulFetchCount++
return
- Updater.retryCoef = 10
- Updater.timer.textContent = "-#{Conf['Interval']}"
+ Updater.unsuccessfulFetchCount++
+ Updater.timer.textContent = "-#{Updater.getInterval()}"
###
Status Code 304: Not modified
@@ -2099,7 +2103,8 @@ Updater =
This saves bandwidth for both the user and the servers, avoid unnecessary computation,
and won't load images and scripts when parsing the response.
###
- if @status is 304
+ if @status in [0, 304]
+ # XXX 304 -> 0 in Opera
if Conf['Verbose']
Updater.count.textContent = '+0'
Updater.count.className = null
@@ -2116,38 +2121,44 @@ Updater =
break if reply.id[2..] <= id #make sure to not insert older posts
nodes.push reply
- count = nodes.length
- scroll = Conf['Scrolling'] && Updater.scrollBG() && count &&
- lastPost.getBoundingClientRect().bottom - d.documentElement.clientHeight < 25
+ count = nodes.length
if Conf['Verbose']
Updater.count.textContent = "+#{count}"
Updater.count.className = if count then 'new' else null
+ return unless count
+
+ Updater.unsuccessfulFetchCount = 0
+ Updater.timer.textContent = "-#{Updater.getInterval()}"
+ scroll = Conf['Scrolling'] && Updater.scrollBG() &&
+ lastPost.getBoundingClientRect().bottom - d.documentElement.clientHeight < 25
$.add Updater.thread, nodes.reverse()
if scroll
nodes[0].scrollIntoView()
+ getInterval: ->
+ i = +Conf['Interval']
+ j = Math.min @unsuccessfulFetchCount, 9
+ Math.max i, [5, 10, 15, 20, 30, 60, 90, 120, 300, 600][j]
+
timeout: ->
Updater.timeoutID = setTimeout Updater.timeout, 1000
n = 1 + Number Updater.timer.textContent
if n is 0
Updater.update()
- else if n is Updater.retryCoef
- Updater.retryCoef += 10 * (Updater.retryCoef < 120)
- Updater.retry()
+ else if n is Updater.getInterval()
+ Updater.unsuccessfulFetchCount++
+ Updater.count.textContent = 'Retry'
+ Updater.count.className = null
+ Updater.update()
else
Updater.timer.textContent = n
- retry: ->
- @count.textContent = 'Retry'
- @count.className = null
- @update()
-
update: ->
Updater.timer.textContent = 0
Updater.request?.abort()
- #fool the cache
+ # Fool the cache.
url = location.pathname + '?' + Date.now()
Updater.request = $.ajax url, onload: Updater.cb.update,
headers: 'If-Modified-Since': Updater.lastModified
@@ -4005,6 +4016,9 @@ body.unscroll {
border: none;
background: transparent;
}
+#updater input[type=number] {
+ width: 4em;
+}
.new {
background: lime;
}