]> git.wh0rd.org - tt-rss.git/blob - js/tt-rss.js
update dojo to 1.7.3
[tt-rss.git] / js / tt-rss.js
1 var total_unread = 0;
2 var global_unread = -1;
3 var firsttime_update = true;
4 var _active_feed_id = 0;
5 var _active_feed_is_cat = false;
6 var hotkey_prefix = false;
7 var hotkey_prefix_pressed = false;
8 var _force_scheduled_update = false;
9 var last_scheduled_update = false;
10
11 var _rpc_seq = 0;
12
13 function next_seq() {
14 _rpc_seq += 1;
15 return _rpc_seq;
16 }
17
18 function get_seq() {
19 return _rpc_seq;
20 }
21
22 function activeFeedIsCat() {
23 return _active_feed_is_cat;
24 }
25
26 function getActiveFeedId() {
27 try {
28 //console.log("gAFID: " + _active_feed_id);
29 return _active_feed_id;
30 } catch (e) {
31 exception_error("getActiveFeedId", e);
32 }
33 }
34
35 function setActiveFeedId(id, is_cat) {
36 try {
37 _active_feed_id = id;
38
39 if (is_cat != undefined) {
40 _active_feed_is_cat = is_cat;
41 }
42
43 selectFeed(id, is_cat);
44
45 dijit.byId("include_children").attr("disabled", !(is_cat && id > 0));
46
47
48 } catch (e) {
49 exception_error("setActiveFeedId", e);
50 }
51 }
52
53
54 function updateFeedList() {
55 try {
56
57 // $("feeds-holder").innerHTML = "<div id=\"feedlistLoading\">" +
58 // __("Loading, please wait...") + "</div>";
59
60 Element.show("feedlistLoading");
61
62 if (dijit.byId("feedTree")) {
63 dijit.byId("feedTree").destroyRecursive();
64 }
65
66 var store = new dojo.data.ItemFileWriteStore({
67 url: "backend.php?op=pref_feeds&method=getfeedtree&mode=2"});
68
69 var treeModel = new fox.FeedStoreModel({
70 store: store,
71 query: {
72 "type": getInitParam('enable_feed_cats') == 1 ? "category" : "feed"
73 },
74 rootId: "root",
75 rootLabel: "Feeds",
76 childrenAttrs: ["items"]
77 });
78
79 var tree = new fox.FeedTree({
80 persist: false,
81 model: treeModel,
82 onOpen: function (item, node) {
83 var id = String(item.id);
84 var cat_id = id.substr(id.indexOf(":")+1);
85
86 new Ajax.Request("backend.php",
87 { parameters: "backend.php?op=feeds&method=collapse&cid=" +
88 param_escape(cat_id) + "&mode=0" } );
89 },
90 onClose: function (item, node) {
91 var id = String(item.id);
92 var cat_id = id.substr(id.indexOf(":")+1);
93
94 new Ajax.Request("backend.php",
95 { parameters: "backend.php?op=feeds&method=collapse&cid=" +
96 param_escape(cat_id) + "&mode=1" } );
97
98 },
99 onClick: function (item, node) {
100 var id = String(item.id);
101 var is_cat = id.match("^CAT:");
102 var feed = id.substr(id.indexOf(":")+1);
103 viewfeed(feed, '', is_cat);
104 return false;
105 },
106 openOnClick: false,
107 showRoot: false,
108 id: "feedTree",
109 }, "feedTree");
110
111 _force_scheduled_update = true;
112
113 /* var menu = new dijit.Menu({id: 'feedMenu'});
114
115 menu.addChild(new dijit.MenuItem({
116 label: "Simple menu item"
117 }));
118
119 // menu.bindDomNode(tree.domNode); */
120
121 var tmph = dojo.connect(dijit.byId('feedMenu'), '_openMyself', function (event) {
122 console.log(dijit.getEnclosingWidget(event.target));
123 dojo.disconnect(tmph);
124 });
125
126 $("feeds-holder").appendChild(tree.domNode);
127
128 var tmph = dojo.connect(tree, 'onLoad', function() {
129 dojo.disconnect(tmph);
130 Element.hide("feedlistLoading");
131
132 tree.collapseHiddenCats();
133
134 feedlist_init();
135
136 // var node = dijit.byId("feedTree")._itemNodesMap['FEED:-2'][0].domNode
137 // menu.bindDomNode(node);
138
139 loading_set_progress(25);
140 });
141
142 tree.startup();
143
144 } catch (e) {
145 exception_error("updateFeedList", e);
146 }
147 }
148
149 function catchupAllFeeds() {
150
151 var str = __("Mark all articles as read?");
152
153 if (getInitParam("confirm_feed_catchup") != 1 || confirm(str)) {
154
155 var query_str = "backend.php?op=feeds&method=catchupAll";
156
157 notify_progress("Marking all feeds as read...");
158
159 //console.log("catchupAllFeeds Q=" + query_str);
160
161 new Ajax.Request("backend.php", {
162 parameters: query_str,
163 onComplete: function(transport) {
164 feedlist_callback2(transport);
165 } });
166
167 global_unread = 0;
168 updateTitle("");
169 }
170 }
171
172 function viewCurrentFeed(method) {
173
174 if (getActiveFeedId() != undefined) {
175 viewfeed(getActiveFeedId(), method, activeFeedIsCat());
176 }
177 return false; // block unneeded form submits
178 }
179
180 function timeout() {
181 if (getInitParam("bw_limit") == "1") return;
182
183 try {
184 var date = new Date();
185 var ts = Math.round(date.getTime() / 1000);
186
187 if (ts - last_scheduled_update > 10 || _force_scheduled_update) {
188
189 //console.log("timeout()");
190
191 window.clearTimeout(counter_timeout_id);
192
193 var query_str = "?op=rpc&method=getAllCounters&seq=" + next_seq();
194
195 var omode;
196
197 if (firsttime_update && !navigator.userAgent.match("Opera")) {
198 firsttime_update = false;
199 omode = "T";
200 } else {
201 omode = "flc";
202 }
203
204 query_str = query_str + "&omode=" + omode;
205
206 if (!_force_scheduled_update)
207 query_str = query_str + "&last_article_id=" + getInitParam("last_article_id");
208
209 //console.log("[timeout]" + query_str);
210
211 new Ajax.Request("backend.php", {
212 parameters: query_str,
213 onComplete: function(transport) {
214 handle_rpc_json(transport, !_force_scheduled_update);
215 _force_scheduled_update = false;
216 } });
217
218 last_scheduled_update = ts;
219 }
220
221 } catch (e) {
222 exception_error("timeout", e);
223 }
224
225 setTimeout("timeout()", 3000);
226 }
227
228 function search() {
229 var query = "backend.php?op=dlg&method=search&param=" +
230 param_escape(getActiveFeedId() + ":" + activeFeedIsCat());
231
232 if (dijit.byId("searchDlg"))
233 dijit.byId("searchDlg").destroyRecursive();
234
235 dialog = new dijit.Dialog({
236 id: "searchDlg",
237 title: __("Search"),
238 style: "width: 600px",
239 execute: function() {
240 if (this.validate()) {
241 _search_query = dojo.objectToQuery(this.attr('value'));
242 this.hide();
243 viewCurrentFeed();
244 }
245 },
246 href: query});
247
248 dialog.show();
249 }
250
251 function updateTitle() {
252 var tmp = "Tiny Tiny RSS";
253
254 if (global_unread > 0) {
255 tmp = tmp + " (" + global_unread + ")";
256 }
257
258 if (window.fluid) {
259 if (global_unread > 0) {
260 window.fluid.dockBadge = global_unread;
261 } else {
262 window.fluid.dockBadge = "";
263 }
264 }
265
266 document.title = tmp;
267 }
268
269 function genericSanityCheck() {
270 setCookie("ttrss_test", "TEST");
271
272 if (getCookie("ttrss_test") != "TEST") {
273 return fatalError(2);
274 }
275
276 return true;
277 }
278
279 function init() {
280 try {
281 //dojo.registerModulePath("fox", "../../js/");
282
283 dojo.require("fox.FeedTree");
284
285 if (typeof themeBeforeLayout == 'function') {
286 themeBeforeLayout();
287 }
288
289 dojo.require("dijit.ColorPalette");
290 dojo.require("dijit.Dialog");
291 dojo.require("dijit.form.Button");
292 dojo.require("dijit.form.CheckBox");
293 dojo.require("dijit.form.DropDownButton");
294 dojo.require("dijit.form.FilteringSelect");
295 dojo.require("dijit.form.Form");
296 dojo.require("dijit.form.RadioButton");
297 dojo.require("dijit.form.Select");
298 dojo.require("dijit.form.SimpleTextarea");
299 dojo.require("dijit.form.TextBox");
300 dojo.require("dijit.form.ValidationTextBox");
301 dojo.require("dijit.InlineEditBox");
302 dojo.require("dijit.layout.AccordionContainer");
303 dojo.require("dijit.layout.BorderContainer");
304 dojo.require("dijit.layout.ContentPane");
305 dojo.require("dijit.layout.TabContainer");
306 dojo.require("dijit.Menu");
307 dojo.require("dijit.ProgressBar");
308 dojo.require("dijit.ProgressBar");
309 dojo.require("dijit.Toolbar");
310 dojo.require("dijit.Tree");
311 dojo.require("dijit.tree.dndSource");
312 dojo.require("dojo.data.ItemFileWriteStore");
313
314 dojo.parser.parse();
315
316 if (!genericSanityCheck())
317 return false;
318
319 loading_set_progress(20);
320
321 var hasAudio = !!((myAudioTag = document.createElement('audio')).canPlayType);
322
323 new Ajax.Request("backend.php", {
324 parameters: {op: "rpc", method: "sanityCheck", hasAudio: hasAudio},
325 onComplete: function(transport) {
326 backend_sanity_check_callback(transport);
327 } });
328
329 } catch (e) {
330 exception_error("init", e);
331 }
332 }
333
334 function init_second_stage() {
335
336 try {
337 dojo.addOnLoad(function() {
338 updateFeedList();
339 closeArticlePanel();
340
341 if (typeof themeAfterLayout == 'function') {
342 themeAfterLayout();
343 }
344
345 });
346
347 delCookie("ttrss_test");
348
349 var toolbar = document.forms["main_toolbar_form"];
350
351 dijit.getEnclosingWidget(toolbar.view_mode).attr('value',
352 getInitParam("default_view_mode"));
353
354 dijit.getEnclosingWidget(toolbar.order_by).attr('value',
355 getInitParam("default_view_order_by"));
356
357
358 if (getInitParam("enable_feed_cats") == 0)
359 Element.hide(dijit.byId("include_children").domNode);
360
361 dijit.byId("include_children").attr("checked",
362 getInitParam("default_include_children"));
363
364 feeds_sort_by_unread = getInitParam("feeds_sort_by_unread") == 1;
365
366 loading_set_progress(30);
367
368 // can't use cache_clear() here because viewfeed might not have initialized yet
369 if ('sessionStorage' in window && window['sessionStorage'] !== null)
370 sessionStorage.clear();
371
372 console.log("second stage ok");
373
374 } catch (e) {
375 exception_error("init_second_stage", e);
376 }
377 }
378
379 function quickMenuGo(opid) {
380 try {
381 if (opid == "qmcPrefs") {
382 gotoPreferences();
383 }
384
385 if (opid == "qmcTagCloud") {
386 displayDlg("printTagCloud");
387 }
388
389 if (opid == "qmcTagSelect") {
390 displayDlg("printTagSelect");
391 }
392
393 if (opid == "qmcSearch") {
394 search();
395 return;
396 }
397
398 if (opid == "qmcAddFeed") {
399 quickAddFeed();
400 return;
401 }
402
403 if (opid == "qmcDigest") {
404 window.location.href = "digest.php";
405 return;
406 }
407
408 if (opid == "qmcEditFeed") {
409 if (activeFeedIsCat())
410 alert(__("You can't edit this kind of feed."));
411 else
412 editFeed(getActiveFeedId());
413 return;
414 }
415
416 if (opid == "qmcRemoveFeed") {
417 var actid = getActiveFeedId();
418
419 if (activeFeedIsCat()) {
420 alert(__("You can't unsubscribe from the category."));
421 return;
422 }
423
424 if (!actid) {
425 alert(__("Please select some feed first."));
426 return;
427 }
428
429 var fn = getFeedName(actid);
430
431 var pr = __("Unsubscribe from %s?").replace("%s", fn);
432
433 if (confirm(pr)) {
434 unsubscribeFeed(actid);
435 }
436
437 return;
438 }
439
440 if (opid == "qmcCatchupAll") {
441 catchupAllFeeds();
442 return;
443 }
444
445 if (opid == "qmcShowOnlyUnread") {
446 toggleDispRead();
447 return;
448 }
449
450 if (opid == "qmcAddFilter") {
451 quickAddFilter();
452 return;
453 }
454
455 if (opid == "qmcAddLabel") {
456 addLabel();
457 return;
458 }
459
460 if (opid == "qmcRescoreFeed") {
461 rescoreCurrentFeed();
462 return;
463 }
464
465 if (opid == "qmcHKhelp") {
466 new Ajax.Request("backend.php", {
467 parameters: "?op=backend&method=help&topic=main",
468 onComplete: function(transport) {
469 $("hotkey_help_overlay").innerHTML = transport.responseText;
470 Effect.Appear("hotkey_help_overlay", {duration : 0.3});
471 } });
472 }
473
474 } catch (e) {
475 exception_error("quickMenuGo", e);
476 }
477 }
478
479 function toggleDispRead() {
480 try {
481
482 var hide = !(getInitParam("hide_read_feeds") == "1");
483
484 hideOrShowFeeds(hide);
485
486 var query = "?op=rpc&method=setpref&key=HIDE_READ_FEEDS&value=" +
487 param_escape(hide);
488
489 setInitParam("hide_read_feeds", hide);
490
491 new Ajax.Request("backend.php", {
492 parameters: query,
493 onComplete: function(transport) {
494 } });
495
496 } catch (e) {
497 exception_error("toggleDispRead", e);
498 }
499 }
500
501 function parse_runtime_info(data) {
502
503 //console.log("parsing runtime info...");
504
505 for (k in data) {
506 var v = data[k];
507
508 // console.log("RI: " + k + " => " + v);
509
510 if (k == "new_version_available") {
511 var icon = $("newVersionIcon");
512 if (icon) {
513 if (v == "1") {
514 icon.style.display = "inline";
515 } else {
516 icon.style.display = "none";
517 }
518 }
519 return;
520 }
521
522 if (k == "daemon_is_running" && v != 1) {
523 notify_error("<span onclick=\"javascript:explainError(1)\">Update daemon is not running.</span>", true);
524 return;
525 }
526
527 if (k == "daemon_stamp_ok" && v != 1) {
528 notify_error("<span onclick=\"javascript:explainError(3)\">Update daemon is not updating feeds.</span>", true);
529 return;
530 }
531
532 if (k == "max_feed_id" || k == "num_feeds") {
533 if (init_params[k] != v) {
534 console.log("feed count changed, need to reload feedlist.");
535 updateFeedList();
536 }
537 }
538
539 init_params[k] = v;
540 notify('');
541 }
542 }
543
544 function collapse_feedlist() {
545 try {
546
547 if (!Element.visible('feeds-holder')) {
548 Element.show('feeds-holder');
549 Element.show('feeds-holder_splitter');
550 $("collapse_feeds_btn").innerHTML = "&lt;&lt;";
551 } else {
552 Element.hide('feeds-holder');
553 Element.hide('feeds-holder_splitter');
554 $("collapse_feeds_btn").innerHTML = "&gt;&gt;";
555 }
556
557 dijit.byId("main").resize();
558
559 query = "?op=rpc&method=setpref&key=_COLLAPSED_FEEDLIST&value=true";
560 new Ajax.Request("backend.php", { parameters: query });
561
562 } catch (e) {
563 exception_error("collapse_feedlist", e);
564 }
565 }
566
567 function viewModeChanged() {
568 return viewCurrentFeed('');
569 }
570
571 function viewLimitChanged() {
572 return viewCurrentFeed('');
573 }
574
575 /* function adjustArticleScore(id, score) {
576 try {
577
578 var pr = prompt(__("Assign score to article:"), score);
579
580 if (pr != undefined) {
581 var query = "?op=rpc&method=setScore&id=" + id + "&score=" + pr;
582
583 new Ajax.Request("backend.php", {
584 parameters: query,
585 onComplete: function(transport) {
586 viewCurrentFeed();
587 } });
588
589 }
590 } catch (e) {
591 exception_error("adjustArticleScore", e);
592 }
593 } */
594
595 function rescoreCurrentFeed() {
596
597 var actid = getActiveFeedId();
598
599 if (activeFeedIsCat() || actid < 0) {
600 alert(__("You can't rescore this kind of feed."));
601 return;
602 }
603
604 if (!actid) {
605 alert(__("Please select some feed first."));
606 return;
607 }
608
609 var fn = getFeedName(actid);
610 var pr = __("Rescore articles in %s?").replace("%s", fn);
611
612 if (confirm(pr)) {
613 notify_progress("Rescoring articles...");
614
615 var query = "?op=pref-feeds&method=rescore&quiet=1&ids=" + actid;
616
617 new Ajax.Request("backend.php", {
618 parameters: query,
619 onComplete: function(transport) {
620 viewCurrentFeed();
621 } });
622 }
623 }
624
625 function hotkey_handler(e) {
626 try {
627
628 if (e.target.nodeName == "INPUT" || e.target.nodeName == "TEXTAREA") return;
629
630 var keycode = false;
631 var shift_key = false;
632
633 var cmdline = $('cmdline');
634
635 try {
636 shift_key = e.shiftKey;
637 } catch (e) {
638
639 }
640
641 if (window.event) {
642 keycode = window.event.keyCode;
643 } else if (e) {
644 keycode = e.which;
645 }
646
647 var keychar = String.fromCharCode(keycode);
648
649 if (keycode == 27) { // escape
650 if (Element.visible("hotkey_help_overlay")) {
651 Element.hide("hotkey_help_overlay");
652 }
653 hotkey_prefix = false;
654 }
655
656 if (keycode == 16) return; // ignore lone shift
657 if (keycode == 17) return; // ignore lone ctrl
658
659 if ((keycode == 70 || keycode == 67 || keycode == 71 || keycode == 65)
660 && !hotkey_prefix) {
661
662 var date = new Date();
663 var ts = Math.round(date.getTime() / 1000);
664
665 hotkey_prefix = keycode;
666 hotkey_prefix_pressed = ts;
667
668 cmdline.innerHTML = keychar;
669 Element.show(cmdline);
670
671 console.log("KP: PREFIX=" + keycode + " CHAR=" + keychar + " TS=" + ts);
672 return true;
673 }
674
675 if (Element.visible("hotkey_help_overlay")) {
676 Element.hide("hotkey_help_overlay");
677 }
678
679 /* Global hotkeys */
680
681 Element.hide(cmdline);
682
683 if (!hotkey_prefix) {
684
685 if (keycode == 27) { // escape
686 closeArticlePanel();
687 return;
688 }
689
690 if (keycode == 69) { // e
691 var id = getActiveArticleId();
692 emailArticle(id);
693 }
694
695 if ((keycode == 191 || keychar == '?') && shift_key) { // ?
696
697 new Ajax.Request("backend.php", {
698 parameters: "?op=backend&method=help&topic=main",
699 onComplete: function(transport) {
700 $("hotkey_help_overlay").innerHTML = transport.responseText;
701 Effect.Appear("hotkey_help_overlay", {duration : 0.3});
702 } });
703 return false;
704 }
705
706 if (keycode == 191 || keychar == '/') { // /
707 search();
708 return false;
709 }
710
711 if (keycode == 74 && !shift_key) { // j
712 var rv = dijit.byId("feedTree").getPreviousFeed(
713 getActiveFeedId(), activeFeedIsCat());
714
715 if (rv) viewfeed(rv[0], '', rv[1]);
716
717 return;
718 }
719
720 if (keycode == 75) { // k
721 var rv = dijit.byId("feedTree").getNextFeed(
722 getActiveFeedId(), activeFeedIsCat());
723
724 if (rv) viewfeed(rv[0], '', rv[1]);
725
726 return;
727 }
728
729 if (shift_key && keycode == 40) { // shift-down
730 catchupRelativeToArticle(1);
731 return;
732 }
733
734 if (shift_key && keycode == 38) { // shift-up
735 catchupRelativeToArticle(0);
736 return;
737 }
738
739 if (shift_key && keycode == 78) { // N
740 scrollArticle(50);
741 return;
742 }
743
744 if (shift_key && keycode == 80) { // P
745 scrollArticle(-50);
746 return;
747 }
748
749 if (keycode == 68 && shift_key) { // shift-D
750 dismissSelectedArticles();
751 return;
752 }
753
754 if (keycode == 88 && shift_key) { // shift-X
755 dismissReadArticles();
756 return;
757 }
758
759 if (keycode == 78 || keycode == 40) { // n, down
760 if (typeof moveToPost != 'undefined') {
761 moveToPost('next');
762 return false;
763 }
764 }
765
766 if (keycode == 80 || keycode == 38) { // p, up
767 if (typeof moveToPost != 'undefined') {
768 moveToPost('prev');
769 return false;
770 }
771 }
772
773 if (keycode == 83 && shift_key) { // S
774 selectionTogglePublished(undefined, false, true);
775 return;
776 }
777
778 if (keycode == 83) { // s
779 selectionToggleMarked(undefined, false, true);
780 return;
781 }
782
783 if (keycode == 85) { // u
784 selectionToggleUnread(undefined, false, true);
785 return;
786 }
787
788 if (keycode == 84 && shift_key) { // T
789 var id = getActiveArticleId();
790 if (id) {
791 editArticleTags(id, getActiveFeedId(), isCdmMode());
792 return;
793 }
794 }
795
796 if (keycode == 9) { // tab
797 var id = getArticleUnderPointer();
798 if (id) {
799 var cb = $("RCHK-" + id);
800
801 if (cb) {
802 cb.checked = !cb.checked;
803 toggleSelectRowById(cb, "RROW-" + id);
804 return false;
805 }
806 }
807 }
808
809 if (keycode == 79) { // o
810 if (getActiveArticleId()) {
811 openArticleInNewWindow(getActiveArticleId());
812 return;
813 }
814 }
815
816 if (keycode == 81 && shift_key) { // Q
817 if (typeof catchupAllFeeds != 'undefined') {
818 catchupAllFeeds();
819 return;
820 }
821 }
822
823 if (keycode == 88 && !shift_key) { // x
824 if (activeFeedIsCat()) {
825 dijit.byId("feedTree").collapseCat(getActiveFeedId());
826 return;
827 }
828 }
829 }
830
831 /* Prefix a */
832
833 if (hotkey_prefix == 65) { // a
834 hotkey_prefix = false;
835
836 if (keycode == 65) { // a
837 selectArticles('all');
838 return;
839 }
840
841 if (keycode == 85) { // u
842 selectArticles('unread');
843 return;
844 }
845
846 if (keycode == 73) { // i
847 selectArticles('invert');
848 return;
849 }
850
851 if (keycode == 78) { // n
852 selectArticles('none');
853 return;
854 }
855
856 }
857
858 /* Prefix f */
859
860 if (hotkey_prefix == 70) { // f
861
862 hotkey_prefix = false;
863
864 if (keycode == 81) { // q
865 if (getActiveFeedId()) {
866 catchupCurrentFeed();
867 return;
868 }
869 }
870
871 if (keycode == 82) { // r
872 if (getActiveFeedId()) {
873 viewfeed(getActiveFeedId(), '', activeFeedIsCat());
874 return;
875 }
876 }
877
878 if (keycode == 65) { // a
879 toggleDispRead();
880 return false;
881 }
882
883 if (keycode == 85) { // u
884 if (getActiveFeedId()) {
885 viewfeed(getActiveFeedId(), '');
886 return false;
887 }
888 }
889
890 if (keycode == 69) { // e
891
892 if (activeFeedIsCat())
893 alert(__("You can't edit this kind of feed."));
894 else
895 editFeed(getActiveFeedId());
896 return;
897
898 return false;
899 }
900
901 if (keycode == 83) { // s
902 quickAddFeed();
903 return false;
904 }
905
906 if (keycode == 67 && shift_key) { // C
907 if (typeof catchupAllFeeds != 'undefined') {
908 catchupAllFeeds();
909 return false;
910 }
911 }
912
913 if (keycode == 67) { // c
914 if (getActiveFeedId()) {
915 catchupCurrentFeed();
916 return false;
917 }
918 }
919
920 if (keycode == 88) { // x
921 reverseHeadlineOrder();
922 return;
923 }
924 }
925
926 /* Prefix c */
927
928 if (hotkey_prefix == 67) { // c
929 hotkey_prefix = false;
930
931 if (keycode == 70) { // f
932 quickAddFilter();
933 return false;
934 }
935
936 if (keycode == 76) { // l
937 addLabel();
938 return false;
939 }
940
941 if (keycode == 83) { // s
942 if (typeof collapse_feedlist != 'undefined') {
943 collapse_feedlist();
944 return false;
945 }
946 }
947
948 if (keycode == 77) { // m
949 // TODO: sortable feedlist
950 return;
951 }
952
953 if (keycode == 78) { // n
954 catchupRelativeToArticle(1);
955 return;
956 }
957
958 if (keycode == 80) { // p
959 catchupRelativeToArticle(0);
960 return;
961 }
962
963
964 }
965
966 /* Prefix g */
967
968 if (hotkey_prefix == 71) { // g
969
970 hotkey_prefix = false;
971
972
973 if (keycode == 65) { // a
974 viewfeed(-4);
975 return false;
976 }
977
978 if (keycode == 83) { // s
979 viewfeed(-1);
980 return false;
981 }
982
983 if (keycode == 80 && shift_key) { // P
984 gotoPreferences();
985 return false;
986 }
987
988 if (keycode == 80) { // p
989 viewfeed(-2);
990 return false;
991 }
992
993 if (keycode == 70) { // f
994 viewfeed(-3);
995 return false;
996 }
997
998 if (keycode == 84) { // t
999 displayDlg("printTagCloud");
1000 return false;
1001 }
1002 }
1003
1004 /* Cmd */
1005
1006 if (hotkey_prefix == 224 || hotkey_prefix == 91) { // f
1007 hotkey_prefix = false;
1008 return;
1009 }
1010
1011 if (hotkey_prefix) {
1012 console.log("KP: PREFIX=" + hotkey_prefix + " CODE=" + keycode + " CHAR=" + keychar);
1013 } else {
1014 console.log("KP: CODE=" + keycode + " CHAR=" + keychar);
1015 }
1016
1017
1018 } catch (e) {
1019 exception_error("hotkey_handler", e);
1020 }
1021 }
1022
1023 function inPreferences() {
1024 return false;
1025 }
1026
1027 function reverseHeadlineOrder() {
1028 try {
1029
1030 var query_str = "?op=rpc&method=togglepref&key=REVERSE_HEADLINES";
1031
1032 new Ajax.Request("backend.php", {
1033 parameters: query_str,
1034 onComplete: function(transport) {
1035 viewCurrentFeed();
1036 } });
1037
1038 } catch (e) {
1039 exception_error("reverseHeadlineOrder", e);
1040 }
1041 }
1042
1043 function scheduleFeedUpdate(id, is_cat) {
1044 try {
1045 if (!id) {
1046 id = getActiveFeedId();
1047 is_cat = activeFeedIsCat();
1048 }
1049
1050 if (!id) {
1051 alert(__("Please select some feed first."));
1052 return;
1053 }
1054
1055 var query = "?op=rpc&method=scheduleFeedUpdate&id=" +
1056 param_escape(id) +
1057 "&is_cat=" + param_escape(is_cat);
1058
1059 console.log(query);
1060
1061 new Ajax.Request("backend.php", {
1062 parameters: query,
1063 onComplete: function(transport) {
1064 handle_rpc_json(transport);
1065
1066 var reply = JSON.parse(transport.responseText);
1067 var message = reply['message'];
1068
1069 if (message) {
1070 notify_info(message);
1071 return;
1072 }
1073
1074 } });
1075
1076
1077 } catch (e) {
1078 exception_error("scheduleFeedUpdate", e);
1079 }
1080 }
1081
1082 function newVersionDlg() {
1083 try {
1084 var query = "backend.php?op=dlg&method=newVersion";
1085
1086 if (dijit.byId("newVersionDlg"))
1087 dijit.byId("newVersionDlg").destroyRecursive();
1088
1089 dialog = new dijit.Dialog({
1090 id: "newVersionDlg",
1091 title: __("New version available!"),
1092 style: "width: 600px",
1093 href: query,
1094 });
1095
1096 dialog.show();
1097
1098 } catch (e) {
1099 exception_error("newVersionDlg", e);
1100 }
1101 }
1102
1103 function handle_rpc_json(transport, scheduled_call) {
1104 try {
1105 var reply = JSON.parse(transport.responseText);
1106
1107 if (reply) {
1108
1109 var error = reply['error'];
1110
1111 if (error) {
1112 var code = error['code'];
1113 var msg = error['msg'];
1114
1115 console.warn("[handle_rpc_json] received fatal error " + code + "/" + msg);
1116
1117 if (code != 0) {
1118 fatalError(code, msg);
1119 return false;
1120 }
1121 }
1122
1123 var seq = reply['seq'];
1124
1125 if (seq) {
1126 if (get_seq() != seq) {
1127 console.log("[handle_rpc_json] sequence mismatch: " + seq +
1128 " (want: " + get_seq() + ")");
1129 return true;
1130 }
1131 }
1132
1133 var message = reply['message'];
1134
1135 if (message) {
1136 if (message == "UPDATE_COUNTERS") {
1137 console.log("need to refresh counters...");
1138 setInitParam("last_article_id", -1);
1139 _force_scheduled_update = true;
1140 }
1141 }
1142
1143 var counters = reply['counters'];
1144
1145 if (counters)
1146 parse_counters(counters, scheduled_call);
1147
1148 var runtime_info = reply['runtime-info'];;
1149
1150 if (runtime_info)
1151 parse_runtime_info(runtime_info);
1152
1153 hideOrShowFeeds(getInitParam("hide_read_feeds") == 1);
1154
1155 } else {
1156 notify_error("Error communicating with server.");
1157 }
1158
1159 } catch (e) {
1160 notify_error("Error communicating with server.");
1161 console.log(e);
1162 //exception_error("handle_rpc_json", e, transport);
1163 }
1164
1165 return true;
1166 }
1167