diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4274c0f3..fb8b47c62 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,15 @@ The attributions below are for work that has been incorporated into the script a
The links to individual versions below are to copies of the script with the update URL removed. If you want automatic updates, install the script from the links on the [main page](https://github.com/ccd0/4chan-x).
+
+### v1.9.13.0
+*2014-11-23* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.13.0/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.13.0/builds/4chan-X-noupdate.crx "Chromium version")]
+
+**ccd0**
+- Improve unread count compatibility with quote threading.
+- Add `Fullscreen Gallery` option (off by default).
+- Make close, pause, and slideshow keybinds of gallery configurable.
+
### v1.9.12.5
*2014-11-22* - [[Firefox](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.12.5/builds/4chan-X-noupdate.user.js "Firefox version")] [[Chromium](https://raw.githubusercontent.com/ccd0/4chan-x/1.9.12.5/builds/4chan-X-noupdate.crx "Chromium version")]
diff --git a/LICENSE b/LICENSE
index 3b441c6ef..a4c2afdab 100755
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,5 @@
/*
-* 4chan X - Version 1.9.12.5
+* 4chan X - Version 1.9.13.0
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx
index 40b4b31b4..4a05feedc 100644
Binary files a/builds/4chan-X-beta.crx and b/builds/4chan-X-beta.crx differ
diff --git a/builds/4chan-X-beta.meta.js b/builds/4chan-X-beta.meta.js
index 237e3d99a..dd9180555 100644
--- a/builds/4chan-X-beta.meta.js
+++ b/builds/4chan-X-beta.meta.js
@@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X beta
-// @version 1.9.12.5
+// @version 1.9.13.0
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
diff --git a/builds/4chan-X-beta.user.js b/builds/4chan-X-beta.user.js
index 11136873d..63af86101 100644
--- a/builds/4chan-X-beta.user.js
+++ b/builds/4chan-X-beta.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X beta
-// @version 1.9.12.5
+// @version 1.9.13.0
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -24,7 +24,7 @@
// ==/UserScript==
/*
-* 4chan X - Version 1.9.12.5
+* 4chan X - Version 1.9.13.0
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
@@ -178,6 +178,7 @@
'Image Hover': [true, 'Show full image / video on mouseover.'],
'Image Hover in Catalog': [false, 'Show full image / video on mouseover in 4chan X catalog.'],
'Gallery': [true, 'Adds a simple and cute image gallery.'],
+ 'Fullscreen Gallery': [false, 'Open gallery in fullscreen mode.'],
'PDF in Gallery': [false, 'Show PDF files in gallery.'],
'Sauce': [true, 'Add sauce links to images.'],
'Reveal Spoiler Thumbnails': [false, 'Replace spoiler thumbnails with the original image.'],
@@ -267,7 +268,7 @@
'Fit Width': [true],
'Fit Height': [true],
'Scroll to Post': [true],
- 'Slide Delay': [5.0]
+ 'Slide Delay': [6.0]
},
threadWatcher: {
'Current Board': [false, 'Only show watched threads from the current board.'],
@@ -330,7 +331,7 @@
'Open empty QR': ['q', 'Open QR without post number inserted.'],
'Open QR': ['Shift+q', 'Open QR with post number inserted.'],
'Open settings': ['Alt+o', 'Open Settings.'],
- 'Close': ['Esc', 'Close Settings, Notifications or QR.'],
+ 'Close': ['Esc', 'Close Settings/Notifications/QR/Gallery.'],
'Spoiler tags': ['Ctrl+s', 'Insert spoiler tags.'],
'Code tags': ['Alt+c', 'Insert code tags.'],
'Eqn tags': ['Alt+e', 'Insert eqn tags.'],
@@ -342,6 +343,8 @@
'Expand image': ['Shift+e', 'Expand selected image.'],
'Expand images': ['e', 'Expand all images.'],
'Open Gallery': ['g', 'Opens the gallery.'],
+ 'Pause': ['p', 'Pause/play videos in the gallery.'],
+ 'Slideshow': ['s', 'Toggle the gallery slideshow mode.'],
'fappeTyme': ['f', 'Toggle Fappe Tyme.'],
'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'],
'Front page': ['1', 'Jump to front page.'],
@@ -385,7 +388,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.9.12.5',
+ VERSION: '1.9.13.0',
NAMESPACE: '4chan X.',
NAME: '4chan X',
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
@@ -708,6 +711,15 @@
}
};
+ $.one = function(el, events, handler) {
+ var cb;
+ cb = function(e) {
+ $.off(el, events, cb);
+ return handler.call(this, e);
+ };
+ return $.on(el, events, cb);
+ };
+
$.event = function(event, detail, root) {
if (root == null) {
root = d;
@@ -6026,9 +6038,7 @@
el: this.controls,
order: 98
});
- if (!Conf['Unread Count']) {
- $.on(d, '4chanXInitFinished', this.ready);
- }
+ $.on(d, '4chanXInitFinished', this.ready);
return Post.callbacks.push({
name: 'Quote Threading',
cb: this.node
@@ -6044,10 +6054,8 @@
return post.cb(true);
}
});
- if (Conf['Unread Count'] && Unread.thread.OP.nodes.root.parentElement.parentElement) {
- Unread.read();
- return Unread.update();
- }
+ Unread.read();
+ return Unread.update();
},
node: function() {
var keys, len, posts, quote, _i, _len, _ref;
@@ -6055,9 +6063,7 @@
if (this.isClone || !QuoteThreading.enabled) {
return;
}
- if (Conf['Unread Count']) {
- Unread.addPost(this);
- }
+ Unread.addPost(this);
if (this.thread.OP === this || this.isHidden) {
return;
}
@@ -6087,7 +6093,7 @@
if (!force) {
height = doc.clientHeight;
_ref = root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
- if (!((Conf['Unread Count'] && posts[post.ID]) || ((bottom < height) && (top > 0)))) {
+ if (!(posts[post.ID] || ((bottom < height) && (top > 0)))) {
return false;
}
}
@@ -6103,9 +6109,6 @@
$.after(root, threadContainer);
$.addClass(root, 'threadOP');
}
- if (!Conf['Unread Count']) {
- return true;
- }
if (post = posts[post.ID]) {
posts.after(post, posts[this.ID]);
} else if (posts[this.ID]) {
@@ -8298,6 +8301,17 @@
}
}
}
+ if (Conf['Fullscreen Gallery']) {
+ $.one(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', function() {
+ return $.on(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', cb.close);
+ });
+ if (typeof doc.mozRequestFullScreen === "function") {
+ doc.mozRequestFullScreen();
+ }
+ if (typeof doc.webkitRequestFullScreen === "function") {
+ doc.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
+ }
+ }
$.addClass(doc, 'gallery-open');
$.add(d.body, dialog);
nodes.thumbs.scrollTop = 0;
@@ -8457,7 +8471,7 @@
}
cb = (function() {
switch (key) {
- case 'Esc':
+ case Conf['Close']:
case Conf['Open Gallery']:
return Gallery.cb.close;
case 'Right':
@@ -8467,9 +8481,9 @@
case 'Left':
case '':
return Gallery.cb.prev;
- case 'p':
+ case Conf['Pause']:
return Gallery.cb.pause;
- case 's':
+ case Conf['Slideshow']:
return Gallery.cb.toggleSlideshow;
}
})();
@@ -8553,6 +8567,15 @@
}
$.rm(Gallery.nodes.el);
$.rmClass(doc, 'gallery-open');
+ if (Conf['Fullscreen Gallery']) {
+ $.off(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', Gallery.cb.close);
+ if (typeof d.mozCancelFullScreen === "function") {
+ d.mozCancelFullScreen();
+ }
+ if (typeof d.webkitExitFullscreen === "function") {
+ d.webkitExitFullscreen();
+ }
+ }
delete Gallery.nodes;
delete Gallery.fullIDs;
doc.style.overflow = '';
@@ -11786,7 +11809,7 @@
Unread = {
init: function() {
- if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Unread Line'] && !Conf['Desktop Notifications'] && !(Conf['Thread Watcher'] && Conf['Show Unread Count'])) {
+ if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Unread Line'] && !Conf['Scroll to Last Read Post'] && !Conf['Thread Watcher'] && !Conf['Desktop Notifications'] && !Conf['Quote Threading']) {
return;
}
this.db = new DataBoard('lastReadPosts', this.sync);
@@ -11809,7 +11832,7 @@
threadID: this.ID,
defaultValue: 0
});
- $.on(d, '4chanXInitFinished', Unread.ready);
+ $.one(d, '4chanXInitFinished', Unread.ready);
$.on(d, 'ThreadUpdate', Unread.onUpdate);
$.on(d, 'scroll visibilitychange', Unread.read);
if (Conf['Unread Line'] && !Conf['Quote Threading']) {
@@ -11818,7 +11841,6 @@
},
ready: function() {
var posts;
- $.off(d, '4chanXInitFinished', Unread.ready);
if (!Conf['Quote Threading']) {
posts = [];
Unread.thread.posts.forEach(function(post) {
@@ -11836,31 +11858,26 @@
}
},
scroll: function() {
- var down, hash, keys, post, posts, root;
+ var ID, hash, posts, root, _i, _ref;
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
return;
}
- if (post = Unread.posts.first) {
- while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.data.nodes.root)) {
- if (!(post = Get.postFromRoot(root)).isHidden) {
- break;
- }
+ posts = Unread.thread.posts;
+ _ref = posts.keys;
+ for (_i = _ref.length - 1; _i >= 0; _i += -1) {
+ ID = _ref[_i];
+ if (!(+ID <= Unread.lastReadPost)) {
+ continue;
}
- if (!root) {
- return;
+ root = posts[ID].nodes.root;
+ if (root.getBoundingClientRect().height) {
+ Header.scrollToIfNeeded(root, true);
+ break;
}
- down = true;
- } else {
- posts = Unread.thread.posts;
- keys = posts.keys;
- root = posts[keys[keys.length - 1]].nodes.root;
- }
- if (Header.getBottomOf(root) < 0) {
- return Header.scrollTo(root, down);
}
},
sync: function() {
- var ID, lastReadPost, post;
+ var ID, lastReadPost, _i, _len, _ref;
if (Unread.lastReadPost == null) {
return;
}
@@ -11873,13 +11890,12 @@
return;
}
Unread.lastReadPost = lastReadPost;
- post = Unread.posts.first;
- while (post) {
- if (post.ID > Unread.lastReadPost) {
+ _ref = Unread.thread.posts.keys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ ID = _ref[_i];
+ if (+ID > Unread.lastReadPost) {
break;
}
- ID = post.ID;
- post = post.next;
Unread.posts.rm(ID);
delete Unread.postsQuotingYou[ID];
}
@@ -11901,13 +11917,14 @@
return Unread.addPostQuotingYou(post);
},
addPosts: function(posts) {
- var post, _i, _len, _ref, _ref1;
+ var oldCount, post, _i, _len;
+ oldCount = Unread.posts.length;
for (_i = 0, _len = posts.length; _i < _len; _i++) {
post = posts[_i];
Unread.addPost(post);
}
if (Conf['Unread Line'] && !Conf['Quote Threading']) {
- Unread.setLine((_ref = (_ref1 = Unread.posts.first) != null ? _ref1.data : void 0, __indexOf.call(posts, _ref) >= 0));
+ Unread.setLine(oldCount === 0 && Unread.posts.length !== 0);
}
Unread.read();
return Unread.update();
@@ -11971,28 +11988,25 @@
if (!posts[ID]) {
return;
}
- if (post === posts.first && !(Conf['Quote Threading'] && Unread.posts.length)) {
- Unread.lastReadPost = ID;
- Unread.saveLastReadPost();
- }
posts.rm(ID);
delete Unread.postsQuotingYou[ID];
+ Unread.saveLastReadPost();
return Unread.update();
},
read: $.debounce(100, function(e) {
- var ID, data, height, maxID, post, posts, _ref;
+ var ID, count, data, height, post, posts, _ref;
if (d.hidden || !Unread.posts.length) {
return;
}
height = doc.clientHeight;
posts = Unread.posts;
- maxID = 0;
+ count = 0;
while (post = posts.first) {
if (!(Header.getBottomOf(post.data.nodes.root) > -1)) {
break;
}
ID = post.ID, data = post.data;
- maxID = Math.max(maxID, ID);
+ count++;
posts.rm(ID);
delete Unread.postsQuotingYou[ID];
if (Conf['Mark Quotes of You'] && ((_ref = QR.db) != null ? _ref.get({
@@ -12003,23 +12017,30 @@
QuoteYou.lastRead = data.nodes.root;
}
}
- if (!maxID) {
+ if (!count) {
return;
}
- if (!(Conf['Quote Threading'] && posts.length)) {
- if (Unread.lastReadPost < maxID || !Unread.lastReadPost) {
- Unread.lastReadPost = maxID;
- }
- Unread.saveLastReadPost();
- }
+ Unread.saveLastReadPost();
if (e) {
return Unread.update();
}
}),
saveLastReadPost: $.debounce(2 * $.SECOND, function() {
+ var ID, _i, _len, _ref;
+ _ref = Unread.thread.posts.keys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ ID = _ref[_i];
+ if (Unread.posts[ID]) {
+ break;
+ }
+ if (+ID > Unread.lastReadPost) {
+ Unread.lastReadPost = +ID;
+ }
+ }
if (Unread.thread.isDead && !Unread.thread.isArchived) {
return;
}
+ Unread.db.forceSync();
return Unread.db.set({
boardID: Unread.thread.board.ID,
threadID: Unread.thread.ID,
@@ -12027,15 +12048,20 @@
});
}),
setLine: function(force) {
- var post;
+ var ID, posts, _i, _ref;
if (!(d.hidden || force === true)) {
return;
}
- if (!(post = Unread.posts.first)) {
+ if (!Unread.posts.length) {
return $.rm(Unread.hr);
}
- if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.data.nodes.root)) {
- return $.before(post.data.nodes.root, Unread.hr);
+ posts = Unread.thread.posts;
+ _ref = posts.keys;
+ for (_i = _ref.length - 1; _i >= 0; _i += -1) {
+ ID = _ref[_i];
+ if (+ID <= Unread.lastReadPost) {
+ return $.after(posts[ID].nodes.root, Unread.hr);
+ }
}
},
update: function() {
@@ -13169,7 +13195,7 @@
Gallery.cb.toggle();
break;
case Conf['fappeTyme']:
- if (g.VIEW === 'catalog') {
+ if (!Conf['Fappe Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') {
return;
}
FappeTyme.cb.toggle.call({
@@ -13177,7 +13203,7 @@
});
break;
case Conf['werkTyme']:
- if (g.VIEW === 'catalog') {
+ if (!Conf['Werk Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') {
return;
}
FappeTyme.cb.toggle.call({
@@ -13833,7 +13859,7 @@
className: 'dialog'
});
$.extend(dialog, {
- innerHTML: "
"
+ innerHTML: ""
});
$.on($('.export', Settings.dialog), 'click', Settings["export"]);
$.on($('.import', Settings.dialog), 'click', Settings["import"]);
diff --git a/builds/4chan-X-noupdate.crx b/builds/4chan-X-noupdate.crx
index f5ded89a2..042f41322 100644
Binary files a/builds/4chan-X-noupdate.crx and b/builds/4chan-X-noupdate.crx differ
diff --git a/builds/4chan-X-noupdate.user.js b/builds/4chan-X-noupdate.user.js
index 4ee394bae..55e4a1e6d 100644
--- a/builds/4chan-X-noupdate.user.js
+++ b/builds/4chan-X-noupdate.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
-// @version 1.9.12.5
+// @version 1.9.13.0
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -23,7 +23,7 @@
// ==/UserScript==
/*
-* 4chan X - Version 1.9.12.5
+* 4chan X - Version 1.9.13.0
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
@@ -177,6 +177,7 @@
'Image Hover': [true, 'Show full image / video on mouseover.'],
'Image Hover in Catalog': [false, 'Show full image / video on mouseover in 4chan X catalog.'],
'Gallery': [true, 'Adds a simple and cute image gallery.'],
+ 'Fullscreen Gallery': [false, 'Open gallery in fullscreen mode.'],
'PDF in Gallery': [false, 'Show PDF files in gallery.'],
'Sauce': [true, 'Add sauce links to images.'],
'Reveal Spoiler Thumbnails': [false, 'Replace spoiler thumbnails with the original image.'],
@@ -266,7 +267,7 @@
'Fit Width': [true],
'Fit Height': [true],
'Scroll to Post': [true],
- 'Slide Delay': [5.0]
+ 'Slide Delay': [6.0]
},
threadWatcher: {
'Current Board': [false, 'Only show watched threads from the current board.'],
@@ -329,7 +330,7 @@
'Open empty QR': ['q', 'Open QR without post number inserted.'],
'Open QR': ['Shift+q', 'Open QR with post number inserted.'],
'Open settings': ['Alt+o', 'Open Settings.'],
- 'Close': ['Esc', 'Close Settings, Notifications or QR.'],
+ 'Close': ['Esc', 'Close Settings/Notifications/QR/Gallery.'],
'Spoiler tags': ['Ctrl+s', 'Insert spoiler tags.'],
'Code tags': ['Alt+c', 'Insert code tags.'],
'Eqn tags': ['Alt+e', 'Insert eqn tags.'],
@@ -341,6 +342,8 @@
'Expand image': ['Shift+e', 'Expand selected image.'],
'Expand images': ['e', 'Expand all images.'],
'Open Gallery': ['g', 'Opens the gallery.'],
+ 'Pause': ['p', 'Pause/play videos in the gallery.'],
+ 'Slideshow': ['s', 'Toggle the gallery slideshow mode.'],
'fappeTyme': ['f', 'Toggle Fappe Tyme.'],
'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'],
'Front page': ['1', 'Jump to front page.'],
@@ -384,7 +387,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.9.12.5',
+ VERSION: '1.9.13.0',
NAMESPACE: '4chan X.',
NAME: '4chan X',
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
@@ -707,6 +710,15 @@
}
};
+ $.one = function(el, events, handler) {
+ var cb;
+ cb = function(e) {
+ $.off(el, events, cb);
+ return handler.call(this, e);
+ };
+ return $.on(el, events, cb);
+ };
+
$.event = function(event, detail, root) {
if (root == null) {
root = d;
@@ -6025,9 +6037,7 @@
el: this.controls,
order: 98
});
- if (!Conf['Unread Count']) {
- $.on(d, '4chanXInitFinished', this.ready);
- }
+ $.on(d, '4chanXInitFinished', this.ready);
return Post.callbacks.push({
name: 'Quote Threading',
cb: this.node
@@ -6043,10 +6053,8 @@
return post.cb(true);
}
});
- if (Conf['Unread Count'] && Unread.thread.OP.nodes.root.parentElement.parentElement) {
- Unread.read();
- return Unread.update();
- }
+ Unread.read();
+ return Unread.update();
},
node: function() {
var keys, len, posts, quote, _i, _len, _ref;
@@ -6054,9 +6062,7 @@
if (this.isClone || !QuoteThreading.enabled) {
return;
}
- if (Conf['Unread Count']) {
- Unread.addPost(this);
- }
+ Unread.addPost(this);
if (this.thread.OP === this || this.isHidden) {
return;
}
@@ -6086,7 +6092,7 @@
if (!force) {
height = doc.clientHeight;
_ref = root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
- if (!((Conf['Unread Count'] && posts[post.ID]) || ((bottom < height) && (top > 0)))) {
+ if (!(posts[post.ID] || ((bottom < height) && (top > 0)))) {
return false;
}
}
@@ -6102,9 +6108,6 @@
$.after(root, threadContainer);
$.addClass(root, 'threadOP');
}
- if (!Conf['Unread Count']) {
- return true;
- }
if (post = posts[post.ID]) {
posts.after(post, posts[this.ID]);
} else if (posts[this.ID]) {
@@ -8297,6 +8300,17 @@
}
}
}
+ if (Conf['Fullscreen Gallery']) {
+ $.one(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', function() {
+ return $.on(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', cb.close);
+ });
+ if (typeof doc.mozRequestFullScreen === "function") {
+ doc.mozRequestFullScreen();
+ }
+ if (typeof doc.webkitRequestFullScreen === "function") {
+ doc.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
+ }
+ }
$.addClass(doc, 'gallery-open');
$.add(d.body, dialog);
nodes.thumbs.scrollTop = 0;
@@ -8456,7 +8470,7 @@
}
cb = (function() {
switch (key) {
- case 'Esc':
+ case Conf['Close']:
case Conf['Open Gallery']:
return Gallery.cb.close;
case 'Right':
@@ -8466,9 +8480,9 @@
case 'Left':
case '':
return Gallery.cb.prev;
- case 'p':
+ case Conf['Pause']:
return Gallery.cb.pause;
- case 's':
+ case Conf['Slideshow']:
return Gallery.cb.toggleSlideshow;
}
})();
@@ -8552,6 +8566,15 @@
}
$.rm(Gallery.nodes.el);
$.rmClass(doc, 'gallery-open');
+ if (Conf['Fullscreen Gallery']) {
+ $.off(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', Gallery.cb.close);
+ if (typeof d.mozCancelFullScreen === "function") {
+ d.mozCancelFullScreen();
+ }
+ if (typeof d.webkitExitFullscreen === "function") {
+ d.webkitExitFullscreen();
+ }
+ }
delete Gallery.nodes;
delete Gallery.fullIDs;
doc.style.overflow = '';
@@ -11785,7 +11808,7 @@
Unread = {
init: function() {
- if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Unread Line'] && !Conf['Desktop Notifications'] && !(Conf['Thread Watcher'] && Conf['Show Unread Count'])) {
+ if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Unread Line'] && !Conf['Scroll to Last Read Post'] && !Conf['Thread Watcher'] && !Conf['Desktop Notifications'] && !Conf['Quote Threading']) {
return;
}
this.db = new DataBoard('lastReadPosts', this.sync);
@@ -11808,7 +11831,7 @@
threadID: this.ID,
defaultValue: 0
});
- $.on(d, '4chanXInitFinished', Unread.ready);
+ $.one(d, '4chanXInitFinished', Unread.ready);
$.on(d, 'ThreadUpdate', Unread.onUpdate);
$.on(d, 'scroll visibilitychange', Unread.read);
if (Conf['Unread Line'] && !Conf['Quote Threading']) {
@@ -11817,7 +11840,6 @@
},
ready: function() {
var posts;
- $.off(d, '4chanXInitFinished', Unread.ready);
if (!Conf['Quote Threading']) {
posts = [];
Unread.thread.posts.forEach(function(post) {
@@ -11835,31 +11857,26 @@
}
},
scroll: function() {
- var down, hash, keys, post, posts, root;
+ var ID, hash, posts, root, _i, _ref;
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
return;
}
- if (post = Unread.posts.first) {
- while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.data.nodes.root)) {
- if (!(post = Get.postFromRoot(root)).isHidden) {
- break;
- }
+ posts = Unread.thread.posts;
+ _ref = posts.keys;
+ for (_i = _ref.length - 1; _i >= 0; _i += -1) {
+ ID = _ref[_i];
+ if (!(+ID <= Unread.lastReadPost)) {
+ continue;
}
- if (!root) {
- return;
+ root = posts[ID].nodes.root;
+ if (root.getBoundingClientRect().height) {
+ Header.scrollToIfNeeded(root, true);
+ break;
}
- down = true;
- } else {
- posts = Unread.thread.posts;
- keys = posts.keys;
- root = posts[keys[keys.length - 1]].nodes.root;
- }
- if (Header.getBottomOf(root) < 0) {
- return Header.scrollTo(root, down);
}
},
sync: function() {
- var ID, lastReadPost, post;
+ var ID, lastReadPost, _i, _len, _ref;
if (Unread.lastReadPost == null) {
return;
}
@@ -11872,13 +11889,12 @@
return;
}
Unread.lastReadPost = lastReadPost;
- post = Unread.posts.first;
- while (post) {
- if (post.ID > Unread.lastReadPost) {
+ _ref = Unread.thread.posts.keys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ ID = _ref[_i];
+ if (+ID > Unread.lastReadPost) {
break;
}
- ID = post.ID;
- post = post.next;
Unread.posts.rm(ID);
delete Unread.postsQuotingYou[ID];
}
@@ -11900,13 +11916,14 @@
return Unread.addPostQuotingYou(post);
},
addPosts: function(posts) {
- var post, _i, _len, _ref, _ref1;
+ var oldCount, post, _i, _len;
+ oldCount = Unread.posts.length;
for (_i = 0, _len = posts.length; _i < _len; _i++) {
post = posts[_i];
Unread.addPost(post);
}
if (Conf['Unread Line'] && !Conf['Quote Threading']) {
- Unread.setLine((_ref = (_ref1 = Unread.posts.first) != null ? _ref1.data : void 0, __indexOf.call(posts, _ref) >= 0));
+ Unread.setLine(oldCount === 0 && Unread.posts.length !== 0);
}
Unread.read();
return Unread.update();
@@ -11970,28 +11987,25 @@
if (!posts[ID]) {
return;
}
- if (post === posts.first && !(Conf['Quote Threading'] && Unread.posts.length)) {
- Unread.lastReadPost = ID;
- Unread.saveLastReadPost();
- }
posts.rm(ID);
delete Unread.postsQuotingYou[ID];
+ Unread.saveLastReadPost();
return Unread.update();
},
read: $.debounce(100, function(e) {
- var ID, data, height, maxID, post, posts, _ref;
+ var ID, count, data, height, post, posts, _ref;
if (d.hidden || !Unread.posts.length) {
return;
}
height = doc.clientHeight;
posts = Unread.posts;
- maxID = 0;
+ count = 0;
while (post = posts.first) {
if (!(Header.getBottomOf(post.data.nodes.root) > -1)) {
break;
}
ID = post.ID, data = post.data;
- maxID = Math.max(maxID, ID);
+ count++;
posts.rm(ID);
delete Unread.postsQuotingYou[ID];
if (Conf['Mark Quotes of You'] && ((_ref = QR.db) != null ? _ref.get({
@@ -12002,23 +12016,30 @@
QuoteYou.lastRead = data.nodes.root;
}
}
- if (!maxID) {
+ if (!count) {
return;
}
- if (!(Conf['Quote Threading'] && posts.length)) {
- if (Unread.lastReadPost < maxID || !Unread.lastReadPost) {
- Unread.lastReadPost = maxID;
- }
- Unread.saveLastReadPost();
- }
+ Unread.saveLastReadPost();
if (e) {
return Unread.update();
}
}),
saveLastReadPost: $.debounce(2 * $.SECOND, function() {
+ var ID, _i, _len, _ref;
+ _ref = Unread.thread.posts.keys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ ID = _ref[_i];
+ if (Unread.posts[ID]) {
+ break;
+ }
+ if (+ID > Unread.lastReadPost) {
+ Unread.lastReadPost = +ID;
+ }
+ }
if (Unread.thread.isDead && !Unread.thread.isArchived) {
return;
}
+ Unread.db.forceSync();
return Unread.db.set({
boardID: Unread.thread.board.ID,
threadID: Unread.thread.ID,
@@ -12026,15 +12047,20 @@
});
}),
setLine: function(force) {
- var post;
+ var ID, posts, _i, _ref;
if (!(d.hidden || force === true)) {
return;
}
- if (!(post = Unread.posts.first)) {
+ if (!Unread.posts.length) {
return $.rm(Unread.hr);
}
- if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.data.nodes.root)) {
- return $.before(post.data.nodes.root, Unread.hr);
+ posts = Unread.thread.posts;
+ _ref = posts.keys;
+ for (_i = _ref.length - 1; _i >= 0; _i += -1) {
+ ID = _ref[_i];
+ if (+ID <= Unread.lastReadPost) {
+ return $.after(posts[ID].nodes.root, Unread.hr);
+ }
}
},
update: function() {
@@ -13168,7 +13194,7 @@
Gallery.cb.toggle();
break;
case Conf['fappeTyme']:
- if (g.VIEW === 'catalog') {
+ if (!Conf['Fappe Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') {
return;
}
FappeTyme.cb.toggle.call({
@@ -13176,7 +13202,7 @@
});
break;
case Conf['werkTyme']:
- if (g.VIEW === 'catalog') {
+ if (!Conf['Werk Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') {
return;
}
FappeTyme.cb.toggle.call({
@@ -13832,7 +13858,7 @@
className: 'dialog'
});
$.extend(dialog, {
- innerHTML: ""
+ innerHTML: ""
});
$.on($('.export', Settings.dialog), 'click', Settings["export"]);
$.on($('.import', Settings.dialog), 'click', Settings["import"]);
diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx
index 8a720b4e4..b31fdd46f 100644
Binary files a/builds/4chan-X.crx and b/builds/4chan-X.crx differ
diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js
index f913454fb..5396e7fec 100644
--- a/builds/4chan-X.meta.js
+++ b/builds/4chan-X.meta.js
@@ -1,6 +1,6 @@
// ==UserScript==
// @name 4chan X
-// @version 1.9.12.5
+// @version 1.9.13.0
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js
index 6e3c18f94..a237ce893 100644
--- a/builds/4chan-X.user.js
+++ b/builds/4chan-X.user.js
@@ -1,7 +1,7 @@
// Generated by CoffeeScript
// ==UserScript==
// @name 4chan X
-// @version 1.9.12.5
+// @version 1.9.13.0
// @minGMVer 1.14
// @minFFVer 26
// @namespace 4chan-X
@@ -24,7 +24,7 @@
// ==/UserScript==
/*
-* 4chan X - Version 1.9.12.5
+* 4chan X - Version 1.9.13.0
*
* Licensed under the MIT license.
* https://github.com/ccd0/4chan-x/blob/master/LICENSE
@@ -178,6 +178,7 @@
'Image Hover': [true, 'Show full image / video on mouseover.'],
'Image Hover in Catalog': [false, 'Show full image / video on mouseover in 4chan X catalog.'],
'Gallery': [true, 'Adds a simple and cute image gallery.'],
+ 'Fullscreen Gallery': [false, 'Open gallery in fullscreen mode.'],
'PDF in Gallery': [false, 'Show PDF files in gallery.'],
'Sauce': [true, 'Add sauce links to images.'],
'Reveal Spoiler Thumbnails': [false, 'Replace spoiler thumbnails with the original image.'],
@@ -267,7 +268,7 @@
'Fit Width': [true],
'Fit Height': [true],
'Scroll to Post': [true],
- 'Slide Delay': [5.0]
+ 'Slide Delay': [6.0]
},
threadWatcher: {
'Current Board': [false, 'Only show watched threads from the current board.'],
@@ -330,7 +331,7 @@
'Open empty QR': ['q', 'Open QR without post number inserted.'],
'Open QR': ['Shift+q', 'Open QR with post number inserted.'],
'Open settings': ['Alt+o', 'Open Settings.'],
- 'Close': ['Esc', 'Close Settings, Notifications or QR.'],
+ 'Close': ['Esc', 'Close Settings/Notifications/QR/Gallery.'],
'Spoiler tags': ['Ctrl+s', 'Insert spoiler tags.'],
'Code tags': ['Alt+c', 'Insert code tags.'],
'Eqn tags': ['Alt+e', 'Insert eqn tags.'],
@@ -342,6 +343,8 @@
'Expand image': ['Shift+e', 'Expand selected image.'],
'Expand images': ['e', 'Expand all images.'],
'Open Gallery': ['g', 'Opens the gallery.'],
+ 'Pause': ['p', 'Pause/play videos in the gallery.'],
+ 'Slideshow': ['s', 'Toggle the gallery slideshow mode.'],
'fappeTyme': ['f', 'Toggle Fappe Tyme.'],
'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'],
'Front page': ['1', 'Jump to front page.'],
@@ -385,7 +388,7 @@
doc = d.documentElement;
g = {
- VERSION: '1.9.12.5',
+ VERSION: '1.9.13.0',
NAMESPACE: '4chan X.',
NAME: '4chan X',
FAQ: 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions',
@@ -708,6 +711,15 @@
}
};
+ $.one = function(el, events, handler) {
+ var cb;
+ cb = function(e) {
+ $.off(el, events, cb);
+ return handler.call(this, e);
+ };
+ return $.on(el, events, cb);
+ };
+
$.event = function(event, detail, root) {
if (root == null) {
root = d;
@@ -6026,9 +6038,7 @@
el: this.controls,
order: 98
});
- if (!Conf['Unread Count']) {
- $.on(d, '4chanXInitFinished', this.ready);
- }
+ $.on(d, '4chanXInitFinished', this.ready);
return Post.callbacks.push({
name: 'Quote Threading',
cb: this.node
@@ -6044,10 +6054,8 @@
return post.cb(true);
}
});
- if (Conf['Unread Count'] && Unread.thread.OP.nodes.root.parentElement.parentElement) {
- Unread.read();
- return Unread.update();
- }
+ Unread.read();
+ return Unread.update();
},
node: function() {
var keys, len, posts, quote, _i, _len, _ref;
@@ -6055,9 +6063,7 @@
if (this.isClone || !QuoteThreading.enabled) {
return;
}
- if (Conf['Unread Count']) {
- Unread.addPost(this);
- }
+ Unread.addPost(this);
if (this.thread.OP === this || this.isHidden) {
return;
}
@@ -6087,7 +6093,7 @@
if (!force) {
height = doc.clientHeight;
_ref = root.getBoundingClientRect(), bottom = _ref.bottom, top = _ref.top;
- if (!((Conf['Unread Count'] && posts[post.ID]) || ((bottom < height) && (top > 0)))) {
+ if (!(posts[post.ID] || ((bottom < height) && (top > 0)))) {
return false;
}
}
@@ -6103,9 +6109,6 @@
$.after(root, threadContainer);
$.addClass(root, 'threadOP');
}
- if (!Conf['Unread Count']) {
- return true;
- }
if (post = posts[post.ID]) {
posts.after(post, posts[this.ID]);
} else if (posts[this.ID]) {
@@ -8298,6 +8301,17 @@
}
}
}
+ if (Conf['Fullscreen Gallery']) {
+ $.one(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', function() {
+ return $.on(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', cb.close);
+ });
+ if (typeof doc.mozRequestFullScreen === "function") {
+ doc.mozRequestFullScreen();
+ }
+ if (typeof doc.webkitRequestFullScreen === "function") {
+ doc.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
+ }
+ }
$.addClass(doc, 'gallery-open');
$.add(d.body, dialog);
nodes.thumbs.scrollTop = 0;
@@ -8457,7 +8471,7 @@
}
cb = (function() {
switch (key) {
- case 'Esc':
+ case Conf['Close']:
case Conf['Open Gallery']:
return Gallery.cb.close;
case 'Right':
@@ -8467,9 +8481,9 @@
case 'Left':
case '':
return Gallery.cb.prev;
- case 'p':
+ case Conf['Pause']:
return Gallery.cb.pause;
- case 's':
+ case Conf['Slideshow']:
return Gallery.cb.toggleSlideshow;
}
})();
@@ -8553,6 +8567,15 @@
}
$.rm(Gallery.nodes.el);
$.rmClass(doc, 'gallery-open');
+ if (Conf['Fullscreen Gallery']) {
+ $.off(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', Gallery.cb.close);
+ if (typeof d.mozCancelFullScreen === "function") {
+ d.mozCancelFullScreen();
+ }
+ if (typeof d.webkitExitFullscreen === "function") {
+ d.webkitExitFullscreen();
+ }
+ }
delete Gallery.nodes;
delete Gallery.fullIDs;
doc.style.overflow = '';
@@ -11786,7 +11809,7 @@
Unread = {
init: function() {
- if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Unread Line'] && !Conf['Desktop Notifications'] && !(Conf['Thread Watcher'] && Conf['Show Unread Count'])) {
+ if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Unread Line'] && !Conf['Scroll to Last Read Post'] && !Conf['Thread Watcher'] && !Conf['Desktop Notifications'] && !Conf['Quote Threading']) {
return;
}
this.db = new DataBoard('lastReadPosts', this.sync);
@@ -11809,7 +11832,7 @@
threadID: this.ID,
defaultValue: 0
});
- $.on(d, '4chanXInitFinished', Unread.ready);
+ $.one(d, '4chanXInitFinished', Unread.ready);
$.on(d, 'ThreadUpdate', Unread.onUpdate);
$.on(d, 'scroll visibilitychange', Unread.read);
if (Conf['Unread Line'] && !Conf['Quote Threading']) {
@@ -11818,7 +11841,6 @@
},
ready: function() {
var posts;
- $.off(d, '4chanXInitFinished', Unread.ready);
if (!Conf['Quote Threading']) {
posts = [];
Unread.thread.posts.forEach(function(post) {
@@ -11836,31 +11858,26 @@
}
},
scroll: function() {
- var down, hash, keys, post, posts, root;
+ var ID, hash, posts, root, _i, _ref;
if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) {
return;
}
- if (post = Unread.posts.first) {
- while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.data.nodes.root)) {
- if (!(post = Get.postFromRoot(root)).isHidden) {
- break;
- }
+ posts = Unread.thread.posts;
+ _ref = posts.keys;
+ for (_i = _ref.length - 1; _i >= 0; _i += -1) {
+ ID = _ref[_i];
+ if (!(+ID <= Unread.lastReadPost)) {
+ continue;
}
- if (!root) {
- return;
+ root = posts[ID].nodes.root;
+ if (root.getBoundingClientRect().height) {
+ Header.scrollToIfNeeded(root, true);
+ break;
}
- down = true;
- } else {
- posts = Unread.thread.posts;
- keys = posts.keys;
- root = posts[keys[keys.length - 1]].nodes.root;
- }
- if (Header.getBottomOf(root) < 0) {
- return Header.scrollTo(root, down);
}
},
sync: function() {
- var ID, lastReadPost, post;
+ var ID, lastReadPost, _i, _len, _ref;
if (Unread.lastReadPost == null) {
return;
}
@@ -11873,13 +11890,12 @@
return;
}
Unread.lastReadPost = lastReadPost;
- post = Unread.posts.first;
- while (post) {
- if (post.ID > Unread.lastReadPost) {
+ _ref = Unread.thread.posts.keys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ ID = _ref[_i];
+ if (+ID > Unread.lastReadPost) {
break;
}
- ID = post.ID;
- post = post.next;
Unread.posts.rm(ID);
delete Unread.postsQuotingYou[ID];
}
@@ -11901,13 +11917,14 @@
return Unread.addPostQuotingYou(post);
},
addPosts: function(posts) {
- var post, _i, _len, _ref, _ref1;
+ var oldCount, post, _i, _len;
+ oldCount = Unread.posts.length;
for (_i = 0, _len = posts.length; _i < _len; _i++) {
post = posts[_i];
Unread.addPost(post);
}
if (Conf['Unread Line'] && !Conf['Quote Threading']) {
- Unread.setLine((_ref = (_ref1 = Unread.posts.first) != null ? _ref1.data : void 0, __indexOf.call(posts, _ref) >= 0));
+ Unread.setLine(oldCount === 0 && Unread.posts.length !== 0);
}
Unread.read();
return Unread.update();
@@ -11971,28 +11988,25 @@
if (!posts[ID]) {
return;
}
- if (post === posts.first && !(Conf['Quote Threading'] && Unread.posts.length)) {
- Unread.lastReadPost = ID;
- Unread.saveLastReadPost();
- }
posts.rm(ID);
delete Unread.postsQuotingYou[ID];
+ Unread.saveLastReadPost();
return Unread.update();
},
read: $.debounce(100, function(e) {
- var ID, data, height, maxID, post, posts, _ref;
+ var ID, count, data, height, post, posts, _ref;
if (d.hidden || !Unread.posts.length) {
return;
}
height = doc.clientHeight;
posts = Unread.posts;
- maxID = 0;
+ count = 0;
while (post = posts.first) {
if (!(Header.getBottomOf(post.data.nodes.root) > -1)) {
break;
}
ID = post.ID, data = post.data;
- maxID = Math.max(maxID, ID);
+ count++;
posts.rm(ID);
delete Unread.postsQuotingYou[ID];
if (Conf['Mark Quotes of You'] && ((_ref = QR.db) != null ? _ref.get({
@@ -12003,23 +12017,30 @@
QuoteYou.lastRead = data.nodes.root;
}
}
- if (!maxID) {
+ if (!count) {
return;
}
- if (!(Conf['Quote Threading'] && posts.length)) {
- if (Unread.lastReadPost < maxID || !Unread.lastReadPost) {
- Unread.lastReadPost = maxID;
- }
- Unread.saveLastReadPost();
- }
+ Unread.saveLastReadPost();
if (e) {
return Unread.update();
}
}),
saveLastReadPost: $.debounce(2 * $.SECOND, function() {
+ var ID, _i, _len, _ref;
+ _ref = Unread.thread.posts.keys;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ ID = _ref[_i];
+ if (Unread.posts[ID]) {
+ break;
+ }
+ if (+ID > Unread.lastReadPost) {
+ Unread.lastReadPost = +ID;
+ }
+ }
if (Unread.thread.isDead && !Unread.thread.isArchived) {
return;
}
+ Unread.db.forceSync();
return Unread.db.set({
boardID: Unread.thread.board.ID,
threadID: Unread.thread.ID,
@@ -12027,15 +12048,20 @@
});
}),
setLine: function(force) {
- var post;
+ var ID, posts, _i, _ref;
if (!(d.hidden || force === true)) {
return;
}
- if (!(post = Unread.posts.first)) {
+ if (!Unread.posts.length) {
return $.rm(Unread.hr);
}
- if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.data.nodes.root)) {
- return $.before(post.data.nodes.root, Unread.hr);
+ posts = Unread.thread.posts;
+ _ref = posts.keys;
+ for (_i = _ref.length - 1; _i >= 0; _i += -1) {
+ ID = _ref[_i];
+ if (+ID <= Unread.lastReadPost) {
+ return $.after(posts[ID].nodes.root, Unread.hr);
+ }
}
},
update: function() {
@@ -13169,7 +13195,7 @@
Gallery.cb.toggle();
break;
case Conf['fappeTyme']:
- if (g.VIEW === 'catalog') {
+ if (!Conf['Fappe Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') {
return;
}
FappeTyme.cb.toggle.call({
@@ -13177,7 +13203,7 @@
});
break;
case Conf['werkTyme']:
- if (g.VIEW === 'catalog') {
+ if (!Conf['Werk Tyme'] || g.VIEW === 'catalog' || g.BOARD === 'f') {
return;
}
FappeTyme.cb.toggle.call({
@@ -13833,7 +13859,7 @@
className: 'dialog'
});
$.extend(dialog, {
- innerHTML: ""
+ innerHTML: ""
});
$.on($('.export', Settings.dialog), 'click', Settings["export"]);
$.on($('.import', Settings.dialog), 'click', Settings["import"]);
diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip
index e71b2eda5..7802e3d10 100644
Binary files a/builds/4chan-X.zip and b/builds/4chan-X.zip differ
diff --git a/builds/updates-beta.xml b/builds/updates-beta.xml
index 09ba804b0..fe28fba2b 100644
--- a/builds/updates-beta.xml
+++ b/builds/updates-beta.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/builds/updates.xml b/builds/updates.xml
index 6a8e5abcd..0f4a55c49 100644
--- a/builds/updates.xml
+++ b/builds/updates.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/package.json b/package.json
index 3fb63852c..dc3b6bf7d 100755
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"description": "Cross-browser userscript for maximum lurking on 4chan.",
"meta": {
"name": "4chan X",
- "version": "1.9.12.5",
+ "version": "1.9.13.0",
"repo": "https://github.com/ccd0/4chan-x/",
"page": "https://github.com/ccd0/4chan-x",
"downloads": "https://ccd0.github.io/4chan-x/builds/",
@@ -67,4 +67,4 @@
"engines": {
"node": ">=0.10"
}
-}
+}
\ No newline at end of file