]> git.wh0rd.org - tt-rss.git/blame - tt-rss.js
unify counter reply object handling when called from auto refetch and manually
[tt-rss.git] / tt-rss.js
CommitLineData
1cd17194 1var xmlhttp = false;
76798ff3 2var total_unread = 0;
525116d4 3var first_run = true;
8143ae1f 4var display_tags = false;
806a3d14 5var global_unread = -1;
21703604 6var active_title_text = "";
21703604 7var current_subtitle = "";
c6784aea 8var daemon_enabled = false;
0d51e25d 9var daemon_refresh_only = false;
15da5cc1 10var _qfd_deleted_feed = 0;
2bf6e0a8 11var firsttime_update = true;
c441662f 12var last_refetch = 0;
76b4eae1 13var cookie_lifetime = 0;
33d13e72 14var active_feed_id = 0;
0a6c4846 15var active_feed_is_cat = false;
9e397d0f 16var number_of_feeds = 0;
15da5cc1 17
a58069db 18var xmlhttp = Ajax.getTransport();
abbe0154 19var xmlhttp_ctr = Ajax.getTransport();
1cd17194 20
1035fcec 21var init_params = new Object();
3ac2b520 22
1dc8dba0
AD
23var op_history = new Array();
24
8143ae1f
AD
25function toggleTags() {
26 display_tags = !display_tags;
27
28 var p = document.getElementById("dispSwitchPrompt");
29
30 if (display_tags) {
31 p.innerHTML = "display feeds";
32 } else {
33 p.innerHTML = "display tags";
34 }
35
807f452a
AD
36 notify("Loading, please wait...");
37
8143ae1f
AD
38 updateFeedList();
39}
40
6de5d056 41function dlg_frefresh_callback() {
abbe0154 42 if (xmlhttp.readyState == 4) {
a58d997c 43// notify(xmlhttp.responseText);
abbe0154
AD
44
45 if (getActiveFeedId() == _qfd_deleted_feed) {
46 var h = document.getElementById("headlines-frame");
47 if (h) {
48 h.innerHTML = "<div class='whiteBox'>No feed selected.</div>";
49 }
50 }
51
0e9dd1ba 52 setTimeout('updateFeedList(false, false)', 50);
eff4997c 53 closeInfoBox();
c0e5a40e 54 }
1cd17194 55}
e2f8f7b4 56
8158c57a 57function refetch_callback() {
abbe0154 58 if (xmlhttp_ctr.readyState == 4) {
7719618b 59 try {
310da49d 60
c441662f
AD
61 var date = new Date();
62
63 last_refetch = date.getTime() / 1000;
64
5854573a 65 parse_counters_reply(xmlhttp_ctr);
71ad883b 66
0ee1d1a0
AD
67 debug("refetch_callback: done");
68
0d51e25d 69 if (!daemon_enabled && !daemon_refresh_only) {
c6784aea 70 notify("All feeds updated.");
5a180505 71 updateTitle("");
4c059b7b
AD
72 } else {
73 notify("");
c6784aea 74 }
7719618b
AD
75 } catch (e) {
76 exception_error("refetch_callback", e);
e2cb4c6d 77 updateTitle("");
7719618b 78 }
090e250b
AD
79 }
80}
1a66d16e 81
295f9b42
AD
82function backend_sanity_check_callback() {
83
84 if (xmlhttp.readyState == 4) {
295f9b42 85
7719618b
AD
86 try {
87
88 if (!xmlhttp.responseXML) {
462a192b 89 fatalError(3, "[D001, Received reply is not XML]: " + xmlhttp.responseText);
7719618b
AD
90 return;
91 }
295f9b42 92
3ac2b520 93 var reply = xmlhttp.responseXML.firstChild.firstChild;
7719618b
AD
94
95 if (!reply) {
af106b0e 96 fatalError(3, "[D002, Invalid RPC reply]: " + xmlhttp.responseText);
7719618b
AD
97 return;
98 }
99
100 var error_code = reply.getAttribute("error-code");
101
102 if (error_code && error_code != 0) {
af106b0e 103 return fatalError(error_code, reply.getAttribute("error-msg"));
7719618b
AD
104 }
105
0ee1d1a0
AD
106 debug("sanity check ok");
107
3ac2b520
AD
108 var params = reply.nextSibling;
109
110 if (params) {
111 debug('reading init-params...');
112 var param = params.firstChild;
113
114 while (param) {
115 var k = param.getAttribute("key");
116 var v = param.getAttribute("value");
117 debug(k + " => " + v);
118 init_params[k] = v;
119 param = param.nextSibling;
120 }
121 }
122
7719618b 123 init_second_stage();
295f9b42 124
7719618b
AD
125 } catch (e) {
126 exception_error("backend_sanity_check_callback", e);
127 }
295f9b42
AD
128 }
129}
130
cb246176 131function scheduleFeedUpdate(force) {
525116d4 132
0d51e25d 133 if (!daemon_enabled && !daemon_refresh_only) {
4d4200a8 134 notify("Updating feeds, please wait.", true);
c6784aea
AD
135 updateTitle("Updating");
136 }
55193822 137
cb246176
AD
138 var query_str = "backend.php?op=rpc&subop=";
139
140 if (force) {
c3b81db0 141 query_str = query_str + "forceUpdateAllFeeds";
cb246176 142 } else {
c3b81db0 143 query_str = query_str + "updateAllFeeds";
cb246176 144 }
525116d4 145
9826bd2e
AD
146 var omode;
147
b6104dee 148 if (firsttime_update && !navigator.userAgent.match("Opera")) {
2bf6e0a8
AD
149 firsttime_update = false;
150 omode = "T";
9826bd2e 151 } else {
2bf6e0a8
AD
152 if (display_tags) {
153 omode = "t";
154 } else {
155 omode = "flc";
156 }
9826bd2e 157 }
2bf6e0a8 158
9826bd2e 159 query_str = query_str + "&omode=" + omode;
78ea1de0 160 query_str = query_str + "&uctr=" + global_unread;
9826bd2e 161
0ee1d1a0 162 debug("in scheduleFeedUpdate");
2bf6e0a8 163
c441662f
AD
164 var date = new Date();
165
abbe0154 166 if (!xmlhttp_ready(xmlhttp_ctr) && last_refetch < date.getTime() / 1000 - 60) {
a7565293 167 debug("<b>xmlhttp seems to be stuck, aborting</b>");
abbe0154 168 xmlhttp_ctr.abort();
c441662f
AD
169 }
170
52db9978
AD
171 debug("REFETCH query: " + query_str);
172
abbe0154
AD
173 if (xmlhttp_ready(xmlhttp_ctr)) {
174 xmlhttp_ctr.open("GET", query_str, true);
175 xmlhttp_ctr.onreadystatechange=refetch_callback;
176 xmlhttp_ctr.send(null);
525116d4 177 } else {
abbe0154 178 debug("xmlhttp_ctr busy");
bed0f18f 179 //printLockingError();
c0e5a40e 180 }
525116d4 181}
1cd17194 182
525116d4 183function updateFeedList(silent, fetch) {
c0e5a40e 184
1a66d16e
AD
185// if (silent != true) {
186// notify("Loading feed list...");
187// }
82baad4a 188
331900c6
AD
189 var query_str = "backend.php?op=feeds";
190
8143ae1f
AD
191 if (display_tags) {
192 query_str = query_str + "&tags=1";
193 }
194
5c365f60 195 if (getActiveFeedId() && !activeFeedIsCat()) {
86741347 196 query_str = query_str + "&actid=" + getActiveFeedId();
175847de
AD
197 }
198
59b8192f
AD
199 if (navigator.userAgent.match("Opera")) {
200 var date = new Date();
201 var timestamp = Math.round(date.getTime() / 1000);
202 query_str = query_str + "&ts=" + timestamp
203 }
204
1a66d16e 205 if (fetch) query_str = query_str + "&fetch=yes";
e1123aee 206
6b4163cb
AD
207// var feeds_frame = document.getElementById("feeds-frame");
208// feeds_frame.src = query_str;
209
0e9dd1ba 210 debug("updateFeedList Q=" + query_str);
6b4163cb
AD
211
212 if (xmlhttp_ready(xmlhttp)) {
213 xmlhttp.open("GET", query_str, true);
214 xmlhttp.onreadystatechange=feedlist_callback;
215 xmlhttp.send(null);
216 } else {
217 debug("xmlhttp busy");
218 //printLockingError();
219 }
e1123aee 220
1a66d16e 221}
175847de 222
476cac42 223function catchupAllFeeds() {
076682aa 224
476cac42
AD
225 var query_str = "backend.php?op=feeds&subop=catchupAll";
226
227 notify("Marking all feeds as read...");
228
ca2f46a7 229 debug("catchupAllFeeds Q=" + query_str);
1a66d16e 230
ca2f46a7
AD
231 if (xmlhttp_ready(xmlhttp)) {
232 xmlhttp.open("GET", query_str, true);
233 xmlhttp.onreadystatechange=feedlist_callback;
234 xmlhttp.send(null);
235 } else {
236 debug("xmlhttp busy");
237 //printLockingError();
238 }
476cac42 239
fc69e641 240 global_unread = 0;
21703604 241 updateTitle("");
fc69e641 242
476cac42 243}
1cd17194 244
767e2486 245function viewCurrentFeed(subop) {
1a66d16e 246
ec6e2fd3
AD
247// if (getActiveFeedId()) {
248 if (getActiveFeedId() != undefined) {
767e2486 249 viewfeed(getActiveFeedId(), subop);
033e47e0
AD
250 } else {
251 disableContainerChildren("headlinesToolbar", false, document);
ec6e2fd3 252// viewfeed(-1, subop); // FIXME
f0601b87 253 }
164f4738 254 return false; // block unneeded form submits
f0601b87
AD
255}
256
767e2486 257function viewfeed(feed, subop) {
db8d6f67 258 var f = window.frames["feeds-frame"];
767e2486 259 f.viewfeed(feed, subop);
9cfc649a
AD
260}
261
40d13c28 262function timeout() {
05732aa0 263 scheduleFeedUpdate(false);
f5de0d8d 264
3ac2b520 265 var refresh_time = getInitParam("feeds_frame_refresh");
f5de0d8d 266
3ac2b520 267 if (!refresh_time) refresh_time = 600;
f5de0d8d
AD
268
269 setTimeout("timeout()", refresh_time*1000);
ac53063a
AD
270}
271
c374a3fe 272function resetSearch() {
64c620ce
AD
273 var searchbox = document.getElementById("searchbox")
274
86741347 275 if (searchbox.value != "" && getActiveFeedId()) {
64c620ce 276 searchbox.value = "";
767e2486 277 viewfeed(getActiveFeedId(), "");
ac43eba1 278 }
c374a3fe 279}
ac53063a 280
86b682ce
AD
281function searchCancel() {
282 closeInfoBox(true);
283}
284
f0601b87 285function search() {
eff4997c 286 closeInfoBox();
4ce19859 287 viewCurrentFeed(0, "");
76798ff3 288}
1cd17194 289
13ad9102
AD
290function localPiggieFunction(enable) {
291 if (enable) {
292 var query_str = "backend.php?op=feeds&subop=piggie";
293
c0e5a40e 294 if (xmlhttp_ready(xmlhttp)) {
13ad9102
AD
295
296 xmlhttp.open("GET", query_str, true);
297 xmlhttp.onreadystatechange=feedlist_callback;
298 xmlhttp.send(null);
299 }
300 }
301}
302
806a3d14
AD
303// if argument is undefined, current subtitle is not updated
304// use blank string to clear subtitle
fc69e641
AD
305function updateTitle(s) {
306 var tmp = "Tiny Tiny RSS";
21703604 307
5a494a0b 308 if (s != undefined) {
21703604
AD
309 current_subtitle = s;
310 }
311
fc69e641
AD
312 if (global_unread > 0) {
313 tmp = tmp + " (" + global_unread + ")";
314 }
315
5a494a0b 316 if (current_subtitle) {
21703604 317 tmp = tmp + " - " + current_subtitle;
fc69e641 318 }
21703604
AD
319
320 if (active_title_text.length > 0) {
321 tmp = tmp + " > " + active_title_text;
322 }
323
fc69e641
AD
324 document.title = tmp;
325}
326
22a93ad8 327function genericSanityCheck() {
ac43eba1 328
295f9b42
AD
329 if (!xmlhttp) fatalError(1);
330
331 setCookie("ttrss_vf_test", "TEST");
332
333 if (getCookie("ttrss_vf_test") != "TEST") {
334 fatalError(2);
335 }
336
22a93ad8
AD
337 return true;
338}
339
340function init() {
341
7719618b 342 try {
fe2f1970 343
97dcd654
AD
344 // this whole shebang is based on http://www.birnamdesigns.com/misc/busted2.html
345
346 if (arguments.callee.done) return;
347 arguments.callee.done = true;
348
7719618b 349 disableContainerChildren("headlinesToolbar", true);
70830c87 350
86b682ce
AD
351 Form.disable("main_toolbar_form");
352
7719618b
AD
353 if (!genericSanityCheck())
354 return;
ac43eba1 355
0ee1d1a0
AD
356 if (getURLParam('debug')) {
357 document.getElementById('debug_output').style.display = 'block';
358 debug('debug mode activated');
359 }
360
7719618b
AD
361 xmlhttp.open("GET", "backend.php?op=rpc&subop=sanityCheck", true);
362 xmlhttp.onreadystatechange=backend_sanity_check_callback;
363 xmlhttp.send(null);
47179952 364
7719618b
AD
365 } catch (e) {
366 exception_error("init", e);
a8d28f48 367 }
7719618b 368}
86741347 369
7719618b 370function init_second_stage() {
295f9b42 371
7719618b 372 try {
2f587484 373
76b4eae1
AD
374 cookie_lifetime = getCookie("ttrss_cltime");
375
376 delCookie("ttrss_vf_test");
7719618b 377
7719618b 378 document.onkeydown = hotkey_handler;
1b0809ae 379
f31673f7
AD
380 var tb = parent.document.forms["main_toolbar_form"];
381
9f10e152
AD
382// dropboxSelect(tb.view_mode, getInitParam("toolbar_view_mode"));
383// dropboxSelect(tb.limit, getInitParam("toolbar_limit"));
c6784aea 384
0d51e25d
AD
385 daemon_enabled = getInitParam("daemon_enabled") == 1;
386 daemon_refresh_only = getInitParam("daemon_refresh_only") == 1;
5f136c9a 387
0e9dd1ba 388 setTimeout('updateFeedList(false, false)', 50);
0ee1d1a0
AD
389
390 debug("second stage ok");
7719618b 391
7719618b
AD
392 } catch (e) {
393 exception_error("init_second_stage", e);
2f587484 394 }
1cd17194 395}
ac43eba1 396
c09ec856 397function quickMenuChange() {
cbe45fa8 398 var chooser = document.getElementById("quickMenuChooser");
86b682ce 399 var opid = chooser[chooser.selectedIndex].value;
e2f8f7b4 400
c09ec856
AD
401 chooser.selectedIndex = 0;
402 quickMenuGo(opid);
403}
404
405function quickMenuGo(opid) {
bb3423cf 406 try {
c09ec856 407
bb3423cf
AD
408 if (opid == "qmcPrefs") {
409 gotoPreferences();
410 }
411
412 if (opid == "qmcSearch") {
0a6c4846 413 displayDlg("search", getActiveFeedId() + ":" + activeFeedIsCat());
6de5d056
AD
414 return;
415 }
bb3423cf
AD
416
417 if (opid == "qmcAddFeed") {
418 displayDlg("quickAddFeed");
419 return;
69668465 420 }
7086277c
AD
421
422 if (opid == "qmcEditFeed") {
423 editFeedDlg(getActiveFeedId());
424 }
6de5d056 425
bb3423cf
AD
426 if (opid == "qmcRemoveFeed") {
427 var actid = getActiveFeedId();
428
5c365f60 429 if (!actid || activeFeedIsCat()) {
0530ddd8 430 alert("Please select some feed first.");
bb3423cf
AD
431 return;
432 }
64a2875d
AD
433
434 var fn = getFeedName(actid);
bb3423cf 435
64a2875d 436 if (confirm("Unsubscribe from " + fn + "?")) {
bb3423cf
AD
437 qfdDelete(actid);
438 }
439
440 return;
441 }
442
443 if (opid == "qmcUpdateFeeds") {
444 scheduleFeedUpdate(true);
445 return;
446 }
447
448 if (opid == "qmcCatchupAll") {
449 catchupAllFeeds();
450 return;
451 }
452
453 if (opid == "qmcShowOnlyUnread") {
454 toggleDispRead();
455 return;
456 }
457
458 if (opid == "qmcAddFilter") {
459 displayDlg("quickAddFilter", getActiveFeedId());
460 }
461 } catch (e) {
462 exception_error("quickMenuGo", e);
a24f525c 463 }
e2f8f7b4
AD
464}
465
6de5d056
AD
466function qfdDelete(feed_id) {
467
468 notify("Removing feed...");
469
7f123cda
AD
470 if (!xmlhttp_ready(xmlhttp)) {
471 printLockingError();
472 return
473 }
474
15da5cc1
AD
475 _qfd_deleted_feed = feed_id;
476
69668465 477 xmlhttp.open("GET", "backend.php?op=pref-feeds&quiet=1&subop=remove&ids=" + feed_id);
6de5d056
AD
478 xmlhttp.onreadystatechange=dlg_frefresh_callback;
479 xmlhttp.send(null);
7bc4f251
AD
480
481 return false;
6de5d056 482}
033e47e0 483
3745788e 484
21703604
AD
485function updateFeedTitle(t) {
486 active_title_text = t;
487 updateTitle();
488}
489
3745788e 490function toggleDispRead() {
7f123cda 491 try {
3745788e 492
7f123cda
AD
493 if (!xmlhttp_ready(xmlhttp)) {
494 printLockingError();
495 return
496 }
3745788e 497
e8bd0da9 498 var hide_read_feeds = (getInitParam("hide_read_feeds") == "1");
3745788e 499
7f123cda 500 hide_read_feeds = !hide_read_feeds;
e8bd0da9
AD
501
502 debug("toggle_disp_read => " + hide_read_feeds);
503
504 hideOrShowFeeds(getFeedsContext().document, hide_read_feeds);
505
7f123cda
AD
506 var query = "backend.php?op=rpc&subop=setpref" +
507 "&key=HIDE_READ_FEEDS&value=" + param_escape(hide_read_feeds);
3745788e 508
e8bd0da9
AD
509 storeInitParam("hide_read_feeds", hide_read_feeds, true);
510
511 new Ajax.Request(query);
7f123cda
AD
512
513 } catch (e) {
514 exception_error("toggleDispRead", e);
3745788e 515 }
3745788e 516}
295f9b42 517
71ad883b 518function parse_runtime_info(elem) {
4724a093
AD
519 if (!elem) {
520 debug("parse_runtime_info: elem is null, aborting");
521 return;
522 }
523
71ad883b
AD
524 var param = elem.firstChild;
525
52db9978 526 debug("parse_runtime_info: " + param);
1cb7492d 527
71ad883b
AD
528 while (param) {
529 var k = param.getAttribute("key");
530 var v = param.getAttribute("value");
3ac2b520 531
1cb7492d
AD
532 debug("RI: " + k + " => " + v);
533
71ad883b
AD
534 var w = document.getElementById("noDaemonWarning");
535
536 if (w) {
537 if (k == "daemon_is_running" && v != 1) {
538 w.style.display = "block";
539 } else {
540 w.style.display = "none";
541 }
542 }
543 param = param.nextSibling;
544 }
545}
fce24838
AD
546
547function catchupCurrentFeed() {
548
234e467c 549 var fn = getFeedName(getActiveFeedId(), active_feed_is_cat);
fce24838 550
234e467c
AD
551 var str = "Mark all articles in " + fn + " as read?";
552
553/* if (active_feed_is_cat) {
554 str = "Mark all articles in this category as read?";
555 } */
556
f6d6e22f 557 if (getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
28de3732 558 return viewCurrentFeed('MarkAllRead')
fce24838
AD
559 }
560}
88040f57 561
461766f3
AD
562function userSwitch() {
563 var chooser = document.getElementById("userSwitch");
564 var user = chooser[chooser.selectedIndex].value;
565 window.location = "tt-rss.php?swu=" + user;
566}
6e6504bc 567
7086277c
AD
568function editFeedDlg(feed) {
569
729bafaa
AD
570 disableHotkeys();
571
7086277c
AD
572 if (!feed) {
573 alert("Please select some feed first.");
574 return;
575 }
576
577 if (xmlhttp_ready(xmlhttp)) {
578 xmlhttp.open("GET", "backend.php?op=pref-feeds&subop=editfeed&id=" +
579 param_escape(feed), true);
580 xmlhttp.onreadystatechange=infobox_callback;
581 xmlhttp.send(null);
582 } else {
583 printLockingError();
584 }
585}
586
587/* this functions duplicate those of prefs.js feed editor, with
588 some differences because there is no feedlist */
589
590function feedEditCancel() {
591 closeInfoBox();
592 return false;
593}
594
595function feedEditSave() {
596
597 try {
598
599 if (!xmlhttp_ready(xmlhttp)) {
600 printLockingError();
601 return
602 }
603
604 // FIXME: add parameter validation
605
606 var query = Form.serialize("edit_feed_form");
607
608 notify("Saving feed...");
609
610 xmlhttp.open("POST", "backend.php", true);
611 xmlhttp.onreadystatechange=dlg_frefresh_callback;
612 xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
613 xmlhttp.send(query);
614
615 closeInfoBox();
616
617 return false;
618
619 } catch (e) {
620 exception_error("feedEditSave (main)", e);
621 }
622}
6e6504bc 623
1dc8dba0
AD
624function localHotkeyHandler(e) {
625
626 var keycode;
627
628 if (window.event) {
629 keycode = window.event.keyCode;
630 } else if (e) {
631 keycode = e.which;
632 }
633
634 var shift_key = false;
635
636 try {
637 shift_key = e.shiftKey;
638 } catch (e) { }
639
640 if (keycode == 66 && shift_key) { // shift-B
641
642 var op = history_pop();
643
644 if (op) {
645 var op_s = op.split(":");
646
647 var i;
648 for (i = 0; i < op_s.length; i++) {
649 if (op_s[i] == 'undefined') {
650 op_s[i] = undefined;
651 }
652
653 if (op_s[i] == 'false') {
654 op_s[i] = false;
655 }
656
657 if (op_s[i] == 'true') {
658 op_s[i] = true;
659 }
660
661 }
662
663 debug("history split: " + op_s);
664
665 if (op_s[0] == "ARTICLE") {
666 debug("history: reverting to article " + op_s[1] + "/" + op_s[2]);
667 view(op_s[1], op_s[2], true);
668 }
669
670 if (op_s[0] == "FEED") {
671 viewfeed(op_s[1], op_s[2], op_s[3], op_s[4], true);
672 }
673
674 } else {
675 notify("No operation to undo");
676 }
677
678 return false;
679
680 }
681
682 debug("LKP=" + keycode);
683}
684
685function history_push(op) {
686 debug("history_push: " + op);
687 op_history.push(op);
688
689 while (op_history.length > 30) {
690 op_history.shift();
691 }
692}
693
694function history_pop() {
695 var op = op_history.pop();
696 debug("history_pop: " + op);
697 return op;
698}
699
700function history_clear() {
701 debug("history_clear");
702 op_history.clear();
703}