Unread.coffee
This commit is contained in:
parent
ac5a6c53b0
commit
5f771c9430
@ -13075,23 +13075,29 @@
|
||||
|
||||
Unread = {
|
||||
init: function() {
|
||||
if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Desktop Notifications']) {
|
||||
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);
|
||||
this.hr = $.el('hr', {
|
||||
id: 'unread-line'
|
||||
});
|
||||
this.posts = new RandomAccessList;
|
||||
this.postsQuotingYou = [];
|
||||
return Thread.callbacks.push({
|
||||
this.posts = new Set;
|
||||
this.postsQuotingYou = new Set;
|
||||
this.order = new RandomAccessList;
|
||||
this.position = null;
|
||||
Thread.callbacks.push({
|
||||
name: 'Unread',
|
||||
cb: this.node
|
||||
});
|
||||
return Post.callbacks.push({
|
||||
name: 'Unread',
|
||||
cb: this.addPost
|
||||
});
|
||||
},
|
||||
disconnect: function() {
|
||||
var hr, name, _i, _len, _ref;
|
||||
if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Desktop Notifications']) {
|
||||
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;
|
||||
}
|
||||
Unread.db.disconnect();
|
||||
@ -13114,6 +13120,7 @@
|
||||
return Thread.callbacks.disconnect('Unread');
|
||||
},
|
||||
node: function() {
|
||||
var ID, _i, _len, _ref;
|
||||
Unread.thread = this;
|
||||
Unread.title = d.title;
|
||||
Unread.lastReadPost = Unread.db.get({
|
||||
@ -13121,118 +13128,108 @@
|
||||
threadID: this.ID,
|
||||
defaultValue: 0
|
||||
});
|
||||
$.on(d, '4chanXInitFinished', Unread.ready);
|
||||
$.on(d, 'ThreadUpdate', Unread.onUpdate);
|
||||
Unread.readCount = 0;
|
||||
_ref = this.posts.keys;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
ID = _ref[_i];
|
||||
if (+ID <= Unread.lastReadPost) {
|
||||
Unread.readCount++;
|
||||
}
|
||||
}
|
||||
$.one(d, '4chanXInitFinished', Unread.ready);
|
||||
return $.on(d, 'ThreadUpdate', Unread.onUpdate);
|
||||
},
|
||||
ready: function() {
|
||||
Unread.setLine(true);
|
||||
Unread.read();
|
||||
Unread.update();
|
||||
if (Conf['Scroll to Last Read Post']) {
|
||||
Unread.scroll();
|
||||
}
|
||||
$.on(d, 'scroll visibilitychange', Unread.read);
|
||||
if (Conf['Unread Line']) {
|
||||
return $.on(d, 'visibilitychange', Unread.setLine);
|
||||
}
|
||||
},
|
||||
ready: function() {
|
||||
var post, posts;
|
||||
$.off(d, '4chanXInitFinished', Unread.ready);
|
||||
posts = Unread.thread.posts;
|
||||
post = posts.first().nodes.root;
|
||||
return $.asap((function() {
|
||||
return post.getBoundingClientRect().bottom;
|
||||
}), function() {
|
||||
var arr;
|
||||
if (Conf['Quote Threading']) {
|
||||
QuoteThreading.force();
|
||||
} else {
|
||||
arr = [];
|
||||
posts.forEach(function(post) {
|
||||
if (post.isReply) {
|
||||
return arr.push(post);
|
||||
}
|
||||
});
|
||||
Unread.addPosts(arr);
|
||||
}
|
||||
if (Conf['Scroll to Last Read Post']) {
|
||||
return setTimeout(Unread.scroll, 200);
|
||||
}
|
||||
});
|
||||
positionPrev: function() {
|
||||
if (Unread.position) {
|
||||
return Unread.position.prev;
|
||||
} else {
|
||||
return Unread.order.last;
|
||||
}
|
||||
},
|
||||
scroll: function() {
|
||||
var down, hash, keys, post, posts, root;
|
||||
var hash, position, root;
|
||||
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;
|
||||
}
|
||||
position = Unread.positionPrev();
|
||||
while (position) {
|
||||
root = position.data.nodes.root;
|
||||
if (!root.getBoundingClientRect().height) {
|
||||
position = position.prev;
|
||||
} else {
|
||||
Header.scrollToIfNeeded(root, true);
|
||||
break;
|
||||
}
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
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, i, lastReadPost, postIDs, _i, _ref, _ref1;
|
||||
if (Unread.lastReadPost == null) {
|
||||
return;
|
||||
}
|
||||
lastReadPost = Unread.db.get({
|
||||
boardID: Unread.thread.board.ID,
|
||||
threadID: Unread.thread.ID,
|
||||
defaultValue: 0
|
||||
});
|
||||
if (Unread.lastReadPost > lastReadPost) {
|
||||
if (!(Unread.lastReadPost < lastReadPost)) {
|
||||
return;
|
||||
}
|
||||
Unread.lastReadPost = lastReadPost;
|
||||
post = Unread.posts.first;
|
||||
while (post) {
|
||||
ID = post.ID;
|
||||
if (ID > lastReadPost) {
|
||||
break;
|
||||
postIDs = Unread.thread.posts.keys;
|
||||
for (i = _i = _ref = Unread.readCount, _ref1 = postIDs.length; _i < _ref1; i = _i += 1) {
|
||||
ID = +postIDs[i];
|
||||
if (!Unread.thread.posts[ID].isFetchedQuote) {
|
||||
if (ID > Unread.lastReadPost) {
|
||||
break;
|
||||
}
|
||||
Unread.posts["delete"](ID);
|
||||
Unread.postsQuotingYou["delete"](ID);
|
||||
}
|
||||
post = post.next;
|
||||
Unread.posts.rm(ID);
|
||||
}
|
||||
Unread.readArray(Unread.postsQuotingYou);
|
||||
if (Conf['Unread Line']) {
|
||||
Unread.setLine();
|
||||
Unread.readCount++;
|
||||
}
|
||||
Unread.updatePosition();
|
||||
Unread.setLine();
|
||||
return Unread.update();
|
||||
},
|
||||
addPosts: function(posts) {
|
||||
var ID, post, _i, _len, _ref, _ref1;
|
||||
for (_i = 0, _len = posts.length; _i < _len; _i++) {
|
||||
post = posts[_i];
|
||||
ID = post.ID;
|
||||
if (ID <= Unread.lastReadPost || post.isHidden || QR.db.get({
|
||||
boardID: post.board.ID,
|
||||
threadID: post.thread.ID,
|
||||
postID: ID
|
||||
})) {
|
||||
continue;
|
||||
}
|
||||
Unread.posts.push(post);
|
||||
Unread.addPostQuotingYou(post);
|
||||
addPost: function() {
|
||||
var _ref;
|
||||
if (this.isFetchedQuote || this.isClone) {
|
||||
return;
|
||||
}
|
||||
if (Conf['Unread Line']) {
|
||||
Unread.setLine((_ref = (_ref1 = Unread.posts.first) != null ? _ref1.data : void 0, __indexOf.call(posts, _ref) >= 0));
|
||||
Unread.order.push(this);
|
||||
if (this.ID <= Unread.lastReadPost || this.isHidden || ((_ref = QR.db) != null ? _ref.get({
|
||||
boardID: this.board.ID,
|
||||
threadID: this.thread.ID,
|
||||
postID: this.ID
|
||||
}) : void 0)) {
|
||||
return;
|
||||
}
|
||||
Unread.read();
|
||||
return Unread.update();
|
||||
Unread.posts.add(this.ID);
|
||||
Unread.addPostQuotingYou(this);
|
||||
return Unread.position != null ? Unread.position : Unread.position = Unread.order[this.ID];
|
||||
},
|
||||
addPostQuotingYou: function(post) {
|
||||
var quotelink, _i, _len, _ref;
|
||||
var quotelink, _i, _len, _ref, _ref1;
|
||||
_ref = post.nodes.quotelinks;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
quotelink = _ref[_i];
|
||||
if (!(QR.db.get(Get.postDataFromLink(quotelink)))) {
|
||||
if (!((_ref1 = QR.db) != null ? _ref1.get(Get.postDataFromLink(quotelink)) : void 0)) {
|
||||
continue;
|
||||
}
|
||||
Unread.postsQuotingYou.push(post);
|
||||
Unread.postsQuotingYou.add(post.ID);
|
||||
Unread.openNotification(post);
|
||||
return;
|
||||
}
|
||||
@ -13242,8 +13239,8 @@
|
||||
if (!Header.areNotificationsEnabled) {
|
||||
return;
|
||||
}
|
||||
notif = new Notification("" + (post.getNameBlock()) + " replied to you", {
|
||||
body: post.info.comment,
|
||||
notif = new Notification("" + post.info.nameBlock + " replied to you", {
|
||||
body: post.info[Conf['Remove Spoilers'] || Conf['Reveal Spoilers'] ? 'comment' : 'commentSpoilered'],
|
||||
icon: Favicon.logo
|
||||
});
|
||||
notif.onclick = function() {
|
||||
@ -13257,80 +13254,83 @@
|
||||
};
|
||||
},
|
||||
onUpdate: function(e) {
|
||||
if (e.detail[404]) {
|
||||
return Unread.update();
|
||||
} else if (Conf['Quote Threading']) {
|
||||
if (!e.detail[404]) {
|
||||
Unread.setLine();
|
||||
Unread.read();
|
||||
return Unread.update();
|
||||
} else {
|
||||
return Unread.addPosts([].map.call(e.detail.newPosts, function(fullID) {
|
||||
return g.posts[fullID];
|
||||
}));
|
||||
}
|
||||
},
|
||||
readSinglePost: function(post) {
|
||||
var ID, i, posts;
|
||||
ID = post.ID;
|
||||
posts = Unread.posts;
|
||||
if (!posts[ID]) {
|
||||
return;
|
||||
}
|
||||
if (post === posts.first) {
|
||||
Unread.lastReadPost = ID;
|
||||
Unread.saveLastReadPost();
|
||||
}
|
||||
posts.rm(ID);
|
||||
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
|
||||
Unread.postsQuotingYou.splice(i, 1);
|
||||
}
|
||||
return Unread.update();
|
||||
},
|
||||
readArray: function(arr) {
|
||||
var i, post, _i, _len;
|
||||
for (i = _i = 0, _len = arr.length; _i < _len; i = ++_i) {
|
||||
post = arr[i];
|
||||
if (post.ID > Unread.lastReadPost) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return arr.splice(0, i);
|
||||
},
|
||||
read: $.debounce(100, function(e) {
|
||||
var ID, data, post, posts;
|
||||
if (d.hidden || !Unread.posts.length) {
|
||||
readSinglePost: function(post) {
|
||||
var ID;
|
||||
ID = post.ID;
|
||||
if (!Unread.posts.has(ID)) {
|
||||
return;
|
||||
}
|
||||
posts = Unread.posts;
|
||||
while (post = posts.first) {
|
||||
if (!(Header.getBottomOf(post.data.nodes.root) > -1)) {
|
||||
Unread.posts["delete"](ID);
|
||||
Unread.postsQuotingYou["delete"](ID);
|
||||
Unread.updatePosition();
|
||||
Unread.saveLastReadPost();
|
||||
return Unread.update();
|
||||
},
|
||||
read: $.debounce(100, function(e) {
|
||||
var ID, count, data, height, root, _ref, _ref1;
|
||||
if (d.hidden || !Unread.posts.size) {
|
||||
return;
|
||||
}
|
||||
height = doc.clientHeight;
|
||||
count = 0;
|
||||
while (Unread.position) {
|
||||
_ref = Unread.position, ID = _ref.ID, data = _ref.data;
|
||||
root = data.nodes.root;
|
||||
if (!(!root.getBoundingClientRect().height || Header.getBottomOf(root) > -1)) {
|
||||
break;
|
||||
}
|
||||
ID = post.ID, data = post.data;
|
||||
posts.rm(ID);
|
||||
if (Conf['Mark Quotes of You'] && QR.db.get({
|
||||
count++;
|
||||
Unread.posts["delete"](ID);
|
||||
Unread.postsQuotingYou["delete"](ID);
|
||||
if (Conf['Mark Quotes of You'] && ((_ref1 = QR.db) != null ? _ref1.get({
|
||||
boardID: data.board.ID,
|
||||
threadID: data.thread.ID,
|
||||
postID: ID
|
||||
})) {
|
||||
QuoteMarkers.lastRead = data.nodes.root;
|
||||
}) : void 0)) {
|
||||
QuoteYou.lastRead = root;
|
||||
}
|
||||
Unread.position = Unread.position.next;
|
||||
}
|
||||
if (!ID) {
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
if (Unread.lastReadPost < ID) {
|
||||
Unread.lastReadPost = ID;
|
||||
}
|
||||
Unread.updatePosition();
|
||||
Unread.saveLastReadPost();
|
||||
Unread.readArray(Unread.postsQuotingYou);
|
||||
if (e) {
|
||||
return Unread.update();
|
||||
}
|
||||
}),
|
||||
saveLastReadPost: $.debounce(5 * $.SECOND, function() {
|
||||
if (Unread.thread.isDead) {
|
||||
updatePosition: function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
while (Unread.position && !Unread.posts.has(Unread.position.ID)) {
|
||||
_results.push(Unread.position = Unread.position.next);
|
||||
}
|
||||
return _results;
|
||||
},
|
||||
saveLastReadPost: $.debounce(2 * $.SECOND, function() {
|
||||
var ID, i, postIDs, _i, _ref, _ref1;
|
||||
postIDs = Unread.thread.posts.keys;
|
||||
for (i = _i = _ref = Unread.readCount, _ref1 = postIDs.length; _i < _ref1; i = _i += 1) {
|
||||
ID = +postIDs[i];
|
||||
if (!Unread.thread.posts[ID].isFetchedQuote) {
|
||||
if (Unread.posts.has(ID)) {
|
||||
break;
|
||||
}
|
||||
Unread.lastReadPost = ID;
|
||||
}
|
||||
Unread.readCount++;
|
||||
}
|
||||
if (Unread.thread.isDead && !Unread.thread.isArchived) {
|
||||
return;
|
||||
}
|
||||
Unread.db.forceSync();
|
||||
return Unread.db.set({
|
||||
boardID: Unread.thread.board.ID,
|
||||
threadID: Unread.thread.ID,
|
||||
@ -13338,27 +13338,39 @@
|
||||
});
|
||||
}),
|
||||
setLine: function(force) {
|
||||
var post;
|
||||
if (!(d.hidden || force === true)) {
|
||||
if (!Conf['Unread Line']) {
|
||||
return;
|
||||
}
|
||||
if (!(post = Unread.posts.first)) {
|
||||
return $.rm(Unread.hr);
|
||||
}
|
||||
if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.data.nodes.root)) {
|
||||
return $.before(post.data.nodes.root, Unread.hr);
|
||||
if (d.hidden || (force === true)) {
|
||||
if (Unread.linePosition = Unread.positionPrev()) {
|
||||
$.after(Unread.linePosition.data.nodes.root, Unread.hr);
|
||||
} else {
|
||||
$.rm(Unread.hr);
|
||||
}
|
||||
}
|
||||
return Unread.hr.hidden = Unread.linePosition === Unread.order.last;
|
||||
},
|
||||
update: function() {
|
||||
var count;
|
||||
count = Unread.posts.length;
|
||||
var count, countQuotingYou, titleCount, titleDead, titleQuotingYou;
|
||||
count = Unread.posts.size;
|
||||
countQuotingYou = Unread.postsQuotingYou.size;
|
||||
if (Conf['Unread Count']) {
|
||||
d.title = "" + (count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '') + (g.DEAD ? Unread.title.replace('-', '- 404 -') : Unread.title);
|
||||
titleQuotingYou = Conf['Quoted Title'] && countQuotingYou ? '(!) ' : '';
|
||||
titleCount = count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '';
|
||||
titleDead = Unread.thread.isDead ? Unread.title.replace('-', (Unread.thread.isArchived ? '- Archived -' : '- 404 -')) : Unread.title;
|
||||
d.title = "" + titleQuotingYou + titleCount + titleDead;
|
||||
}
|
||||
if (!(Unread.thread.isDead && !Unread.thread.isArchived)) {
|
||||
ThreadWatcher.update(Unread.thread.board.ID, Unread.thread.ID, {
|
||||
isDead: Unread.thread.isDead,
|
||||
unread: count,
|
||||
quotingYou: countQuotingYou
|
||||
});
|
||||
}
|
||||
if (!Conf['Unread Favicon']) {
|
||||
return;
|
||||
}
|
||||
Favicon.el.href = g.DEAD ? Unread.postsQuotingYou[0] ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? Unread.postsQuotingYou[0] ? Favicon.unreadY : Favicon.unread : Favicon["default"];
|
||||
Favicon.el.href = Unread.thread.isDead ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"];
|
||||
return $.add(d.head, Favicon.el);
|
||||
}
|
||||
};
|
||||
|
||||
@ -13064,23 +13064,29 @@
|
||||
|
||||
Unread = {
|
||||
init: function() {
|
||||
if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Desktop Notifications']) {
|
||||
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);
|
||||
this.hr = $.el('hr', {
|
||||
id: 'unread-line'
|
||||
});
|
||||
this.posts = new RandomAccessList;
|
||||
this.postsQuotingYou = [];
|
||||
return Thread.callbacks.push({
|
||||
this.posts = new Set;
|
||||
this.postsQuotingYou = new Set;
|
||||
this.order = new RandomAccessList;
|
||||
this.position = null;
|
||||
Thread.callbacks.push({
|
||||
name: 'Unread',
|
||||
cb: this.node
|
||||
});
|
||||
return Post.callbacks.push({
|
||||
name: 'Unread',
|
||||
cb: this.addPost
|
||||
});
|
||||
},
|
||||
disconnect: function() {
|
||||
var hr, name, _i, _len, _ref;
|
||||
if (g.VIEW !== 'thread' || !Conf['Unread Count'] && !Conf['Unread Favicon'] && !Conf['Desktop Notifications']) {
|
||||
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;
|
||||
}
|
||||
Unread.db.disconnect();
|
||||
@ -13103,6 +13109,7 @@
|
||||
return Thread.callbacks.disconnect('Unread');
|
||||
},
|
||||
node: function() {
|
||||
var ID, _i, _len, _ref;
|
||||
Unread.thread = this;
|
||||
Unread.title = d.title;
|
||||
Unread.lastReadPost = Unread.db.get({
|
||||
@ -13110,118 +13117,108 @@
|
||||
threadID: this.ID,
|
||||
defaultValue: 0
|
||||
});
|
||||
$.on(d, '4chanXInitFinished', Unread.ready);
|
||||
$.on(d, 'ThreadUpdate', Unread.onUpdate);
|
||||
Unread.readCount = 0;
|
||||
_ref = this.posts.keys;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
ID = _ref[_i];
|
||||
if (+ID <= Unread.lastReadPost) {
|
||||
Unread.readCount++;
|
||||
}
|
||||
}
|
||||
$.one(d, '4chanXInitFinished', Unread.ready);
|
||||
return $.on(d, 'ThreadUpdate', Unread.onUpdate);
|
||||
},
|
||||
ready: function() {
|
||||
Unread.setLine(true);
|
||||
Unread.read();
|
||||
Unread.update();
|
||||
if (Conf['Scroll to Last Read Post']) {
|
||||
Unread.scroll();
|
||||
}
|
||||
$.on(d, 'scroll visibilitychange', Unread.read);
|
||||
if (Conf['Unread Line']) {
|
||||
return $.on(d, 'visibilitychange', Unread.setLine);
|
||||
}
|
||||
},
|
||||
ready: function() {
|
||||
var post, posts;
|
||||
$.off(d, '4chanXInitFinished', Unread.ready);
|
||||
posts = Unread.thread.posts;
|
||||
post = posts.first().nodes.root;
|
||||
return $.asap((function() {
|
||||
return post.getBoundingClientRect().bottom;
|
||||
}), function() {
|
||||
var arr;
|
||||
if (Conf['Quote Threading']) {
|
||||
QuoteThreading.force();
|
||||
} else {
|
||||
arr = [];
|
||||
posts.forEach(function(post) {
|
||||
if (post.isReply) {
|
||||
return arr.push(post);
|
||||
}
|
||||
});
|
||||
Unread.addPosts(arr);
|
||||
}
|
||||
if (Conf['Scroll to Last Read Post']) {
|
||||
return setTimeout(Unread.scroll, 200);
|
||||
}
|
||||
});
|
||||
positionPrev: function() {
|
||||
if (Unread.position) {
|
||||
return Unread.position.prev;
|
||||
} else {
|
||||
return Unread.order.last;
|
||||
}
|
||||
},
|
||||
scroll: function() {
|
||||
var down, hash, keys, post, posts, root;
|
||||
var hash, position, root;
|
||||
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;
|
||||
}
|
||||
position = Unread.positionPrev();
|
||||
while (position) {
|
||||
root = position.data.nodes.root;
|
||||
if (!root.getBoundingClientRect().height) {
|
||||
position = position.prev;
|
||||
} else {
|
||||
Header.scrollToIfNeeded(root, true);
|
||||
break;
|
||||
}
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
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, i, lastReadPost, postIDs, _i, _ref, _ref1;
|
||||
if (Unread.lastReadPost == null) {
|
||||
return;
|
||||
}
|
||||
lastReadPost = Unread.db.get({
|
||||
boardID: Unread.thread.board.ID,
|
||||
threadID: Unread.thread.ID,
|
||||
defaultValue: 0
|
||||
});
|
||||
if (Unread.lastReadPost > lastReadPost) {
|
||||
if (!(Unread.lastReadPost < lastReadPost)) {
|
||||
return;
|
||||
}
|
||||
Unread.lastReadPost = lastReadPost;
|
||||
post = Unread.posts.first;
|
||||
while (post) {
|
||||
ID = post.ID;
|
||||
if (ID > lastReadPost) {
|
||||
break;
|
||||
postIDs = Unread.thread.posts.keys;
|
||||
for (i = _i = _ref = Unread.readCount, _ref1 = postIDs.length; _i < _ref1; i = _i += 1) {
|
||||
ID = +postIDs[i];
|
||||
if (!Unread.thread.posts[ID].isFetchedQuote) {
|
||||
if (ID > Unread.lastReadPost) {
|
||||
break;
|
||||
}
|
||||
Unread.posts["delete"](ID);
|
||||
Unread.postsQuotingYou["delete"](ID);
|
||||
}
|
||||
post = post.next;
|
||||
Unread.posts.rm(ID);
|
||||
}
|
||||
Unread.readArray(Unread.postsQuotingYou);
|
||||
if (Conf['Unread Line']) {
|
||||
Unread.setLine();
|
||||
Unread.readCount++;
|
||||
}
|
||||
Unread.updatePosition();
|
||||
Unread.setLine();
|
||||
return Unread.update();
|
||||
},
|
||||
addPosts: function(posts) {
|
||||
var ID, post, _i, _len, _ref, _ref1;
|
||||
for (_i = 0, _len = posts.length; _i < _len; _i++) {
|
||||
post = posts[_i];
|
||||
ID = post.ID;
|
||||
if (ID <= Unread.lastReadPost || post.isHidden || QR.db.get({
|
||||
boardID: post.board.ID,
|
||||
threadID: post.thread.ID,
|
||||
postID: ID
|
||||
})) {
|
||||
continue;
|
||||
}
|
||||
Unread.posts.push(post);
|
||||
Unread.addPostQuotingYou(post);
|
||||
addPost: function() {
|
||||
var _ref;
|
||||
if (this.isFetchedQuote || this.isClone) {
|
||||
return;
|
||||
}
|
||||
if (Conf['Unread Line']) {
|
||||
Unread.setLine((_ref = (_ref1 = Unread.posts.first) != null ? _ref1.data : void 0, __indexOf.call(posts, _ref) >= 0));
|
||||
Unread.order.push(this);
|
||||
if (this.ID <= Unread.lastReadPost || this.isHidden || ((_ref = QR.db) != null ? _ref.get({
|
||||
boardID: this.board.ID,
|
||||
threadID: this.thread.ID,
|
||||
postID: this.ID
|
||||
}) : void 0)) {
|
||||
return;
|
||||
}
|
||||
Unread.read();
|
||||
return Unread.update();
|
||||
Unread.posts.add(this.ID);
|
||||
Unread.addPostQuotingYou(this);
|
||||
return Unread.position != null ? Unread.position : Unread.position = Unread.order[this.ID];
|
||||
},
|
||||
addPostQuotingYou: function(post) {
|
||||
var quotelink, _i, _len, _ref;
|
||||
var quotelink, _i, _len, _ref, _ref1;
|
||||
_ref = post.nodes.quotelinks;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
quotelink = _ref[_i];
|
||||
if (!(QR.db.get(Get.postDataFromLink(quotelink)))) {
|
||||
if (!((_ref1 = QR.db) != null ? _ref1.get(Get.postDataFromLink(quotelink)) : void 0)) {
|
||||
continue;
|
||||
}
|
||||
Unread.postsQuotingYou.push(post);
|
||||
Unread.postsQuotingYou.add(post.ID);
|
||||
Unread.openNotification(post);
|
||||
return;
|
||||
}
|
||||
@ -13231,8 +13228,8 @@
|
||||
if (!Header.areNotificationsEnabled) {
|
||||
return;
|
||||
}
|
||||
notif = new Notification("" + (post.getNameBlock()) + " replied to you", {
|
||||
body: post.info.comment,
|
||||
notif = new Notification("" + post.info.nameBlock + " replied to you", {
|
||||
body: post.info[Conf['Remove Spoilers'] || Conf['Reveal Spoilers'] ? 'comment' : 'commentSpoilered'],
|
||||
icon: Favicon.logo
|
||||
});
|
||||
notif.onclick = function() {
|
||||
@ -13246,80 +13243,83 @@
|
||||
};
|
||||
},
|
||||
onUpdate: function(e) {
|
||||
if (e.detail[404]) {
|
||||
return Unread.update();
|
||||
} else if (Conf['Quote Threading']) {
|
||||
if (!e.detail[404]) {
|
||||
Unread.setLine();
|
||||
Unread.read();
|
||||
return Unread.update();
|
||||
} else {
|
||||
return Unread.addPosts([].map.call(e.detail.newPosts, function(fullID) {
|
||||
return g.posts[fullID];
|
||||
}));
|
||||
}
|
||||
},
|
||||
readSinglePost: function(post) {
|
||||
var ID, i, posts;
|
||||
ID = post.ID;
|
||||
posts = Unread.posts;
|
||||
if (!posts[ID]) {
|
||||
return;
|
||||
}
|
||||
if (post === posts.first) {
|
||||
Unread.lastReadPost = ID;
|
||||
Unread.saveLastReadPost();
|
||||
}
|
||||
posts.rm(ID);
|
||||
if ((i = Unread.postsQuotingYou.indexOf(post)) !== -1) {
|
||||
Unread.postsQuotingYou.splice(i, 1);
|
||||
}
|
||||
return Unread.update();
|
||||
},
|
||||
readArray: function(arr) {
|
||||
var i, post, _i, _len;
|
||||
for (i = _i = 0, _len = arr.length; _i < _len; i = ++_i) {
|
||||
post = arr[i];
|
||||
if (post.ID > Unread.lastReadPost) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return arr.splice(0, i);
|
||||
},
|
||||
read: $.debounce(100, function(e) {
|
||||
var ID, data, post, posts;
|
||||
if (d.hidden || !Unread.posts.length) {
|
||||
readSinglePost: function(post) {
|
||||
var ID;
|
||||
ID = post.ID;
|
||||
if (!Unread.posts.has(ID)) {
|
||||
return;
|
||||
}
|
||||
posts = Unread.posts;
|
||||
while (post = posts.first) {
|
||||
if (!(Header.getBottomOf(post.data.nodes.root) > -1)) {
|
||||
Unread.posts["delete"](ID);
|
||||
Unread.postsQuotingYou["delete"](ID);
|
||||
Unread.updatePosition();
|
||||
Unread.saveLastReadPost();
|
||||
return Unread.update();
|
||||
},
|
||||
read: $.debounce(100, function(e) {
|
||||
var ID, count, data, height, root, _ref, _ref1;
|
||||
if (d.hidden || !Unread.posts.size) {
|
||||
return;
|
||||
}
|
||||
height = doc.clientHeight;
|
||||
count = 0;
|
||||
while (Unread.position) {
|
||||
_ref = Unread.position, ID = _ref.ID, data = _ref.data;
|
||||
root = data.nodes.root;
|
||||
if (!(!root.getBoundingClientRect().height || Header.getBottomOf(root) > -1)) {
|
||||
break;
|
||||
}
|
||||
ID = post.ID, data = post.data;
|
||||
posts.rm(ID);
|
||||
if (Conf['Mark Quotes of You'] && QR.db.get({
|
||||
count++;
|
||||
Unread.posts["delete"](ID);
|
||||
Unread.postsQuotingYou["delete"](ID);
|
||||
if (Conf['Mark Quotes of You'] && ((_ref1 = QR.db) != null ? _ref1.get({
|
||||
boardID: data.board.ID,
|
||||
threadID: data.thread.ID,
|
||||
postID: ID
|
||||
})) {
|
||||
QuoteMarkers.lastRead = data.nodes.root;
|
||||
}) : void 0)) {
|
||||
QuoteYou.lastRead = root;
|
||||
}
|
||||
Unread.position = Unread.position.next;
|
||||
}
|
||||
if (!ID) {
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
if (Unread.lastReadPost < ID) {
|
||||
Unread.lastReadPost = ID;
|
||||
}
|
||||
Unread.updatePosition();
|
||||
Unread.saveLastReadPost();
|
||||
Unread.readArray(Unread.postsQuotingYou);
|
||||
if (e) {
|
||||
return Unread.update();
|
||||
}
|
||||
}),
|
||||
saveLastReadPost: $.debounce(5 * $.SECOND, function() {
|
||||
if (Unread.thread.isDead) {
|
||||
updatePosition: function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
while (Unread.position && !Unread.posts.has(Unread.position.ID)) {
|
||||
_results.push(Unread.position = Unread.position.next);
|
||||
}
|
||||
return _results;
|
||||
},
|
||||
saveLastReadPost: $.debounce(2 * $.SECOND, function() {
|
||||
var ID, i, postIDs, _i, _ref, _ref1;
|
||||
postIDs = Unread.thread.posts.keys;
|
||||
for (i = _i = _ref = Unread.readCount, _ref1 = postIDs.length; _i < _ref1; i = _i += 1) {
|
||||
ID = +postIDs[i];
|
||||
if (!Unread.thread.posts[ID].isFetchedQuote) {
|
||||
if (Unread.posts.has(ID)) {
|
||||
break;
|
||||
}
|
||||
Unread.lastReadPost = ID;
|
||||
}
|
||||
Unread.readCount++;
|
||||
}
|
||||
if (Unread.thread.isDead && !Unread.thread.isArchived) {
|
||||
return;
|
||||
}
|
||||
Unread.db.forceSync();
|
||||
return Unread.db.set({
|
||||
boardID: Unread.thread.board.ID,
|
||||
threadID: Unread.thread.ID,
|
||||
@ -13327,27 +13327,39 @@
|
||||
});
|
||||
}),
|
||||
setLine: function(force) {
|
||||
var post;
|
||||
if (!(d.hidden || force === true)) {
|
||||
if (!Conf['Unread Line']) {
|
||||
return;
|
||||
}
|
||||
if (!(post = Unread.posts.first)) {
|
||||
return $.rm(Unread.hr);
|
||||
}
|
||||
if ($.x('preceding-sibling::div[contains(@class,"replyContainer")]', post.data.nodes.root)) {
|
||||
return $.before(post.data.nodes.root, Unread.hr);
|
||||
if (d.hidden || (force === true)) {
|
||||
if (Unread.linePosition = Unread.positionPrev()) {
|
||||
$.after(Unread.linePosition.data.nodes.root, Unread.hr);
|
||||
} else {
|
||||
$.rm(Unread.hr);
|
||||
}
|
||||
}
|
||||
return Unread.hr.hidden = Unread.linePosition === Unread.order.last;
|
||||
},
|
||||
update: function() {
|
||||
var count;
|
||||
count = Unread.posts.length;
|
||||
var count, countQuotingYou, titleCount, titleDead, titleQuotingYou;
|
||||
count = Unread.posts.size;
|
||||
countQuotingYou = Unread.postsQuotingYou.size;
|
||||
if (Conf['Unread Count']) {
|
||||
d.title = "" + (count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '') + (g.DEAD ? Unread.title.replace('-', '- 404 -') : Unread.title);
|
||||
titleQuotingYou = Conf['Quoted Title'] && countQuotingYou ? '(!) ' : '';
|
||||
titleCount = count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : '';
|
||||
titleDead = Unread.thread.isDead ? Unread.title.replace('-', (Unread.thread.isArchived ? '- Archived -' : '- 404 -')) : Unread.title;
|
||||
d.title = "" + titleQuotingYou + titleCount + titleDead;
|
||||
}
|
||||
if (!(Unread.thread.isDead && !Unread.thread.isArchived)) {
|
||||
ThreadWatcher.update(Unread.thread.board.ID, Unread.thread.ID, {
|
||||
isDead: Unread.thread.isDead,
|
||||
unread: count,
|
||||
quotingYou: countQuotingYou
|
||||
});
|
||||
}
|
||||
if (!Conf['Unread Favicon']) {
|
||||
return;
|
||||
}
|
||||
return Favicon.el.href = g.DEAD ? Unread.postsQuotingYou[0] ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? Unread.postsQuotingYou[0] ? Favicon.unreadY : Favicon.unread : Favicon["default"];
|
||||
return Favicon.el.href = Unread.thread.isDead ? countQuotingYou ? Favicon.unreadDeadY : count ? Favicon.unreadDead : Favicon.dead : count ? countQuotingYou ? Favicon.unreadY : Favicon.unread : Favicon["default"];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,19 +1,39 @@
|
||||
Unread =
|
||||
init: ->
|
||||
return if g.VIEW isnt 'thread' or !Conf['Unread Count'] and !Conf['Unread Favicon'] and !Conf['Desktop Notifications']
|
||||
return unless g.VIEW is 'thread' and
|
||||
Conf['Unread Count'] or
|
||||
Conf['Unread Favicon'] or
|
||||
Conf['Unread Line'] or
|
||||
Conf['Scroll to Last Read Post'] or
|
||||
Conf['Thread Watcher'] or
|
||||
Conf['Desktop Notifications'] or
|
||||
Conf['Quote Threading']
|
||||
|
||||
@db = new DataBoard 'lastReadPosts', @sync
|
||||
@hr = $.el 'hr',
|
||||
id: 'unread-line'
|
||||
@posts = new RandomAccessList
|
||||
@postsQuotingYou = []
|
||||
@posts = new Set
|
||||
@postsQuotingYou = new Set
|
||||
@order = new RandomAccessList
|
||||
@position = null
|
||||
|
||||
Thread.callbacks.push
|
||||
name: 'Unread'
|
||||
cb: @node
|
||||
|
||||
Post.callbacks.push
|
||||
name: 'Unread'
|
||||
cb: @addPost
|
||||
|
||||
disconnect: ->
|
||||
return if g.VIEW isnt 'thread' or !Conf['Unread Count'] and !Conf['Unread Favicon'] and !Conf['Desktop Notifications']
|
||||
return unless g.VIEW is 'thread' and
|
||||
Conf['Unread Count'] or
|
||||
Conf['Unread Favicon'] or
|
||||
Conf['Unread Line'] or
|
||||
Conf['Scroll to Last Read Post'] or
|
||||
Conf['Thread Watcher'] or
|
||||
Conf['Desktop Notifications'] or
|
||||
Conf['Quote Threading']
|
||||
|
||||
Unread.db.disconnect()
|
||||
{hr} = Unread
|
||||
@ -33,92 +53,84 @@ Unread =
|
||||
Unread.thread = @
|
||||
Unread.title = d.title
|
||||
Unread.lastReadPost = Unread.db.get
|
||||
boardID: @board.ID
|
||||
threadID: @ID
|
||||
boardID: @board.ID
|
||||
threadID: @ID
|
||||
defaultValue: 0
|
||||
$.on d, '4chanXInitFinished', Unread.ready
|
||||
$.on d, 'ThreadUpdate', Unread.onUpdate
|
||||
$.on d, 'scroll visibilitychange', Unread.read
|
||||
$.on d, 'visibilitychange', Unread.setLine if Conf['Unread Line']
|
||||
Unread.readCount = 0
|
||||
Unread.readCount++ for ID in @posts.keys when +ID <= Unread.lastReadPost
|
||||
$.one d, '4chanXInitFinished', Unread.ready
|
||||
$.on d, 'ThreadUpdate', Unread.onUpdate
|
||||
|
||||
ready: ->
|
||||
$.off d, '4chanXInitFinished', Unread.ready
|
||||
{posts} = Unread.thread
|
||||
post = posts.first().nodes.root
|
||||
# XXX I'm guessing the browser isn't reflowing fast enough?
|
||||
$.asap (-> post.getBoundingClientRect().bottom), ->
|
||||
if Conf['Quote Threading']
|
||||
QuoteThreading.force()
|
||||
else
|
||||
arr = []
|
||||
posts.forEach (post) -> arr.push post if post.isReply
|
||||
Unread.addPosts arr
|
||||
setTimeout Unread.scroll, 200 if Conf['Scroll to Last Read Post']
|
||||
Unread.setLine true
|
||||
Unread.read()
|
||||
Unread.update()
|
||||
Unread.scroll() if Conf['Scroll to Last Read Post']
|
||||
$.on d, 'scroll visibilitychange', Unread.read
|
||||
$.on d, 'visibilitychange', Unread.setLine if Conf['Unread Line']
|
||||
|
||||
positionPrev: ->
|
||||
if Unread.position then Unread.position.prev else Unread.order.last
|
||||
|
||||
scroll: ->
|
||||
# Let the header's onload callback handle it.
|
||||
return if (hash = location.hash.match /\d+/) and hash[0] of Unread.thread.posts
|
||||
if post = Unread.posts.first
|
||||
# Scroll to a non-hidden, non-OP post that's before the first unread post.
|
||||
while root = $.x 'preceding-sibling::div[contains(@class,"replyContainer")][1]', post.data.nodes.root
|
||||
break unless (post = Get.postFromRoot root).isHidden
|
||||
return unless root
|
||||
down = true
|
||||
else
|
||||
# Scroll to the last read post.
|
||||
{posts} = Unread.thread
|
||||
{keys} = posts
|
||||
{root} = posts[keys[keys.length - 1]].nodes
|
||||
|
||||
# Scroll to the target unless we scrolled past it.
|
||||
Header.scrollTo root, down if Header.getBottomOf(root) < 0
|
||||
position = Unread.positionPrev()
|
||||
while position
|
||||
{root} = position.data.nodes
|
||||
if !root.getBoundingClientRect().height
|
||||
# Don't try to scroll to posts with display: none
|
||||
position = position.prev
|
||||
else
|
||||
Header.scrollToIfNeeded root, true
|
||||
break
|
||||
return
|
||||
|
||||
sync: ->
|
||||
return unless Unread.lastReadPost?
|
||||
lastReadPost = Unread.db.get
|
||||
boardID: Unread.thread.board.ID
|
||||
threadID: Unread.thread.ID
|
||||
boardID: Unread.thread.board.ID
|
||||
threadID: Unread.thread.ID
|
||||
defaultValue: 0
|
||||
|
||||
return if Unread.lastReadPost > lastReadPost
|
||||
|
||||
return unless Unread.lastReadPost < lastReadPost
|
||||
Unread.lastReadPost = lastReadPost
|
||||
post = Unread.posts.first
|
||||
while post
|
||||
{ID} = post
|
||||
break if ID > lastReadPost
|
||||
post = post.next
|
||||
Unread.posts.rm ID
|
||||
|
||||
Unread.readArray Unread.postsQuotingYou
|
||||
Unread.setLine() if Conf['Unread Line']
|
||||
postIDs = Unread.thread.posts.keys
|
||||
for i in [Unread.readCount...postIDs.length] by 1
|
||||
ID = +postIDs[i]
|
||||
unless Unread.thread.posts[ID].isFetchedQuote
|
||||
break if ID > Unread.lastReadPost
|
||||
Unread.posts.delete ID
|
||||
Unread.postsQuotingYou.delete ID
|
||||
Unread.readCount++
|
||||
|
||||
Unread.updatePosition()
|
||||
Unread.setLine()
|
||||
Unread.update()
|
||||
|
||||
addPosts: (posts) ->
|
||||
for post in posts
|
||||
{ID} = post
|
||||
continue if ID <= Unread.lastReadPost or post.isHidden or QR.db.get {
|
||||
boardID: post.board.ID
|
||||
threadID: post.thread.ID
|
||||
postID: ID
|
||||
}
|
||||
Unread.posts.push post
|
||||
Unread.addPostQuotingYou post
|
||||
if Conf['Unread Line']
|
||||
# Force line on visible threads if there were no unread posts previously.
|
||||
Unread.setLine Unread.posts.first?.data in posts
|
||||
Unread.read()
|
||||
Unread.update()
|
||||
addPost: ->
|
||||
return if @isFetchedQuote or @isClone
|
||||
Unread.order.push @
|
||||
return if @ID <= Unread.lastReadPost or @isHidden or QR.db?.get {
|
||||
boardID: @board.ID
|
||||
threadID: @thread.ID
|
||||
postID: @ID
|
||||
}
|
||||
Unread.posts.add @ID
|
||||
Unread.addPostQuotingYou @
|
||||
Unread.position ?= Unread.order[@ID]
|
||||
|
||||
addPostQuotingYou: (post) ->
|
||||
for quotelink in post.nodes.quotelinks when QR.db.get Get.postDataFromLink quotelink
|
||||
Unread.postsQuotingYou.push post
|
||||
for quotelink in post.nodes.quotelinks when QR.db?.get Get.postDataFromLink quotelink
|
||||
Unread.postsQuotingYou.add post.ID
|
||||
Unread.openNotification post
|
||||
return
|
||||
|
||||
openNotification: (post) ->
|
||||
return unless Header.areNotificationsEnabled
|
||||
notif = new Notification "#{post.getNameBlock()} replied to you",
|
||||
body: post.info.comment
|
||||
notif = new Notification "#{post.info.nameBlock} replied to you",
|
||||
body: post.info[if Conf['Remove Spoilers'] or Conf['Reveal Spoilers'] then 'comment' else 'commentSpoilered']
|
||||
icon: Favicon.logo
|
||||
notif.onclick = ->
|
||||
Header.scrollToIfNeeded post.nodes.root, true
|
||||
@ -129,78 +141,99 @@ Unread =
|
||||
, 7 * $.SECOND
|
||||
|
||||
onUpdate: (e) ->
|
||||
if e.detail[404]
|
||||
Unread.update()
|
||||
else if Conf['Quote Threading']
|
||||
if !e.detail[404]
|
||||
Unread.setLine()
|
||||
Unread.read()
|
||||
Unread.update()
|
||||
else
|
||||
Unread.addPosts [].map.call e.detail.newPosts, (fullID) -> g.posts[fullID]
|
||||
Unread.update()
|
||||
|
||||
readSinglePost: (post) ->
|
||||
{ID} = post
|
||||
{posts} = Unread
|
||||
return unless posts[ID]
|
||||
if post is posts.first
|
||||
Unread.lastReadPost = ID
|
||||
Unread.saveLastReadPost()
|
||||
posts.rm ID
|
||||
if (i = Unread.postsQuotingYou.indexOf post) isnt -1
|
||||
Unread.postsQuotingYou.splice i, 1
|
||||
return unless Unread.posts.has ID
|
||||
Unread.posts.delete ID
|
||||
Unread.postsQuotingYou.delete ID
|
||||
Unread.updatePosition()
|
||||
Unread.saveLastReadPost()
|
||||
Unread.update()
|
||||
|
||||
readArray: (arr) ->
|
||||
for post, i in arr
|
||||
break if post.ID > Unread.lastReadPost
|
||||
arr.splice 0, i
|
||||
|
||||
read: $.debounce 100, (e) ->
|
||||
return if d.hidden or !Unread.posts.length
|
||||
{posts} = Unread
|
||||
return if d.hidden or !Unread.posts.size
|
||||
height = doc.clientHeight
|
||||
|
||||
while post = posts.first
|
||||
break unless Header.getBottomOf(post.data.nodes.root) > -1 # post is not completely read
|
||||
{ID, data} = post
|
||||
posts.rm ID
|
||||
count = 0
|
||||
while Unread.position
|
||||
{ID, data} = Unread.position
|
||||
{root} = data.nodes
|
||||
break unless !root.getBoundingClientRect().height or # post has been hidden
|
||||
Header.getBottomOf(root) > -1 # post is completely read
|
||||
count++
|
||||
Unread.posts.delete ID
|
||||
Unread.postsQuotingYou.delete ID
|
||||
|
||||
if Conf['Mark Quotes of You'] and QR.db.get {
|
||||
if Conf['Mark Quotes of You'] and QR.db?.get {
|
||||
boardID: data.board.ID
|
||||
threadID: data.thread.ID
|
||||
postID: ID
|
||||
}
|
||||
QuoteMarkers.lastRead = data.nodes.root
|
||||
QuoteYou.lastRead = root
|
||||
Unread.position = Unread.position.next
|
||||
|
||||
return unless ID
|
||||
|
||||
Unread.lastReadPost = ID if Unread.lastReadPost < ID
|
||||
return unless count
|
||||
Unread.updatePosition()
|
||||
Unread.saveLastReadPost()
|
||||
Unread.readArray Unread.postsQuotingYou
|
||||
Unread.update() if e
|
||||
|
||||
saveLastReadPost: $.debounce 5 * $.SECOND, ->
|
||||
return if Unread.thread.isDead
|
||||
updatePosition: ->
|
||||
while Unread.position and !Unread.posts.has Unread.position.ID
|
||||
Unread.position = Unread.position.next
|
||||
|
||||
saveLastReadPost: $.debounce 2 * $.SECOND, ->
|
||||
postIDs = Unread.thread.posts.keys
|
||||
for i in [Unread.readCount...postIDs.length] by 1
|
||||
ID = +postIDs[i]
|
||||
unless Unread.thread.posts[ID].isFetchedQuote
|
||||
break if Unread.posts.has ID
|
||||
Unread.lastReadPost = ID
|
||||
Unread.readCount++
|
||||
return if Unread.thread.isDead and !Unread.thread.isArchived
|
||||
Unread.db.forceSync()
|
||||
Unread.db.set
|
||||
boardID: Unread.thread.board.ID
|
||||
threadID: Unread.thread.ID
|
||||
val: Unread.lastReadPost
|
||||
|
||||
setLine: (force) ->
|
||||
return unless d.hidden or force is true
|
||||
return $.rm Unread.hr unless post = Unread.posts.first
|
||||
if $.x 'preceding-sibling::div[contains(@class,"replyContainer")]', post.data.nodes.root # not the first reply
|
||||
$.before post.data.nodes.root, Unread.hr
|
||||
return unless Conf['Unread Line']
|
||||
if d.hidden or (force is true)
|
||||
if Unread.linePosition = Unread.positionPrev()
|
||||
$.after Unread.linePosition.data.nodes.root, Unread.hr
|
||||
else
|
||||
$.rm Unread.hr
|
||||
Unread.hr.hidden = Unread.linePosition is Unread.order.last
|
||||
|
||||
update: ->
|
||||
count = Unread.posts.length
|
||||
count = Unread.posts.size
|
||||
countQuotingYou = Unread.postsQuotingYou.size
|
||||
|
||||
if Conf['Unread Count']
|
||||
d.title = "#{if count or !Conf['Hide Unread Count at (0)'] then "(#{count}) " else ''}#{if g.DEAD then Unread.title.replace '-', '- 404 -' else Unread.title}"
|
||||
titleQuotingYou = if Conf['Quoted Title'] and countQuotingYou then '(!) ' else ''
|
||||
titleCount = if count or !Conf['Hide Unread Count at (0)'] then "(#{count}) " else ''
|
||||
titleDead = if Unread.thread.isDead
|
||||
Unread.title.replace '-', (if Unread.thread.isArchived then '- Archived -' else '- 404 -')
|
||||
else
|
||||
Unread.title
|
||||
d.title = "#{titleQuotingYou}#{titleCount}#{titleDead}"
|
||||
|
||||
unless Unread.thread.isDead and !Unread.thread.isArchived
|
||||
ThreadWatcher.update Unread.thread.board.ID, Unread.thread.ID,
|
||||
isDead: Unread.thread.isDead
|
||||
unread: count
|
||||
quotingYou: countQuotingYou
|
||||
|
||||
return unless Conf['Unread Favicon']
|
||||
|
||||
Favicon.el.href =
|
||||
if g.DEAD
|
||||
if Unread.postsQuotingYou[0]
|
||||
if Unread.thread.isDead
|
||||
if countQuotingYou
|
||||
Favicon.unreadDeadY
|
||||
else if count
|
||||
Favicon.unreadDead
|
||||
@ -208,7 +241,7 @@ Unread =
|
||||
Favicon.dead
|
||||
else
|
||||
if count
|
||||
if Unread.postsQuotingYou[0]
|
||||
if countQuotingYou
|
||||
Favicon.unreadY
|
||||
else
|
||||
Favicon.unread
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user