mirror of
https://github.com/vichan-devel/vichan.git
synced 2024-11-30 18:24:29 +01:00
watch.js: watch board + watch thread + tool for pinning boards; currently may not work the best at mobiles and without compact-boardlist
This commit is contained in:
parent
2664a84974
commit
371685140a
@ -9,10 +9,13 @@
|
|||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* $config['additional_javascript'][] = 'js/jquery.min.js';
|
* $config['additional_javascript'][] = 'js/jquery.min.js';
|
||||||
|
* //$config['additional_javascript'][] = 'js/titlebar-notifications.js';
|
||||||
* $config['additional_javascript'][] = 'js/auto-reload.js';
|
* $config['additional_javascript'][] = 'js/auto-reload.js';
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
auto_reload_enabled = true; // for watch.js to interop
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
if($('div.banner').length == 0)
|
if($('div.banner').length == 0)
|
||||||
return; // not index
|
return; // not index
|
||||||
@ -24,12 +27,17 @@ $(document).ready(function(){
|
|||||||
|
|
||||||
var end_of_page = false;
|
var end_of_page = false;
|
||||||
|
|
||||||
var orig_title = document.title;
|
|
||||||
var new_posts = 0;
|
var new_posts = 0;
|
||||||
var first_new_post = null;
|
var first_new_post = null;
|
||||||
var update_title = function() {
|
|
||||||
document.title = (new_posts ? "("+new_posts+") " : "") + orig_title;
|
if (typeof update_title == "undefined") {
|
||||||
};
|
var update_title = function() { };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof add_title_collector != "undefined")
|
||||||
|
add_title_collector(function(){
|
||||||
|
return new_posts;
|
||||||
|
});
|
||||||
|
|
||||||
var window_active = true;
|
var window_active = true;
|
||||||
$(window).focus(function() {
|
$(window).focus(function() {
|
||||||
@ -66,6 +74,7 @@ $(document).ready(function(){
|
|||||||
recheck_activated();
|
recheck_activated();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
time_loaded = Date.now(); // interop with watch.js
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
18
js/titlebar-notifications.js
Normal file
18
js/titlebar-notifications.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
var orig_title = document.title;
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
orig_title = document.title;
|
||||||
|
});
|
||||||
|
|
||||||
|
update_title = function() {
|
||||||
|
var updates = 0;
|
||||||
|
for(var i in title_collectors) {
|
||||||
|
updates += title_collectors[i]();
|
||||||
|
}
|
||||||
|
document.title = (updates ? "("+updates+") " : "") + orig_title;
|
||||||
|
};
|
||||||
|
|
||||||
|
var title_collectors = [];
|
||||||
|
add_title_collector = function(f) {
|
||||||
|
title_collectors.push(f);
|
||||||
|
};
|
334
js/watch.js
Normal file
334
js/watch.js
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
$(function(){
|
||||||
|
var status = {};
|
||||||
|
|
||||||
|
time_loaded = Date.now();
|
||||||
|
|
||||||
|
var updating_suspended = false;
|
||||||
|
|
||||||
|
var storage = function() {
|
||||||
|
return JSON.parse(localStorage.watch !== undefined ? localStorage.watch : "{}");
|
||||||
|
};
|
||||||
|
|
||||||
|
var storage_save = function(s) {
|
||||||
|
localStorage.watch = JSON.stringify(s);
|
||||||
|
};
|
||||||
|
|
||||||
|
var osize = function(o) {
|
||||||
|
var size = 0;
|
||||||
|
for (var key in o) {
|
||||||
|
if (o.hasOwnProperty(key)) size++;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
};
|
||||||
|
|
||||||
|
var is_pinned = function(boardconfig) {
|
||||||
|
return boardconfig.pinned || boardconfig.watched || (boardconfig.threads ? osize(boardconfig.threads) : false);
|
||||||
|
};
|
||||||
|
var is_boardwatched = function(boardconfig) {
|
||||||
|
return boardconfig.watched;
|
||||||
|
};
|
||||||
|
var is_threadwatched = function(boardconfig, thread) {
|
||||||
|
return boardconfig && boardconfig.threads && boardconfig.threads[thread];
|
||||||
|
};
|
||||||
|
var toggle_pinned = function(board) {
|
||||||
|
var st = storage();
|
||||||
|
var bc = st[board] || {};
|
||||||
|
if (is_pinned(bc)) {
|
||||||
|
bc.pinned = false;
|
||||||
|
bc.watched = false;
|
||||||
|
bc.threads = {};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bc.pinned = true;
|
||||||
|
}
|
||||||
|
st[board] = bc;
|
||||||
|
storage_save(st);
|
||||||
|
return bc.pinned;
|
||||||
|
};
|
||||||
|
var toggle_boardwatched = function(board) {
|
||||||
|
var st = storage();
|
||||||
|
var bc = st[board] || {};
|
||||||
|
bc.watched = !is_boardwatched(bc) && Date.now();
|
||||||
|
st[board] = bc;
|
||||||
|
storage_save(st);
|
||||||
|
return bc.watched;
|
||||||
|
};
|
||||||
|
var toggle_threadwatched = function(board, thread) {
|
||||||
|
var st = storage();
|
||||||
|
var bc = st[board] || {};
|
||||||
|
if (is_threadwatched(bc, thread)) {
|
||||||
|
delete bc.threads[thread];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bc.threads = bc.threads || {};
|
||||||
|
bc.threads[thread] = Date.now();
|
||||||
|
}
|
||||||
|
st[board] = bc;
|
||||||
|
storage_save(st);
|
||||||
|
return is_threadwatched(bc, thread);
|
||||||
|
};
|
||||||
|
var update_pinned = function() {
|
||||||
|
if (typeof update_title != "undefined") update_title();
|
||||||
|
|
||||||
|
var bl = $('.boardlist').first();
|
||||||
|
$('#watch-pinned').remove();
|
||||||
|
var pinned = $('<div id="watch-pinned"></div>').css('display', 'inline-block').css('vertical-align', 'middle').appendTo(bl);
|
||||||
|
|
||||||
|
var st = storage();
|
||||||
|
for (var i in st) {
|
||||||
|
if (is_pinned(st[i])) {
|
||||||
|
var link;
|
||||||
|
if (bl.find('[href*="/'+i+'/"]:not(.cb-menuitem)').length) link = bl.find('[href*="/'+i+'/"]').first();
|
||||||
|
|
||||||
|
// TODO: fix path
|
||||||
|
else link = $('<a href="/'+i+'/" class="cb-item cb-cat">/'+i+'/</a>').appendTo(pinned);
|
||||||
|
|
||||||
|
if (link[0].origtitle === undefined) {
|
||||||
|
link[0].origtitle = link.html();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
link.html(link[0].origtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st[i].watched) {
|
||||||
|
link.css("font-weight", "bold");
|
||||||
|
if (status && status[i] && status[i].new_threads) {
|
||||||
|
link.html(link.html() + " (" + status[i].new_threads + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (st[i].threads && osize(st[i].threads)) {
|
||||||
|
link.css("font-style", "italic");
|
||||||
|
|
||||||
|
link.attr("data-board", i);
|
||||||
|
|
||||||
|
if (status && status[i] && status[i].threads) {
|
||||||
|
var new_posts = 0;
|
||||||
|
for (var tid in status[i].threads) {
|
||||||
|
if (status[i].threads[tid] > 0) {
|
||||||
|
new_posts += status[i].threads[tid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (new_posts > 0) {
|
||||||
|
link.html(link.html() + " (" + new_posts + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
link.mouseenter(function() {
|
||||||
|
updating_suspended = true;
|
||||||
|
|
||||||
|
var list = $("<div class='boardlist top cb-menu'></div>")
|
||||||
|
.css("top", $(this).position().top + 13 + $(this).height())
|
||||||
|
.css("left", $(this).position().left)
|
||||||
|
.css("right", "auto")
|
||||||
|
.appendTo($(this));
|
||||||
|
var board = $(this).attr("data-board");
|
||||||
|
|
||||||
|
for (var tid in storage()[board].threads) {
|
||||||
|
// TODO: fix path
|
||||||
|
var newposts = "(0)";
|
||||||
|
if (status && status[board] && status[board].threads && status[board].threads[tid]) {
|
||||||
|
if (status[board].threads[tid] == -404) {
|
||||||
|
newposts = "<i class='icon icon-ban-circle'></i>";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newposts = "("+status[board].threads[tid]+")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tag = $("<a href='/"+board+"/res/"+tid+".html'><span>#"+tid+"</span><span class='cb-uri'>"+newposts+"</span>");
|
||||||
|
|
||||||
|
tag
|
||||||
|
.attr('data-thread', tid)
|
||||||
|
.addClass("cb-menuitem")
|
||||||
|
.appendTo(list)
|
||||||
|
.find(".cb-uri").mouseenter(function() {
|
||||||
|
this.oldval = $(this).html();
|
||||||
|
$(this).css("min-width", $(this).width());
|
||||||
|
$(this).html("<i class='icon icon-minus'></i>");
|
||||||
|
})
|
||||||
|
.mouseleave(function() {
|
||||||
|
$(this).html(this.oldval);
|
||||||
|
})
|
||||||
|
.click(function() {
|
||||||
|
var b = $(this).parent().parent().parent().attr("data-board");
|
||||||
|
var t = $(this).parent().attr("data-thread");
|
||||||
|
toggle_threadwatched(b, t);
|
||||||
|
$(this).parent().parent().parent().mouseleave();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}).mouseleave(function() {
|
||||||
|
updating_suspended = false;
|
||||||
|
$('.boardlist .cb-menu').remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var fetch_jsons = function() {
|
||||||
|
if (updating_suspended) return;
|
||||||
|
|
||||||
|
var st = storage();
|
||||||
|
for (var i in st) {
|
||||||
|
if (st[i].watched) {
|
||||||
|
// TODO: fix path
|
||||||
|
var r = $.getJSON("/"+i+"/threads.json", {nocache: Math.random()}, function(j, x, r) {
|
||||||
|
handle_board_json(r.board, j);
|
||||||
|
});
|
||||||
|
r.board = i;
|
||||||
|
}
|
||||||
|
else if (st[i].threads) {
|
||||||
|
for (var j in st[i].threads) {
|
||||||
|
var r = $.getJSON("/"+i+"/res/"+j+".json", {nocache: Math.random()}, function(k, x, r) {
|
||||||
|
handle_thread_json(r.board, r.thread, k);
|
||||||
|
}).error(function(r) {
|
||||||
|
if(r.status == 404) handle_thread_404(r.board, r.thread);
|
||||||
|
});
|
||||||
|
|
||||||
|
r.board = i;
|
||||||
|
r.thread = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var handle_board_json = function(board, json) {
|
||||||
|
var last_thread;
|
||||||
|
|
||||||
|
var new_threads = 0;
|
||||||
|
|
||||||
|
for (var i in json) {
|
||||||
|
for (var j in json[i].threads) {
|
||||||
|
var thread = json[i].threads[j];
|
||||||
|
|
||||||
|
if (thread.last_modified > storage()[board].watched / 1000) {
|
||||||
|
last_thread = thread.no;
|
||||||
|
|
||||||
|
new_threads++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = status || {};
|
||||||
|
status[board] = status[board] || {};
|
||||||
|
status[board].last_thread = last_thread;
|
||||||
|
status[board].new_threads = new_threads;
|
||||||
|
update_pinned();
|
||||||
|
};
|
||||||
|
var handle_thread_json = function(board, threadid, json) {
|
||||||
|
for (var i in json.posts) {
|
||||||
|
var post = json.posts[i];
|
||||||
|
|
||||||
|
var new_posts = 0;
|
||||||
|
if (post.time > storage()[board].threads[threadid] / 1000) {
|
||||||
|
new_posts++;
|
||||||
|
}
|
||||||
|
status = status || {};
|
||||||
|
status[board] = status[board] || {};
|
||||||
|
status[board].threads = status[board].threads || {};
|
||||||
|
status[board].threads[threadid] = new_posts;
|
||||||
|
update_pinned();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var handle_thread_404 = function(board, threadid) {
|
||||||
|
status = status || {};
|
||||||
|
status[board] = status[board] || {};
|
||||||
|
status[board].threads = status[board].threads || {};
|
||||||
|
status[board].threads[threadid] = -404; //notify 404
|
||||||
|
update_pinned();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (active_page == "thread") {
|
||||||
|
var board = $('form[name="post"] input[name="board"]').val();
|
||||||
|
var thread = $('form[name="post"] input[name="thread"]').val();
|
||||||
|
|
||||||
|
var boardconfig = storage()[board] || {};
|
||||||
|
|
||||||
|
$('hr:first').before('<div id="watch-thread" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>');
|
||||||
|
$('#watch-thread a').html(is_threadwatched(boardconfig, thread) ? _("Stop watching this thread") : _("Watch this thread")).click(function() {
|
||||||
|
$(this).html(toggle_threadwatched(board, thread) ? _("Stop watching this thread") : _("Watch this thread"));
|
||||||
|
update_pinned();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (active_page == "index") {
|
||||||
|
var board = $('form[name="post"] input[name="board"]').val();
|
||||||
|
|
||||||
|
var boardconfig = storage()[board] || {};
|
||||||
|
|
||||||
|
$('hr:first').before('<div id="watch-pin" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>');
|
||||||
|
$('#watch-pin a').html(is_pinned(boardconfig) ? _("Unpin this board") : _("Pin this board")).click(function() {
|
||||||
|
$(this).html(toggle_pinned(board) ? _("Unpin this board") : _("Pin this board"));
|
||||||
|
update_pinned();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('hr:first').before('<div id="watch-board" style="text-align:right"><a class="unimportant" href="javascript:void(0)">-</a></div>');
|
||||||
|
$('#watch-board a').html(is_boardwatched(boardconfig) ? _("Stop watching this board") : _("Watch this board")).click(function() {
|
||||||
|
$(this).html(toggle_boardwatched(board) ? _("Stop watching this board") : _("Watch this board"));
|
||||||
|
$('#watch-pin a').html(is_pinned(board) ? _("Unpin this board") : _("Pin this board"));
|
||||||
|
update_pinned();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var check_post = function(frame, post) {
|
||||||
|
return post.length && $(frame).scrollTop() + $(frame).height() >=
|
||||||
|
post.position().top + post.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(window).scroll(function() {
|
||||||
|
if (!status) return;
|
||||||
|
var refresh = false;
|
||||||
|
for(var bid in status) {
|
||||||
|
if (status[bid].new_threads && (active_page == "ukko" || active_page == "index")
|
||||||
|
&& check_post(this, $('[data-board="'+bid+'"]#thread_'+status[bid].last_thread))) {
|
||||||
|
var st = storage()
|
||||||
|
st[bid].watched = time_loaded;
|
||||||
|
storage_save(st);
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
|
if (!status[bid].threads) continue;
|
||||||
|
|
||||||
|
for (var tid in status[bid].threads) {
|
||||||
|
if(status[bid].threads[tid] && check_post(this, $('[data-board="'+bid+'"]#thread_'+tid))) {
|
||||||
|
var st = storage();
|
||||||
|
st[bid].threads[tid] = time_loaded;
|
||||||
|
storage_save(st);
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (refresh) {
|
||||||
|
fetch_jsons();
|
||||||
|
refresh = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof add_title_collector != "undefined")
|
||||||
|
add_title_collector(function() {
|
||||||
|
if (!status) return 0;
|
||||||
|
var sum = 0;
|
||||||
|
for (var bid in status) {
|
||||||
|
if (status[bid].new_threads) {
|
||||||
|
sum += status[bid].new_threads;
|
||||||
|
if (!status[bid].threads) continue;
|
||||||
|
for (var tid in status[bid].threads) {
|
||||||
|
if (status[bid].threads[tid] > 0) {
|
||||||
|
if (auto_reload_enabled && active_page == "thread") {
|
||||||
|
var board = $('form[name="post"] input[name="board"]').val();
|
||||||
|
var thread = $('form[name="post"] input[name="thread"]').val();
|
||||||
|
|
||||||
|
if (board == bid && thread == tid) continue;
|
||||||
|
}
|
||||||
|
sum += status[bid].threads[tid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
});
|
||||||
|
|
||||||
|
update_pinned();
|
||||||
|
fetch_jsons();
|
||||||
|
setInterval(fetch_jsons, 10000);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user