From 876cf8f268bb954819f3948b1473d77d277ebe92 Mon Sep 17 00:00:00 2001 From: Jeena Date: Tue, 17 Sep 2013 09:53:27 +0200 Subject: [PATCH 1/6] fixes too wide contents --- css/screen.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/css/screen.css b/css/screen.css index d6f3200..e5a63d0 100644 --- a/css/screen.css +++ b/css/screen.css @@ -130,14 +130,16 @@ img { } @media screen and (width: 320px) { - #full > article * { + #full > article * , #full > article pre { max-width: 300px !important; + overflow: auto; } } @media screen and (width: 480px) { #full > article * { max-width: 460px !important; + overflow: auto; } } From 6caee6de79b01721a60149ce4e4eda33d324e9b3 Mon Sep 17 00:00:00 2001 From: Jeena Date: Wed, 18 Sep 2013 01:58:35 +0200 Subject: [PATCH 2/6] first attempt, login working, getting some data working --- index.html | 1 + js/App.js | 28 ++++--- js/Login.js | 63 ++++++++++----- js/OwnCloud.js | 200 ++++++++++++++++++++++++++++++++++++++++++++++ js/TinyTinyRSS.js | 1 + js/application.js | 16 ++++ 6 files changed, 276 insertions(+), 33 deletions(-) create mode 100644 js/OwnCloud.js diff --git a/index.html b/index.html index 95997c9..7d5ec18 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,7 @@ + diff --git a/js/App.js b/js/App.js index 999e5ac..ab4878e 100644 --- a/js/App.js +++ b/js/App.js @@ -13,7 +13,7 @@ App.prototype.authenticate = function() { }; -App.prototype.after_login = function() { +App.prototype.after_login = function(backend) { var request = window.navigator.mozApps.getSelf(); request.onsuccess = function() { @@ -92,12 +92,16 @@ App.prototype.after_login = function() { this.changeToPage("#list"); - this.ttrss = new TinyTinyRSS(this, localStorage.server_url, localStorage.session_id); + if(backend == "TinyTinyRSS") { + this.backend = new TinyTinyRSS(this, localStorage.server_url, localStorage.session_id); + } else if(backend == "OwnCloud") { + this.backend = new OwnCloud(this, localStorage.server_url, localStorage.session_id); + } this.reload(); }; App.prototype.logout = function() { - this.ttrss.logOut(); + this.backend.logOut(); this.unread_articles = []; this.populateList(); this.login.log_out(); @@ -131,11 +135,13 @@ App.prototype.setColor = function(color) { App.prototype.reload = function() { this.unread_articles = []; $("#all-read").innerHTML = "❌"; - this.ttrss.getUnreadFeeds(this.gotUnreadFeeds.bind(this)); + this.backend.getUnreadFeeds(this.gotUnreadFeeds.bind(this)); }; App.prototype.gotUnreadFeeds = function(new_articles) { + console.log(JSON.stringify(new_articles.length)) + if(new_articles == null || !this.validate(new_articles)) { // on error load the saved unread articles. var old_articles = localStorage.unread_articles; @@ -149,7 +155,7 @@ App.prototype.gotUnreadFeeds = function(new_articles) { this.unread_articles = this.unread_articles.concat(new_articles); if(new_articles.length > 0) { - this.ttrss.getUnreadFeeds(this.gotUnreadFeeds.bind(this), this.unread_articles.length); + this.backend.getUnreadFeeds(this.gotUnreadFeeds.bind(this), this.unread_articles); } else { localStorage.unread_articles = JSON.stringify(this.unread_articles); this.populateList(); @@ -312,7 +318,7 @@ App.prototype.setCurrentRead = function() { if(!article.set_unread) { article.unread = false; this.updateList(); - this.ttrss.setArticleRead(article.id); + this.backend.setArticleRead(article.id); } article.set_unread = false; @@ -335,7 +341,7 @@ App.prototype.toggleCurrentUnread = function() { } this.updateList(); - this.ttrss.setArticleUnread(article.id); + this.backend.setArticleUnread(article.id); }; App.prototype.toggleAllRead = function() { @@ -353,7 +359,7 @@ App.prototype.toggleAllRead = function() { this.updateList(); - this.ttrss.setArticleRead(ids.join(",")); + this.backend.setArticleRead(ids.join(",")); } else { @@ -367,7 +373,7 @@ App.prototype.toggleAllRead = function() { $("#all-read").innerHTML = "❌"; this.updateList(); - this.ttrss.setArticleUnread(ids.join(",")); + this.backend.setArticleUnread(ids.join(",")); } }; @@ -379,13 +385,13 @@ App.prototype.toggleStarred = function() { if(!article.marked) { article.marked = true; this.updateList(); - this.ttrss.setArticleStarred(article.id); + this.backend.setArticleStarred(article.id); $("#setstarred").innerHTML = "★"; } else { article.marked = false; this.updateList(); - this.ttrss.setArticleUnStarred(article.id); + this.backend.setArticleUnStarred(article.id); $("#setstarred").innerHTML = "☆"; } diff --git a/js/Login.js b/js/Login.js index f405154..bf0cc27 100644 --- a/js/Login.js +++ b/js/Login.js @@ -1,11 +1,10 @@ function Login(app) { this.app = app; - if(!this.is_logged_in()) { this.log_in(); if(!this.onLine()) alert("You need to be on line to log in to your server."); } - else this.app.after_login(); + else this.app.after_login(localStorage.backend); }; Login.prototype.onLine = function() { @@ -13,7 +12,7 @@ Login.prototype.onLine = function() { }; Login.prototype.is_logged_in = function() { - return localStorage.server_url && localStorage.session_id; + return localStorage.backend && localStorage.server_url && localStorage.session_id; }; Login.prototype.log_in = function() { @@ -45,26 +44,46 @@ Login.prototype.authenticate = function(e) { } var _this = this; - TinyTinyRSS.login(server_url, user, password, function(data) { - if(data.error) { - if(data.error == "API_DISABLED") { - alert("You need to enable API access in your TTRSS preferences.\n\nTo do so go to your server log in and then in Preferences -> General -> Enable API access. Check the box and save. Then try again to log in.") - } else if(data.error == "LOGIN_ERROR") { - alert("Login error\n\nIt seems you provided a wrong username or password.") - } else { - alert(data.error); - } + if(true) { + OwnCloud.login(server_url, user, password, function(data) { + if(data.version) { + var auth = btoa(user + ':' + password); + localStorage.server_url = server_url; + localStorage.session_id = auth; + localStorage.backend = "OwnCloud"; + _this.app.after_login(localStorage.backend); - } else { - localStorage.server_url = server_url; - localStorage.session_id = data.session_id; - _this.app.after_login(); - - $("#url").value = ""; - $("#un").value = ""; - $("#pw").value = ""; - } - }); + $("#url").value = ""; + $("#un").value = ""; + $("#pw").value = ""; + } else { + alert("Something went wrong, please check every input field and try again."); + } + }); + + } else { + TinyTinyRSS.login(server_url, user, password, function(data) { + if(data.error) { + if(data.error == "API_DISABLED") { + alert("You need to enable API access in your TTRSS preferences.\n\nTo do so go to your server log in and then in Preferences -> General -> Enable API access. Check the box and save. Then try again to log in.") + } else if(data.error == "LOGIN_ERROR") { + alert("Login error\n\nIt seems you provided a wrong username or password.") + } else { + alert(data.error); + } + + } else { + localStorage.server_url = server_url; + localStorage.session_id = data.session_id; + localStorage.backend = "TinyTinyRSS"; + _this.app.after_login(localStorage.backend); + + $("#url").value = ""; + $("#un").value = ""; + $("#pw").value = ""; + } + }); + } return false; }; diff --git a/js/OwnCloud.js b/js/OwnCloud.js new file mode 100644 index 0000000..9c05116 --- /dev/null +++ b/js/OwnCloud.js @@ -0,0 +1,200 @@ +function OwnCloud(app, server_url, user_pass_btoa) { + this.app = app; + this.server_url = server_url; + this.session_id = user_pass_btoa; + + window.addEventListener("offline", this.onoffline.bind(this)); + window.addEventListener("online", this.ononline.bind(this)); +} + +OwnCloud.prototype.onoffline = function() { + // Do nothing +}; + +OwnCloud.prototype.ononline = function() { + var read_articles = localStorage.read_articles; + if (read_articles ) { + read_articles = JSON.parse(localStorage.read_articles); + this.setArticleRead(read_articles.join(","), function() { + localStorage.read_articles = null; + }); + } + + var unread_articles = localStorage.unread_articles; + if (unread_articles) { + unread_articles = JSON.parse(unread_articles); + this.setArticleUnread(unread_articles.join(","), function() { + localStorage.unread_articles(); + }); + } + +}; + +OwnCloud.prototype.doOperation = function(method, operation, new_options, callback) { + if(!navigator.onLine) { + callback(null); + return; + } + + var url = this.server_url + "/index.php/apps/news/api/v1-2/" + operation; + var options = {}; + + for (var key in new_options) { + options[key] = new_options[key]; + } + + if(method == "GET" || method == "HEAD") { + var a = []; + for(var key in options) { + a.push(key + "=" + options[key]); + } + url += "?" + a.join("&"); + } + + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function() { + if(xhr.readyState == 4) { + if(xhr.status == 200) { + if(callback) + callback(JSON.parse(xhr.responseText)); + } else { + if(xhr.status != 0) alert("error: " + xhr.status + " " + xhr.statusText); + if(callback) callback(null); + } + } + } + xhr.open(method, url, true); + xhr.withCredentials = true; + //var auth = btoa(user + ':' + password); + xhr.setRequestHeader('Authorization', 'Basic ' + this.session_id); + xhr.send(JSON.stringify(options)); +} + +OwnCloud.prototype.getUnreadFeeds = function(callback, skip) { + if(skip) { + skip = skip[skip.length - 1].id; + } + + var options = { + batchSize: 700, + offset: skip || 0, + type: 3, + id: 0, + getRead: false + }; + + var _this = this; + this.doOperation("GET", "items", options, function(data) { + var items = data.items; + // FIXME + var feeds = {}; + for (var i = 0; i < data.feeds.length; i++) { + var feed = data.feeds[i]; + feeds[feed.id] = feed; + } + + callback(items.map(_this.normalize_article, feeds)); + }); +} + +OwnCloud.prototype.setArticleRead = function(article_id) { + var options = { + article_ids: article_id, + mode: 0, + field: 2 + }; + + if (navigator.onLine) { + this.doOperation("updateArticle", options); + } else { + var read_articles = localStorage.read_articles; + if(typeof read_articles !== "undefined") read_articles = JSON.parse(read_articles); + else read_articles = []; + read_articles.push(article_id); + localStorage.read_articles = JSON.stringify(read_articles); + } +}; + +OwnCloud.prototype.setArticleStarred = function(article_id) { + var options = { + article_ids: article_id, + mode: 1, + field: 0 + }; + + if (navigator.onLine) { + this.doOperation("updateArticle", options); + } +}; + +OwnCloud.prototype.setArticleUnStarred = function(article_id) { + var options = { + article_ids: article_id, + mode: 0, + field: 0 + }; + + if (navigator.onLine) { + this.doOperation("updateArticle", options); + } +}; + +OwnCloud.prototype.setArticleUnread = function(article_id) { + var options = { + article_ids: article_id, + mode: 1, + field: 2 + }; + + if (navigator.onLine) this.doOperation("updateArticle", options); + else { + var unread_articles = localStorage.unread_articles; + if (typeof unread_articles !== "undefined") unread_articles = JSON.parse(unread_articles); + else unread_articles = []; + unread_articles.push(article_id); + localStorage.unread_articles = JSON.stringify(unread_articles); + } +}; + +OwnCloud.prototype.normalize_article = function(article) { + var feeds = this; + + return { + id: article.id, + title: article.title, + content: article.body, + feed_title: feeds[article.feedId].title, + excerpt: article.body.stripHTML().substring(0, 50), + updated: article.pubDate, + link: article.link, + marked: article.starred, + unread: article.unread + } +}; + +OwnCloud.prototype.logOut = function() { + this.doOperation("logout"); +}; + +OwnCloud.login = function(server_url, user, password, callback) { + + var url = server_url + "/index.php/apps/news/api/v1-2/version"; + + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function() { + console.log(xhr.status) + if(xhr.readyState == 4) { + if(xhr.status == 200) { + callback(JSON.parse(xhr.responseText)) + } else { + alert("error: " + xhr.status + " " + xhr.statusText) + } + } + } + + xhr.open("GET", url, true); + xhr.withCredentials = true; + var auth = btoa(user + ':' + password); + xhr.setRequestHeader('Authorization', 'Basic ' + auth); + xhr.send(); +} diff --git a/js/TinyTinyRSS.js b/js/TinyTinyRSS.js index 05a4994..1a2a208 100644 --- a/js/TinyTinyRSS.js +++ b/js/TinyTinyRSS.js @@ -63,6 +63,7 @@ TinyTinyRSS.prototype.doOperation = function(operation, new_options, callback) { } TinyTinyRSS.prototype.getUnreadFeeds = function(callback, skip) { + skip = skip.length; var options = { show_excerpt: false, view_mode: "unread", diff --git a/js/application.js b/js/application.js index 3c81170..5e63e8b 100644 --- a/js/application.js +++ b/js/application.js @@ -34,5 +34,21 @@ Node.prototype.removeClass = function(cls) { } }; +var __entityMap = { + "&": "&", + "<": "<", + ">": ">" +}; + +String.prototype.escapeHTML = function() { + return String(this).replace(/[&<>]/g, function (s) { + return __entityMap[s]; + }); +} + +String.prototype.stripHTML = function() { + return this.replace(/(<([^>]+)>)/ig, ""); +} + if(!window.app) window.app = new App(); From be33cd8921f1e2d39e4dc0ed63276740bc2d76d5 Mon Sep 17 00:00:00 2001 From: Jeena Date: Wed, 18 Sep 2013 13:25:24 +0200 Subject: [PATCH 3/6] fixes --- js/App.js | 2 -- js/OwnCloud.js | 7 ++++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/js/App.js b/js/App.js index ab4878e..750017c 100644 --- a/js/App.js +++ b/js/App.js @@ -140,8 +140,6 @@ App.prototype.reload = function() { App.prototype.gotUnreadFeeds = function(new_articles) { - console.log(JSON.stringify(new_articles.length)) - if(new_articles == null || !this.validate(new_articles)) { // on error load the saved unread articles. var old_articles = localStorage.unread_articles; diff --git a/js/OwnCloud.js b/js/OwnCloud.js index 9c05116..c8ec464 100644 --- a/js/OwnCloud.js +++ b/js/OwnCloud.js @@ -87,13 +87,15 @@ OwnCloud.prototype.getUnreadFeeds = function(callback, skip) { this.doOperation("GET", "items", options, function(data) { var items = data.items; // FIXME + /* var feeds = {}; for (var i = 0; i < data.feeds.length; i++) { var feed = data.feeds[i]; feeds[feed.id] = feed; } + */ - callback(items.map(_this.normalize_article, feeds)); + callback(items.map(_this.normalize_article)); }); } @@ -163,7 +165,7 @@ OwnCloud.prototype.normalize_article = function(article) { id: article.id, title: article.title, content: article.body, - feed_title: feeds[article.feedId].title, + feed_title: "", // FIXME: feeds[article.feedId].title, excerpt: article.body.stripHTML().substring(0, 50), updated: article.pubDate, link: article.link, @@ -182,7 +184,6 @@ OwnCloud.login = function(server_url, user, password, callback) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { - console.log(xhr.status) if(xhr.readyState == 4) { if(xhr.status == 200) { callback(JSON.parse(xhr.responseText)) From 4e77ad9a01c32c1ed6bcdf5ec7d014a44436ee97 Mon Sep 17 00:00:00 2001 From: Jeena Date: Fri, 20 Sep 2013 11:16:16 +0200 Subject: [PATCH 4/6] fixed feed names --- js/OwnCloud.js | 110 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 34 deletions(-) diff --git a/js/OwnCloud.js b/js/OwnCloud.js index c8ec464..db6eb6f 100644 --- a/js/OwnCloud.js +++ b/js/OwnCloud.js @@ -2,7 +2,11 @@ function OwnCloud(app, server_url, user_pass_btoa) { this.app = app; this.server_url = server_url; this.session_id = user_pass_btoa; - + this.feeds = {}; + if(localStorage.feeds) { + this.feeds = JSON.parse(localStorage.feeds); + } + window.addEventListener("offline", this.onoffline.bind(this)); window.addEventListener("online", this.ononline.bind(this)); } @@ -67,7 +71,9 @@ OwnCloud.prototype.doOperation = function(method, operation, new_options, callba xhr.withCredentials = true; //var auth = btoa(user + ':' + password); xhr.setRequestHeader('Authorization', 'Basic ' + this.session_id); - xhr.send(JSON.stringify(options)); + var body = JSON.stringify(options); + console.log(body) + xhr.send(body); } OwnCloud.prototype.getUnreadFeeds = function(callback, skip) { @@ -84,39 +90,83 @@ OwnCloud.prototype.getUnreadFeeds = function(callback, skip) { }; var _this = this; + console.log(_this.toString()) + this.doOperation("GET", "items", options, function(data) { var items = data.items; - // FIXME - /* - var feeds = {}; + + function isFeedAvailable(o) { + return !!_this.feeds[o.feedId]; + } + + if(items.every(isFeedAvailable)) { + callback(items.map(_this.normalize_article, _this)); + } else { + _this.getFeeds(function() { + callback(items.map(_this.normalize_article, _this)); + }); + } + }); +}; + + +OwnCloud.prototype.toString = function() { + return "OwnCloud" +}; + +OwnCloud.prototype.getFeeds = function(callback) { + var _this = this; + this.doOperation("GET", "feeds", {}, function(data) { + + this.feeds = {}; for (var i = 0; i < data.feeds.length; i++) { var feed = data.feeds[i]; - feeds[feed.id] = feed; + this.feeds[feed.id] = feed; } - */ - callback(items.map(_this.normalize_article)); + localStorage.feeds = JSON.stringify(this.feeds); + + callback(); }); -} +}; + +OwnCloud.prototype.setArticleRead = function(article_id, callback) { + var items = [article_id]; + if(typeof article_id == "string") items = article_id.split(","); -OwnCloud.prototype.setArticleRead = function(article_id) { var options = { - article_ids: article_id, - mode: 0, - field: 2 + items: items, }; if (navigator.onLine) { - this.doOperation("updateArticle", options); + this.doOperation("PUT", "items/read/multiple", options, callback); } else { var read_articles = localStorage.read_articles; if(typeof read_articles !== "undefined") read_articles = JSON.parse(read_articles); else read_articles = []; - read_articles.push(article_id); + read_articles.concat(options.items); localStorage.read_articles = JSON.stringify(read_articles); } }; +OwnCloud.prototype.setArticleUnread = function(article_id, callback) { + var items = [article_id]; + if(typeof article_id == "string") items = article_id.split(","); + + var options = { + items: items, + }; + + if (navigator.onLine) this.doOperation("PUT", "items/unread/multiple", options, callback); + else { + var unread_articles = localStorage.unread_articles; + if (typeof unread_articles !== "undefined") unread_articles = JSON.parse(unread_articles); + else unread_articles = []; + unread_articles.concat(options.items); + localStorage.unread_articles = JSON.stringify(unread_articles); + } +}; + OwnCloud.prototype.setArticleStarred = function(article_id) { var options = { article_ids: article_id, @@ -141,31 +191,19 @@ OwnCloud.prototype.setArticleUnStarred = function(article_id) { } }; -OwnCloud.prototype.setArticleUnread = function(article_id) { - var options = { - article_ids: article_id, - mode: 1, - field: 2 - }; - - if (navigator.onLine) this.doOperation("updateArticle", options); - else { - var unread_articles = localStorage.unread_articles; - if (typeof unread_articles !== "undefined") unread_articles = JSON.parse(unread_articles); - else unread_articles = []; - unread_articles.push(article_id); - localStorage.unread_articles = JSON.stringify(unread_articles); - } -}; - OwnCloud.prototype.normalize_article = function(article) { - var feeds = this; + var feed = this.feeds[article.feedId]; + var feed_title = ""; + if(feed) { + feed_title = feed.title; + } return { id: article.id, title: article.title, content: article.body, - feed_title: "", // FIXME: feeds[article.feedId].title, + feed_title: feed_title, + feed_id: article.feedId, excerpt: article.body.stripHTML().substring(0, 50), updated: article.pubDate, link: article.link, @@ -178,6 +216,10 @@ OwnCloud.prototype.logOut = function() { this.doOperation("logout"); }; +OwnCloud.prototype.getFeedFor = function(o) { + return this.feeds[o.feedId]; +}; + OwnCloud.login = function(server_url, user, password, callback) { var url = server_url + "/index.php/apps/news/api/v1-2/version"; From 8865361f2d297a3ad166d4775b086fa91fdce150 Mon Sep 17 00:00:00 2001 From: Jeena Date: Fri, 20 Sep 2013 13:54:28 +0200 Subject: [PATCH 5/6] fixed starred/unstarred read/unread --- css/screen.css | 7 ++- index.html | 4 ++ js/App.js | 32 ++++++------ js/Login.js | 6 ++- js/OwnCloud.js | 116 ++++++++++++++++++++++-------------------- js/TinyTinyRSS.js | 125 +++++++++++++++++++++++++++------------------- js/application.js | 4 ++ 7 files changed, 174 insertions(+), 120 deletions(-) diff --git a/css/screen.css b/css/screen.css index e5a63d0..97c1bc7 100644 --- a/css/screen.css +++ b/css/screen.css @@ -73,6 +73,11 @@ button:active, a:active, .button:active { padding: 10px 20px; } +#login .backends label { + display: block; + margin-bottom: 1px; +} + label { display: none; } @@ -356,4 +361,4 @@ canvas { #settings .button.small { width: 20%; text-align: center; -} \ No newline at end of file +} diff --git a/index.html b/index.html index 7d5ec18..3b158b8 100644 --- a/index.html +++ b/index.html @@ -62,6 +62,10 @@ +

+ + +

diff --git a/js/App.js b/js/App.js index 750017c..ea06441 100644 --- a/js/App.js +++ b/js/App.js @@ -92,10 +92,10 @@ App.prototype.after_login = function(backend) { this.changeToPage("#list"); - if(backend == "TinyTinyRSS") { - this.backend = new TinyTinyRSS(this, localStorage.server_url, localStorage.session_id); - } else if(backend == "OwnCloud") { + if(backend == "OwnCloud") { this.backend = new OwnCloud(this, localStorage.server_url, localStorage.session_id); + } else { + this.backend = new TinyTinyRSS(this, localStorage.server_url, localStorage.session_id); } this.reload(); }; @@ -135,7 +135,7 @@ App.prototype.setColor = function(color) { App.prototype.reload = function() { this.unread_articles = []; $("#all-read").innerHTML = "❌"; - this.backend.getUnreadFeeds(this.gotUnreadFeeds.bind(this)); + this.backend.reload(this.gotUnreadFeeds.bind(this)); }; App.prototype.gotUnreadFeeds = function(new_articles) { @@ -214,7 +214,9 @@ App.prototype.updateList = function() { this.updatePieChart(); }; -App.prototype.updatePieChart = function(all, unread) { +App.prototype.updatePieChart = function() { + + if(!this.unread_articles) return; // happens on loginpage var all = this.unread_articles.length; var unread = 0; @@ -316,7 +318,7 @@ App.prototype.setCurrentRead = function() { if(!article.set_unread) { article.unread = false; this.updateList(); - this.backend.setArticleRead(article.id); + this.backend.setArticleRead(article); } article.set_unread = false; @@ -339,39 +341,39 @@ App.prototype.toggleCurrentUnread = function() { } this.updateList(); - this.backend.setArticleUnread(article.id); + this.backend.setArticleUnread(article); }; App.prototype.toggleAllRead = function() { if($("#all-read").innerHTML == "❌") { // set all read - var ids = []; + var articles = []; for (var i = 0; i < this.unread_articles.length; i++) { var article = this.unread_articles[i]; article.unread = false; article.set_unread = false; - ids.push(article.id); + articles.push(article); } $("#all-read").innerHTML = "✓"; this.updateList(); - this.backend.setArticleRead(ids.join(",")); + this.backend.setArticlesRead(articles); } else { - var ids = []; + var articles = []; for (var i = 0; i < this.unread_articles.length; i++) { var article = this.unread_articles[i]; article.unread = true; article.set_unread = false; - ids.push(article.id); + articles.push(article); } $("#all-read").innerHTML = "❌"; this.updateList(); - this.backend.setArticleUnread(ids.join(",")); + this.backend.setArticlesUnread(articles); } }; @@ -383,13 +385,13 @@ App.prototype.toggleStarred = function() { if(!article.marked) { article.marked = true; this.updateList(); - this.backend.setArticleStarred(article.id); + this.backend.setArticleStarred(article); $("#setstarred").innerHTML = "★"; } else { article.marked = false; this.updateList(); - this.backend.setArticleUnStarred(article.id); + this.backend.setArticleUnstarred(article); $("#setstarred").innerHTML = "☆"; } diff --git a/js/Login.js b/js/Login.js index bf0cc27..ed96adc 100644 --- a/js/Login.js +++ b/js/Login.js @@ -25,6 +25,9 @@ Login.prototype.authenticate = function(e) { e.preventDefault(); e.stopPropagation(); + var backend = "TinyTinyRSS"; + if($("#login form").backend[1].checked) backend = "OwnCloud"; + var server_url = $("#url").value; var user = $("#un").value; var password = $("#pw").value; @@ -44,7 +47,8 @@ Login.prototype.authenticate = function(e) { } var _this = this; - if(true) { + + if(backend == "OwnCloud") { OwnCloud.login(server_url, user, password, function(data) { if(data.version) { var auth = btoa(user + ':' + password); diff --git a/js/OwnCloud.js b/js/OwnCloud.js index db6eb6f..34694a8 100644 --- a/js/OwnCloud.js +++ b/js/OwnCloud.js @@ -3,9 +3,8 @@ function OwnCloud(app, server_url, user_pass_btoa) { this.server_url = server_url; this.session_id = user_pass_btoa; this.feeds = {}; - if(localStorage.feeds) { - this.feeds = JSON.parse(localStorage.feeds); - } + var feeds = localStorage.feeds; + if(feeds) this.feeds = JSON.parse(feeds); window.addEventListener("offline", this.onoffline.bind(this)); window.addEventListener("online", this.ononline.bind(this)); @@ -16,22 +15,14 @@ OwnCloud.prototype.onoffline = function() { }; OwnCloud.prototype.ononline = function() { - var read_articles = localStorage.read_articles; - if (read_articles ) { - read_articles = JSON.parse(localStorage.read_articles); - this.setArticleRead(read_articles.join(","), function() { - localStorage.read_articles = null; - }); - } - - var unread_articles = localStorage.unread_articles; - if (unread_articles) { - unread_articles = JSON.parse(unread_articles); - this.setArticleUnread(unread_articles.join(","), function() { - localStorage.unread_articles(); - }); - } + ["read", "unread", "starred", "unstarred"].forEach(function(type) { + var articles = localStorage[type + "_articles"]; + if(articles) { + var callback = function(ok) { if(ok) localStorage[type + "_articles"] = null } + this.call("setArticles" + type.capitalize(), [JSON.parse(articles), callback]); + } + }); }; OwnCloud.prototype.doOperation = function(method, operation, new_options, callback) { @@ -69,13 +60,16 @@ OwnCloud.prototype.doOperation = function(method, operation, new_options, callba } xhr.open(method, url, true); xhr.withCredentials = true; - //var auth = btoa(user + ':' + password); xhr.setRequestHeader('Authorization', 'Basic ' + this.session_id); var body = JSON.stringify(options); - console.log(body) xhr.send(body); } +OwnCloud.prototype.reload = function(callback) { + var _this = this; + this.getFeeds(function() { _this.getUnreadFeeds(callback); }); +}; + OwnCloud.prototype.getUnreadFeeds = function(callback, skip) { if(skip) { skip = skip[skip.length - 1].id; @@ -90,8 +84,6 @@ OwnCloud.prototype.getUnreadFeeds = function(callback, skip) { }; var _this = this; - console.log(_this.toString()) - this.doOperation("GET", "items", options, function(data) { var items = data.items; @@ -130,67 +122,73 @@ OwnCloud.prototype.getFeeds = function(callback) { }); }; -OwnCloud.prototype.setArticleRead = function(article_id, callback) { - var items = [article_id]; - if(typeof article_id == "string") items = article_id.split(","); +OwnCloud.prototype.setArticlesRead = function(articles, callback) { var options = { - items: items, + items: articles.map(function(o) { return o.id; }), }; if (navigator.onLine) { this.doOperation("PUT", "items/read/multiple", options, callback); } else { - var read_articles = localStorage.read_articles; - if(typeof read_articles !== "undefined") read_articles = JSON.parse(read_articles); - else read_articles = []; - read_articles.concat(options.items); - localStorage.read_articles = JSON.stringify(read_articles); + this.append("read_articles", articles); } -}; +} -OwnCloud.prototype.setArticleUnread = function(article_id, callback) { - var items = [article_id]; - if(typeof article_id == "string") items = article_id.split(","); +OwnCloud.prototype.setArticleRead = function(article, callback) { + this.setArticlesRead([article], callback); +} +OwnCloud.prototype.setArticlesUnread = function(articles, callback) { + var options = { - items: items, + items: articles.map(function(o) { return o.id; }), }; if (navigator.onLine) this.doOperation("PUT", "items/unread/multiple", options, callback); else { - var unread_articles = localStorage.unread_articles; - if (typeof unread_articles !== "undefined") unread_articles = JSON.parse(unread_articles); - else unread_articles = []; - unread_articles.concat(options.items); - localStorage.unread_articles = JSON.stringify(unread_articles); + this.append("unread_articles", articles); } }; -OwnCloud.prototype.setArticleStarred = function(article_id) { +OwnCloud.prototype.setArticleUnread = function(article, callback) { + this.setArticlesUnread([article], callback); +} + +OwnCloud.prototype.setArticlesStarred = function(articles, callback) { + console.log(JSON.stringify(articles)) var options = { - article_ids: article_id, - mode: 1, - field: 0 + items: articles.map(function(o) { return { feedId: o.feed_id, guidHash: o.guid_hash }; }) }; if (navigator.onLine) { - this.doOperation("updateArticle", options); - } + this.doOperation("PUT", "items/star/multiple", options, callback); + } else { + this.append("starred_articles", articles); + } }; -OwnCloud.prototype.setArticleUnStarred = function(article_id) { +OwnCloud.prototype.setArticleStarred = function(article, callback) { + this.setArticlesStarred([article], callback); +} + +OwnCloud.prototype.setArticlesUnstarred = function(articles, callback) { + var options = { - article_ids: article_id, - mode: 0, - field: 0 + items: articles.map(function(o) { return { feedId: o.feed_id, guidHash: o.guid_hash }; }) }; if (navigator.onLine) { - this.doOperation("updateArticle", options); - } + this.doOperation("PUT", "items/unstar/multiple", options, callback); + } else { + this.append("unstarred_articles", articles); + } }; +OwnCloud.prototype.setArticleUnstarred = function(articles, callback) { + this.setArticlesUnstarred([articles], callback); +} + OwnCloud.prototype.normalize_article = function(article) { var feed = this.feeds[article.feedId]; var feed_title = ""; @@ -200,6 +198,7 @@ OwnCloud.prototype.normalize_article = function(article) { return { id: article.id, + guid_hash: article.guidHash, title: article.title, content: article.body, feed_title: feed_title, @@ -220,6 +219,17 @@ OwnCloud.prototype.getFeedFor = function(o) { return this.feeds[o.feedId]; }; +OwnCloud.prototype.append = function(key, array) { + + var tmp = localStorage[key]; + + if (typeof tmp !== "undefined") tmp = JSON.parse(tmp); + else tmp = []; + + tmp.concat(options.items); + localStorage[key] = JSON.stringify(tmp); +}; + OwnCloud.login = function(server_url, user, password, callback) { var url = server_url + "/index.php/apps/news/api/v1-2/version"; diff --git a/js/TinyTinyRSS.js b/js/TinyTinyRSS.js index 1a2a208..4479f49 100644 --- a/js/TinyTinyRSS.js +++ b/js/TinyTinyRSS.js @@ -12,22 +12,14 @@ TinyTinyRSS.prototype.onoffline = function() { }; TinyTinyRSS.prototype.ononline = function() { - var read_articles = localStorage.read_articles; - if (read_articles ) { - read_articles = JSON.parse(localStorage.read_articles); - this.setArticleRead(read_articles.join(","), function() { - localStorage.read_articles = null; - }); - } - - var unread_articles = localStorage.unread_articles; - if (unread_articles) { - unread_articles = JSON.parse(unread_articles); - this.setArticleUnread(unread_articles.join(","), function() { - localStorage.unread_articles(); - }); - } + ["read", "unread", "starred", "unstarred"].forEach(function(type) { + var articles = localStorage[type + "_articles"]; + if(articles) { + var callback = function(ok) { if(ok) localStorage[type + "_articles"] = null } + this.call("setArticles" + type.capitalize(), [JSON.parse(articles), callback]); + } + }); }; TinyTinyRSS.prototype.doOperation = function(operation, new_options, callback) { @@ -62,6 +54,10 @@ TinyTinyRSS.prototype.doOperation = function(operation, new_options, callback) { xhr.send(JSON.stringify(options)); } +TinyTinyRSS.prototype.reload = function(callback) { + this.getUnreadFeeds(callback, []); +}; + TinyTinyRSS.prototype.getUnreadFeeds = function(callback, skip) { skip = skip.length; var options = { @@ -75,63 +71,92 @@ TinyTinyRSS.prototype.getUnreadFeeds = function(callback, skip) { this.doOperation("getHeadlines", options, callback); } -TinyTinyRSS.prototype.setArticleRead = function(article_id) { +TinyTinyRSS.prototype.setArticlesRead = function(articles, callback) { + var options = { - article_ids: article_id, + article_ids: articles.map(function(o) { return o.id }).join(","), mode: 0, field: 2 }; + if (navigator.onLine) { + this.doOperation("updateArticle", options, callback); + } else { + this.append("read_articles", articles); + } +}; + +TinyTinyRSS.prototype.setArticleRead = function(article, callback) { + this.setArticlesRead([article], callback); +}; + + +TinyTinyRSS.prototype.setArticlesUnread = function(articles, callback) { + + var options = { + article_ids: articles.map(function(o) { return o.id }).join(","), + mode: 1, + field: 2 + }; + + if (navigator.onLine) { + this.doOperation("updateArticle", options, callback); + } else { + this.append("unread_articles", articles); + } +}; + +TinyTinyRSS.prototype.setArticleUnread = function(article, callback) { + this.setArticlesUnread([article], callback); +}; + +TinyTinyRSS.prototype.setArticlesStarred = function(articles, callback) { + + var options = { + article_ids: articles.map(function(o) { return o.id }).join(","), + mode: 1, + field: 0 + }; + if (navigator.onLine) { this.doOperation("updateArticle", options); } else { - var read_articles = localStorage.read_articles; - if(typeof read_articles !== "undefined") read_articles = JSON.parse(read_articles); - else read_articles = []; - read_articles.push(article_id); - localStorage.read_articles = JSON.stringify(read_articles); + this.append("starred_articles", articles); } }; -TinyTinyRSS.prototype.setArticleStarred = function(article_id) { - var options = { - article_ids: article_id, - mode: 1, - field: 0 - }; - - if (navigator.onLine) { - this.doOperation("updateArticle", options); - } +TinyTinyRSS.prototype.setArticleStarred = function(article, callback) { + this.setArticlesStarred([article], callback); }; -TinyTinyRSS.prototype.setArticleUnStarred = function(article_id) { +TinyTinyRSS.prototype.setArticlesUnstarred = function(articles, callback) { + var options = { - article_ids: article_id, + article_ids: articles.map(function(o) { return o.id}).join(","), mode: 0, field: 0 }; if (navigator.onLine) { - this.doOperation("updateArticle", options); - } + this.doOperation("updateArticle", options, callback); + } else { + this.append("unstarred_articles", articles); + } }; -TinyTinyRSS.prototype.setArticleUnread = function(article_id) { - var options = { - article_ids: article_id, - mode: 1, - field: 2 - }; +TinyTinyRSS.prototype.setArticleUnstarred = function(article, callback) { + this.setArticlesUnstarred([article], callback); +}; - if (navigator.onLine) this.doOperation("updateArticle", options); - else { - var unread_articles = localStorage.unread_articles; - if (typeof unread_articles !== "undefined") unread_articles = JSON.parse(unread_articles); - else unread_articles = []; - unread_articles.push(article_id); - localStorage.unread_articles = JSON.stringify(unread_articles); - } +TinyTinyRSS.prototype.append = function(key, array) { + + var tmp = localStorage[key]; + + if (typeof tmp !== "undefined") tmp = JSON.parse(tmp); + else tmp = []; + + tmp.concat(options.items); + localStorage[key] = JSON.stringify(tmp); }; TinyTinyRSS.prototype.logOut = function() { diff --git a/js/application.js b/js/application.js index 5e63e8b..6ab7903 100644 --- a/js/application.js +++ b/js/application.js @@ -50,5 +50,9 @@ String.prototype.stripHTML = function() { return this.replace(/(<([^>]+)>)/ig, ""); } +String.prototype.capitalize = function() { + return this.charAt(0).toUpperCase() + this.slice(1); +} + if(!window.app) window.app = new App(); From 43b1135762c78a05496d6a0ddcc81fa3545302f5 Mon Sep 17 00:00:00 2001 From: Jeena Date: Fri, 20 Sep 2013 14:10:11 +0200 Subject: [PATCH 6/6] changing server placeholder in login --- js/Login.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/js/Login.js b/js/Login.js index ed96adc..62a5542 100644 --- a/js/Login.js +++ b/js/Login.js @@ -17,6 +17,17 @@ Login.prototype.is_logged_in = function() { Login.prototype.log_in = function() { this.app.changeToPage("#login"); + $("#login form").backend.forEach(function(o, i) { + o.addEventListener("change", function(e) { + if(e.target.checked) { + if(e.target.value == "OwnCloud") { + $("#url").placeholder = "http://example.com/owncloud/"; + } else { + $("#url").placeholder = "http://example.com/tt-rss/"; + } + } + }); + }); $("#login form").addEventListener('submit', this.authenticate.bind(this)); };