]> git.wh0rd.org - tt-rss.git/blob - offline.js
init_offline: call init_second_stage()
[tt-rss.git] / offline.js
1 var SCHEMA_VERSION = 3;
2
3 var offline_mode = false;
4 var store = false;
5 var localServer = false;
6 var db = false;
7
8 function view_offline(id, feed_id) {
9 try {
10
11 enableHotkeys();
12 showArticleInHeadlines(id);
13
14 db.execute("UPDATE articles SET unread = 0 WHERE id = ?", [id]);
15
16 var rs = db.execute("SELECT * FROM articles WHERE id = ?", [id]);
17
18 if (rs.isValidRow()) {
19
20 var tmp = "<div class=\"postReply\">";
21
22 tmp += "<div class=\"postHeader\" onmouseover=\"enable_resize(true)\" "+
23 "onmouseout=\"enable_resize(false)\">";
24
25 tmp += "<div class=\"postDate\">"+rs.fieldByName("updated")+"</div>";
26
27 if (rs.fieldByName("link") != "") {
28 tmp += "<div clear='both'><a target=\"_blank\" "+
29 "href=\"" + rs.fieldByName("link") + "\">" +
30 rs.fieldByName("title") + "</a></div>";
31 } else {
32 tmp += "<div clear='both'>" + rs.fieldByName("title") + "</div>";
33 }
34
35 tmp += "<div style='float : right'> "+
36 "<img src='images/tag.png' class='tagsPic' alt='Tags' title='Tags'>";
37 tmp += rs.fieldByName("tags");
38 tmp += "</div>";
39
40 tmp += "<div clear='both'>"+
41 "<a target=\"_blank\" "+
42 "href=\"" + rs.fieldByName("comments") + "\">" +
43 __("comments") + "</a></div>";
44
45 tmp += "</div>";
46
47 tmp += "<div class=\"postContent\">"
48 tmp += rs.fieldByName("content");
49 tmp += "</div>";
50
51 tmp += "</div>";
52
53 render_article(tmp);
54 update_local_feedlist_counters();
55 }
56
57 rs.close();
58
59 return false;
60
61 } catch (e) {
62 exception_error("view_offline", e);
63 }
64 }
65
66 function viewfeed_offline(feed_id, subop, is_cat, subop_param, skip_history, offset) {
67 try {
68 notify('');
69
70 if (!offset) offset = 0;
71
72 loading_set_progress(100);
73
74 clean_feed_selections();
75
76 setActiveFeedId(feed_id, is_cat);
77
78 if (!is_cat) {
79 var feedr = document.getElementById("FEEDR-" + feed_id);
80 if (feedr && !feedr.className.match("Selected")) {
81 feedr.className = feedr.className + "Selected";
82 }
83 } else {
84 var feedr = document.getElementById("FCAT-" + feed_id);
85 if (feedr && !feedr.className.match("Selected")) {
86 feedr.className = feedr.className + "Selected";
87 }
88 }
89
90 disableContainerChildren("headlinesToolbar", false);
91 Form.enable("main_toolbar_form");
92
93 var f = document.getElementById("headlines-frame");
94 try {
95 if (reply.offset == 0) {
96 debug("resetting headlines scrollTop");
97 f.scrollTop = 0;
98 }
99 } catch (e) { };
100
101
102 var tmp = "";
103
104 rs = db.execute("SELECT title FROM feeds WHERE id = ?", [feed_id]);
105
106 if (rs.isValidRow() || feed_id == -1 || feed_id == -4) {
107
108 feed_title = rs.field(0);
109
110 if (feed_id == -1) {
111 feed_title = __("Starred articles");
112 }
113
114 if (feed_id == -4) {
115 feed_title = __("All articles");
116 }
117
118 if (offset == 0) {
119 tmp += "<div id=\"headlinesContainer\">";
120
121 tmp += "<div class=\"headlinesSubToolbar\">";
122 tmp += "<div id=\"subtoolbar_ftitle\">";
123 tmp += feed_title;
124 tmp += "</div>";
125
126 var sel_all_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, '', true)";
127 var sel_unread_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, 'Unread', true)";
128 var sel_none_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false)";
129 var sel_inv_link = "javascript:invertHeadlineSelection()";
130
131 tmp += __('Select:')+
132 " <a href=\""+sel_all_link+"\">"+__('All')+"</a>, "+
133 "<a href=\""+sel_unread_link+"\">"+__('Unread')+"</a>, "+
134 "<a href=\""+sel_inv_link+"\">"+__('Invert')+"</a>, "+
135 "<a href=\""+sel_none_link+"\">"+__('None')+"</a>";
136
137 tmp += "&nbsp;&nbsp;";
138
139 tmp += "</div>";
140
141 tmp += "<div id=\"headlinesInnerContainer\" onscroll=\"headlines_scroll_handler()\">";
142
143 tmp += "<table class=\"headlinesList\" id=\"headlinesList\" cellspacing=\"0\">";
144
145 }
146
147 var limit = 30;
148
149 var toolbar_form = document.forms["main_toolbar_form"];
150
151 var limit = toolbar_form.limit[toolbar_form.limit.selectedIndex].value;
152 var view_mode = toolbar_form.view_mode[toolbar_form.view_mode.selectedIndex].value;
153
154 var limit_qpart = "";
155 var strategy_qpart = "";
156 var mode_qpart = "";
157 var offset_qpart = "";
158
159 if (limit != 0) {
160 limit_qpart = "LIMIT " + limit;
161 }
162
163 if (view_mode == "all_articles") {
164 mode_qpart = "1";
165 } else if (view_mode == "adaptive") {
166 if (get_local_feed_unread(feed_id) > 0) {
167 mode_qpart = "unread = 1";
168 } else {
169 mode_qpart = "1";
170 }
171 } else if (view_mode == "marked") {
172 mode_qpart = "marked = 1";
173 } else if (view_mode == "unread") {
174 mode_qpart = "unread = 1";
175 } else {
176 mode_qpart = "1";
177 }
178
179 if (feed_id > 0) {
180 strategy_qpart = "feed_id = " + feed_id;
181 } else if (feed_id == -1) {
182 strategy_qpart = "marked = 1";
183 } else if (feed_id == -4) {
184 strategy_qpart = "1";
185 }
186
187 if (offset > 0) {
188 offset_qpart = "OFFSET " + (offset*30);
189 } else {
190 offset_qpart = "";
191 }
192
193 var query = "SELECT * FROM articles WHERE " +
194 strategy_qpart +
195 " AND " + mode_qpart +
196 " ORDER BY updated DESC "+
197 limit_qpart + " " +
198 offset_qpart;
199
200 var rs = db.execute(query);
201
202 var line_num = offset*30;
203
204 while (rs.isValidRow()) {
205
206 var id = rs.fieldByName("id");
207 var feed_id = rs.fieldByName("feed_id");
208
209 var marked_pic;
210
211 var row_class = (line_num % 2) ? "even" : "odd";
212
213 if (rs.fieldByName("unread") == "1") {
214 row_class += "Unread";
215 }
216
217 if (rs.fieldByName("marked") == "1") {
218 marked_pic = "<img id=\"FMPIC-"+id+"\" "+
219 "src=\"images/mark_set.png\" class=\"markedPic\""+
220 "alt=\"Unstar article\" onclick='javascript:tMark("+id+")'>";
221 } else {
222 marked_pic = "<img id=\"FMPIC-"+id+"\" "+
223 "src=\"images/mark_unset.png\" class=\"markedPic\""+
224 "alt=\"Star article\" onclick='javascript:tMark("+id+")'>";
225 }
226
227 var mouseover_attrs = "onmouseover='postMouseIn($id)' "+
228 "onmouseout='postMouseOut($id)'";
229
230 tmp += "<tr class='"+row_class+"' id='RROW-"+id+"' "+mouseover_attrs+">";
231
232 tmp += "<td class='hlUpdPic'> </td>";
233
234 tmp += "<td class='hlSelectRow'>"+
235 "<input type=\"checkbox\" onclick=\"tSR(this)\" id=\"RCHK-"+id+"\"></td>";
236
237 tmp += "<td class='hlMarkedPic'>"+marked_pic+"</td>";
238
239 tmp += "<td onclick='view("+id+","+feed_id+")' "+
240 "class='hlContent' valign='middle'>";
241
242 tmp += "<a target=\"_blank\" id=\"RTITLE-$id\" href=\"" +
243 rs.fieldByName("link") + "\"" +
244 "onclick=\"return view("+id+","+feed_id+");\">"+
245 rs.fieldByName("title");
246
247 var content_preview = truncate_string(strip_tags(rs.fieldByName("content")),
248 100);
249
250 tmp += "<span class=\"contentPreview\"> - "+content_preview+"</span>";
251
252 tmp += "</a>";
253
254 tmp += "</td>";
255
256 tmp += "<td class=\"hlUpdated\" onclick='view("+id+","+feed_id+")'>"+
257 "<nobr>"+rs.fieldByName("updated").substring(0,16)+"</nobr></td>";
258
259 tmp += "</tr>";
260
261 rs.next();
262 line_num++;
263 }
264
265 rs.close();
266
267 if (offset == 0) {
268 tmp += "</table>";
269 tmp += "</div></div>";
270 }
271
272 if (offset == 0) {
273 var container = document.getElementById("headlines-frame");
274 container.innerHTML = tmp;
275 } else {
276 var ids = getSelectedArticleIds2();
277
278 var container = document.getElementById("headlinesList");
279 container.innerHTML = container.innerHTML + tmp;
280
281 for (var i = 0; i < ids.length; i++) {
282 markHeadline(ids[i]);
283 }
284 }
285 }
286
287 remove_splash();
288
289
290 } catch (e) {
291 exception_error("viewfeed_offline", e);
292 }
293 }
294
295 function render_offline_feedlist() {
296 try {
297 var tmp = "<ul class=\"feedList\" id=\"feedList\">";
298
299 var unread = get_local_feed_unread(-4);
300
301 global_unread = unread;
302 updateTitle();
303
304 tmp += printFeedEntry(-4, __("All articles"), "feed", unread,
305 "images/tag.png");
306
307 var unread = get_local_feed_unread(-1);
308
309 tmp += printFeedEntry(-1, __("Starred articles"), "feed", unread,
310 "images/mark_set.png");
311
312 tmp += "<li><hr/></li>";
313
314 var rs = db.execute("SELECT feeds.id,feeds.title,has_icon,COUNT(articles.id) "+
315 "FROM feeds LEFT JOIN articles ON (feed_id = feeds.id) "+
316 "WHERE unread = 1 OR unread IS NULL GROUP BY feeds.id "+
317 "ORDER BY feeds.title");
318
319 while (rs.isValidRow()) {
320
321 var id = rs.field(0);
322 var title = rs.field(1);
323 var has_icon = rs.field(2);
324 var unread = rs.field(3);
325
326 var icon = "";
327
328 if (has_icon) {
329 icon = "icons/" + id + ".ico";
330 }
331
332
333 var feed_icon = "";
334
335 var row_class = "feed";
336
337 if (unread > 0) {
338 row_class += "Unread";
339 fctr_class = "feedCtrHasUnread";
340 } else {
341 fctr_class = "feedCtrNoUnread";
342 }
343
344 tmp += printFeedEntry(id, title, "feed", unread, icon);
345
346 rs.next();
347 }
348
349 rs.close();
350
351 tmp += "</ul>";
352
353 render_feedlist(tmp);
354 } catch (e) {
355 exception_error("render_offline_feedlist", e);
356 }
357 }
358
359 function init_offline() {
360 try {
361 offline_mode = true;
362
363 Element.hide("dispSwitchPrompt");
364 Element.hide("feedBrowserPrompt");
365 Element.hide("quickMenuChooser");
366
367 var tb_form = document.getElementById("main_toolbar_form");
368
369 Element.hide(tb_form.update);
370
371 var rs = db.execute("SELECT key, value FROM init_params");
372
373 while (rs.isValidRow()) {
374 init_params[rs.field(0)] = rs.field(1);
375 rs.next();
376 }
377
378 rs.close();
379
380 render_offline_feedlist();
381 init_second_stage();
382 remove_splash();
383 } catch (e) {
384 exception_error("init_offline", e);
385 }
386 }
387
388 function offline_download_parse(stage, transport) {
389 try {
390 if (transport.responseXML) {
391
392 if (stage == 0) {
393
394 var feeds = transport.responseXML.getElementsByTagName("feed");
395
396 if (feeds.length > 0) {
397 db.execute("DELETE FROM feeds");
398 }
399
400 for (var i = 0; i < feeds.length; i++) {
401 var id = feeds[i].getAttribute("id");
402 var has_icon = feeds[i].getAttribute("has_icon");
403 var title = feeds[i].firstChild.nodeValue;
404
405 db.execute("INSERT INTO feeds (id,title,has_icon)"+
406 "VALUES (?,?,?)",
407 [id, title, has_icon]);
408 }
409
410 window.setTimeout("update_offline_data("+(stage+1)+")", 60*1000);
411 } else {
412
413 var articles = transport.responseXML.getElementsByTagName("article");
414
415 var articles_found = 0;
416
417 for (var i = 0; i < articles.length; i++) {
418 var a = eval("("+articles[i].firstChild.nodeValue+")");
419 articles_found++;
420 if (a) {
421
422 var date = new Date();
423 var ts = Math.round(date.getTime() / 1000);
424
425 db.execute("DELETE FROM articles WHERE id = ?", [a.id]);
426 db.execute("INSERT INTO articles "+
427 "(id, feed_id, title, link, guid, updated, content, "+
428 "unread, marked, tags, added, comments) "+
429 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
430 [a.id, a.feed_id, a.title, a.link, a.guid, a.updated,
431 a.content, a.unread, a.marked, a.tags, ts,
432 a.comments]);
433
434 }
435 }
436
437 if (articles_found > 0) {
438 window.setTimeout("update_offline_data("+(stage+1)+")", 60*1000);
439 } else {
440 window.setTimeout("update_offline_data(0)", 1800*1000);
441
442 var date = new Date();
443 var ts = Math.round(date.getTime() / 1000);
444
445 db.execute("DELETE FROM articles WHERE added < ? - 2592000", [ts]);
446
447 }
448 }
449
450 }
451 } catch (e) {
452 exception_error("offline_download_parse", e);
453 }
454 }
455
456 function update_offline_data(stage) {
457 try {
458
459 if (!stage) stage = 0;
460
461 debug("update_offline_data: stage " + stage);
462
463 // notify_progress("Loading, please wait... (" + stage +")", true);
464
465 var query = "backend.php?op=rpc&subop=download&stage=" + stage;
466
467 var rs = db.execute("SELECT MAX(id), MIN(id) FROM articles");
468
469 if (rs.isValidRow() && rs.field(0)) {
470 var offline_dl_max_id = rs.field(0);
471 var offline_dl_min_id = rs.field(1);
472
473 query = query + "&cidt=" + offline_dl_max_id;
474 query = query + "&cidb=" + offline_dl_min_id;
475 }
476
477 rs.close();
478
479 new Ajax.Request(query, {
480 onComplete: function(transport) {
481 offline_download_parse(stage, transport);
482 debug("update_offline_data: done " + stage);
483 } });
484
485 } catch (e) {
486 exception_error("initiate_offline_download", e);
487 }
488 }
489
490 function set_feedlist_counter(id, ctr) {
491 try {
492
493 var feedctr = document.getElementById("FEEDCTR-" + id);
494 var feedu = document.getElementById("FEEDU-" + id);
495 var feedr = document.getElementById("FEEDR-" + id);
496
497 if (feedctr && feedu && feedr) {
498
499 var row_needs_hl = (ctr > 0 && ctr > parseInt(feedu.innerHTML));
500
501 feedu.innerHTML = ctr;
502
503 if (ctr > 0) {
504 feedctr.className = "feedCtrHasUnread";
505 if (!feedr.className.match("Unread")) {
506 var is_selected = feedr.className.match("Selected");
507
508 feedr.className = feedr.className.replace("Selected", "");
509 feedr.className = feedr.className.replace("Unread", "");
510
511 feedr.className = feedr.className + "Unread";
512
513 if (is_selected) {
514 feedr.className = feedr.className + "Selected";
515 }
516
517 }
518
519 if (row_needs_hl) {
520 new Effect.Highlight(feedr, {duration: 1, startcolor: "#fff7d5",
521 queue: { position:'end', scope: 'EFQ-' + id, limit: 1 } } );
522 }
523 } else {
524 feedctr.className = "feedCtrNoUnread";
525 feedr.className = feedr.className.replace("Unread", "");
526 }
527 }
528
529 } catch (e) {
530 exception_error("set_feedlist_counter", e);
531 }
532 }
533
534 function update_local_feedlist_counters() {
535 try {
536 if (!db) return;
537
538 var rs = db.execute("SELECT feeds.id,COUNT(articles.id) "+
539 "FROM feeds LEFT JOIN articles ON (feed_id = feeds.id) "+
540 "WHERE unread = 1 OR unread IS NULL GROUP BY feeds.id "+
541 "ORDER BY feeds.title");
542
543 while (rs.isValidRow()) {
544 var id = rs.field(0);
545 var ctr = rs.field(1);
546
547 set_feedlist_counter(id, ctr);
548
549 rs.next();
550 }
551
552 rs.close();
553
554 set_feedlist_counter(-4, get_local_feed_unread(-4));
555 set_feedlist_counter(-1, get_local_feed_unread(-1));
556
557 hideOrShowFeeds(getInitParam("hide_read_feeds") == 1);
558
559 global_unread = get_local_feed_unread(-4);
560 updateTitle();
561
562 } catch (e) {
563 exception_error("update_local_feedlist_counters", e);
564 }
565 }
566
567 function get_local_feed_unread(id) {
568 try {
569 var rs;
570
571 if (id == -4) {
572 rs = db.execute("SELECT SUM(unread) FROM articles");
573 } else if (id == -1) {
574 rs = db.execute("SELECT SUM(unread) FROM articles WHERE marked = 1");
575 } else {
576 rs = db.execute("SELECT SUM(unread) FROM articles WHERE feed_id = ?", [id]);
577 }
578
579 var a = false;
580
581 if (rs.isValidRow()) {
582 a = rs.field(0);
583 } else {
584 a = 0;
585 }
586
587 rs.close();
588
589 return a;
590
591 } catch (e) {
592 exception_error("get_local_feed_unread", e);
593 }
594 }
595
596 function init_gears() {
597 try {
598
599 if (window.google && google.gears) {
600 localServer = google.gears.factory.create("beta.localserver");
601 store = localServer.createManagedStore("tt-rss");
602 db = google.gears.factory.create('beta.database');
603 db.open('tt-rss');
604
605 db.execute("CREATE TABLE IF NOT EXISTS version (schema_version text)");
606
607 var rs = db.execute("SELECT schema_version FROM version");
608
609 var version = "";
610
611 if (rs.isValidRow()) {
612 version = rs.field(0);
613 }
614
615 rs.close();
616
617 if (version != SCHEMA_VERSION) {
618 db.execute("DROP TABLE IF EXISTS init_params");
619 db.execute("DROP TABLE IF EXISTS cache");
620 db.execute("DROP TABLE IF EXISTS feeds");
621 db.execute("DROP TABLE IF EXISTS articles");
622 db.execute("DROP TABLE IF EXISTS version");
623 db.execute("CREATE TABLE IF NOT EXISTS version (schema_version text)");
624 db.execute("INSERT INTO version (schema_version) VALUES (?)",
625 [SCHEMA_VERSION]);
626 }
627
628 db.execute("CREATE TABLE IF NOT EXISTS init_params (key text, value text)");
629
630 db.execute("CREATE TABLE IF NOT EXISTS cache (id text, article text, param text, added text)");
631 db.execute("CREATE TABLE IF NOT EXISTS feeds (id integer, title text, has_icon integer)");
632 db.execute("CREATE TABLE IF NOT EXISTS articles (id integer, feed_id integer, title text, link text, guid text, updated text, content text, tags text, unread text, marked text, added text, comments text)");
633 window.setTimeout("update_offline_data(0)", 100);
634
635 }
636
637 cache_expire();
638
639 } catch (e) {
640 exception_error("init_gears", e);
641 }
642 }
643
644