Code refactoring (JS and templates)
This commit is contained in:
parent
14516ea63b
commit
b3b1e8bef7
@ -504,7 +504,7 @@ nav .active a {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item a:visited {
|
#item-content a:visited {
|
||||||
color: purple;
|
color: purple;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
650
assets/js/app.js
650
assets/js/app.js
@ -1,638 +1,32 @@
|
|||||||
(function() {
|
var Miniflux = {};
|
||||||
|
|
||||||
// List of subscriptions
|
Miniflux.App = (function() {
|
||||||
var feeds = [];
|
|
||||||
|
|
||||||
// List of feeds currently updating
|
return {
|
||||||
var queue = [];
|
Run: function() {
|
||||||
|
Miniflux.Event.ListenKeyboardEvents();
|
||||||
|
Miniflux.Event.ListenMouseEvents();
|
||||||
|
},
|
||||||
|
MozillaAuth: function(action) {
|
||||||
|
navigator.id.watch({
|
||||||
|
onlogin: function(assertion) {
|
||||||
|
|
||||||
// Number of concurrent requests when updating all feeds
|
var xhr = new XMLHttpRequest();
|
||||||
var queue_length = 5;
|
xhr.open("POST", "?action=" + action, true);
|
||||||
|
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||||
|
xhr.setRequestHeader("Connection", "close");
|
||||||
|
|
||||||
// Keyboard shortcuts queue
|
xhr.onload = function () {
|
||||||
var keyqueue = [];
|
window.location.href = this.responseText;
|
||||||
|
};
|
||||||
|
|
||||||
// Download full content from the original website
|
xhr.send("token=" + assertion);
|
||||||
function download_item()
|
},
|
||||||
{
|
onlogout: function() {}
|
||||||
var container = document.getElementById("download-item");
|
});
|
||||||
if (! container) return;
|
|
||||||
|
|
||||||
var item_id = container.getAttribute("data-item-id");
|
navigator.id.request();
|
||||||
var message = container.getAttribute("data-before-message");
|
|
||||||
|
|
||||||
var img = document.createElement("img");
|
|
||||||
img.src = "assets/img/refresh.gif";
|
|
||||||
|
|
||||||
container.innerHTML = "";
|
|
||||||
container.className = "downloading";
|
|
||||||
container.appendChild(img);
|
|
||||||
container.appendChild(document.createTextNode(" " + message));
|
|
||||||
|
|
||||||
var request = new XMLHttpRequest();
|
|
||||||
|
|
||||||
request.onload = function() {
|
|
||||||
|
|
||||||
var response = JSON.parse(request.responseText);
|
|
||||||
|
|
||||||
if (response.result) {
|
|
||||||
|
|
||||||
var content = document.getElementById("item-content");
|
|
||||||
if (content) content.innerHTML = response.content;
|
|
||||||
|
|
||||||
if (container) {
|
|
||||||
|
|
||||||
var message = container.getAttribute("data-after-message");
|
|
||||||
|
|
||||||
container.innerHTML = "";
|
|
||||||
container.appendChild(document.createTextNode(" " + message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
if (container) {
|
|
||||||
|
|
||||||
var message = container.getAttribute("data-failure-message");
|
|
||||||
|
|
||||||
container.innerHTML = "";
|
|
||||||
container.appendChild(document.createTextNode(" " + message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
request.open("POST", "?action=download-item&id=" + item_id, true);
|
|
||||||
request.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flip item status between unread and read
|
|
||||||
function switch_status(item_id, hide)
|
|
||||||
{
|
|
||||||
var request = new XMLHttpRequest();
|
|
||||||
|
|
||||||
request.onload = function() {
|
|
||||||
|
|
||||||
if (is_listing()) {
|
|
||||||
|
|
||||||
var response = JSON.parse(request.responseText);
|
|
||||||
|
|
||||||
if (response.status == "read" || response.status == "unread") {
|
|
||||||
|
|
||||||
find_next_item();
|
|
||||||
|
|
||||||
if (hide) {
|
|
||||||
remove_item(response.item_id);
|
|
||||||
}
|
|
||||||
else if (response.status == "read") {
|
|
||||||
show_item_as_read(item_id);
|
|
||||||
}
|
|
||||||
else if (response.status == "unread") {
|
|
||||||
show_item_as_unread(item_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request.open("POST", "?action=change-item-status&id=" + item_id, true);
|
|
||||||
request.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set all items of the current page to the status read and redirect to the main page
|
|
||||||
function mark_items_as_read(redirect)
|
|
||||||
{
|
|
||||||
var articles = document.getElementsByTagName("article");
|
|
||||||
var idlist = [];
|
|
||||||
|
|
||||||
for (var i = 0, ilen = articles.length; i < ilen; i++) {
|
|
||||||
idlist.push(articles[i].getAttribute("data-item-id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
var request = new XMLHttpRequest();
|
|
||||||
|
|
||||||
request.onload = function() {
|
|
||||||
window.location.href = redirect;
|
|
||||||
};
|
|
||||||
|
|
||||||
request.open("POST", "?action=mark-items-as-read", true);
|
|
||||||
request.send(JSON.stringify(idlist));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the current item read and hide this item
|
|
||||||
function mark_as_read(item_id)
|
|
||||||
{
|
|
||||||
var request = new XMLHttpRequest();
|
|
||||||
|
|
||||||
request.onload = function() {
|
|
||||||
remove_item(item_id);
|
|
||||||
};
|
|
||||||
|
|
||||||
request.open("POST", "?action=mark-item-read&id=" + item_id, true);
|
|
||||||
request.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the current item unread and hide this item
|
|
||||||
function mark_as_unread(item_id)
|
|
||||||
{
|
|
||||||
var request = new XMLHttpRequest();
|
|
||||||
|
|
||||||
request.onload = function() {
|
|
||||||
remove_item(item_id);
|
|
||||||
};
|
|
||||||
|
|
||||||
request.open("POST", "?action=mark-item-unread&id=" + item_id, true);
|
|
||||||
request.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bookmark the selected item
|
|
||||||
function bookmark_item()
|
|
||||||
{
|
|
||||||
var item = document.getElementById("current-item");
|
|
||||||
|
|
||||||
if (item) {
|
|
||||||
|
|
||||||
var item_id = item.getAttribute("data-item-id");
|
|
||||||
var link = document.getElementById("bookmark-" + item_id);
|
|
||||||
|
|
||||||
if (link) link.click();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show an item as read (change title color and add icon)
|
|
||||||
function show_item_as_read(item_id)
|
|
||||||
{
|
|
||||||
var link = document.getElementById("open-" + item_id);
|
|
||||||
|
|
||||||
if (link) {
|
|
||||||
link.className = "read";
|
|
||||||
|
|
||||||
var icon = document.createElement("span");
|
|
||||||
icon.id = "read-icon-" + item_id;
|
|
||||||
icon.appendChild(document.createTextNode("☑ "));
|
|
||||||
link.parentNode.insertBefore(icon, link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show an item as unread (change title color and remove read icon)
|
|
||||||
function show_item_as_unread(item_id)
|
|
||||||
{
|
|
||||||
var link = document.getElementById("open-" + item_id);
|
|
||||||
if (link) link.className = "";
|
|
||||||
|
|
||||||
var icon = document.getElementById("read-icon-" + item_id);
|
|
||||||
if (icon) icon.parentNode.removeChild(icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show the refresh icon when updating a feed
|
|
||||||
function show_refresh_icon(feed_id)
|
|
||||||
{
|
|
||||||
var container = document.getElementById("loading-feed-" + feed_id);
|
|
||||||
|
|
||||||
if (container) {
|
|
||||||
|
|
||||||
var img = document.createElement("img");
|
|
||||||
img.src = "assets/img/refresh.gif";
|
|
||||||
|
|
||||||
container.appendChild(img);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide the refresh icon after update
|
|
||||||
function hide_refresh_icon(feed_id)
|
|
||||||
{
|
|
||||||
var container = document.getElementById("loading-feed-" + feed_id);
|
|
||||||
if (container) container.innerHTML = "";
|
|
||||||
|
|
||||||
var container = document.getElementById("last-checked-feed-" + feed_id);
|
|
||||||
if (container) container.innerHTML = container.getAttribute("data-after-update");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update one feed in the background and execute a callback after that
|
|
||||||
function refresh_feed(feed_id, callback)
|
|
||||||
{
|
|
||||||
if (! feed_id) return false;
|
|
||||||
|
|
||||||
show_refresh_icon(feed_id);
|
|
||||||
|
|
||||||
var request = new XMLHttpRequest();
|
|
||||||
|
|
||||||
request.onload = function() {
|
|
||||||
|
|
||||||
hide_refresh_icon(feed_id);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (callback) {
|
|
||||||
callback(JSON.parse(this.responseText));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
request.open("POST", "?action=refresh-feed&feed_id=" + feed_id, true);
|
|
||||||
request.send();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all subscriptions from the feeds page
|
|
||||||
function get_feeds()
|
|
||||||
{
|
|
||||||
var links = document.getElementsByTagName("a");
|
|
||||||
|
|
||||||
for (var i = 0, ilen = links.length; i < ilen; i++) {
|
|
||||||
var feed_id = links[i].getAttribute('data-feed-id');
|
|
||||||
if (feed_id) feeds.push(parseInt(feed_id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh all feeds (use a queue to allow 5 concurrent feed updates)
|
|
||||||
function refresh_all()
|
|
||||||
{
|
|
||||||
get_feeds();
|
|
||||||
|
|
||||||
var interval = setInterval(function() {
|
|
||||||
|
|
||||||
while (feeds.length > 0 && queue.length < queue_length) {
|
|
||||||
|
|
||||||
var feed_id = feeds.shift();
|
|
||||||
queue.push(feed_id);
|
|
||||||
|
|
||||||
refresh_feed(feed_id, function(response) {
|
|
||||||
|
|
||||||
var index = queue.indexOf(response.feed_id);
|
|
||||||
if (index >= 0) queue.splice(index, 1);
|
|
||||||
|
|
||||||
if (feeds.length == 0 && queue.length == 0) {
|
|
||||||
clearInterval(interval);
|
|
||||||
window.location.href = "?action=unread";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go the next page
|
|
||||||
function open_next_page()
|
|
||||||
{
|
|
||||||
var link = document.getElementById("next-page");
|
|
||||||
if (link) link.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go to the previous page
|
|
||||||
function open_previous_page()
|
|
||||||
{
|
|
||||||
var link = document.getElementById("previous-page");
|
|
||||||
if (link) link.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide one item and update the item counter on the top
|
|
||||||
function remove_item(item_id)
|
|
||||||
{
|
|
||||||
var item = document.getElementById("item-" + item_id);
|
|
||||||
|
|
||||||
if (! item) {
|
|
||||||
item = document.getElementById("current-item");
|
|
||||||
if (item.getAttribute("data-item-id") != item_id) item = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item && item.getAttribute("data-hide")) {
|
|
||||||
|
|
||||||
item.parentNode.removeChild(item);
|
|
||||||
var container = document.getElementById("page-counter");
|
|
||||||
|
|
||||||
if (container) {
|
|
||||||
|
|
||||||
counter = parseInt(container.textContent.trim(), 10) - 1;
|
|
||||||
|
|
||||||
if (counter == 0) {
|
|
||||||
|
|
||||||
window.location = "?action=feeds¬hing_to_read=1";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
container.textContent = counter + " ";
|
|
||||||
document.title = "miniflux (" + counter + ")";
|
|
||||||
document.getElementById("nav-counter").textContent = "(" + counter + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the original url inside a new tab
|
|
||||||
function open_original_item()
|
|
||||||
{
|
|
||||||
var link = document.getElementById("original-item");
|
|
||||||
|
|
||||||
if (link) {
|
|
||||||
|
|
||||||
if (is_listing() && link.getAttribute("data-hide")) {
|
|
||||||
mark_as_read(link.getAttribute("data-item-id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
link.removeAttribute("data-action");
|
|
||||||
link.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show item content
|
|
||||||
function open_item()
|
|
||||||
{
|
|
||||||
var link = document.getElementById("open-item");
|
|
||||||
if (link) link.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show the next item
|
|
||||||
function open_next_item()
|
|
||||||
{
|
|
||||||
var link = document.getElementById("next-item");
|
|
||||||
|
|
||||||
if (link) {
|
|
||||||
|
|
||||||
link.click();
|
|
||||||
}
|
|
||||||
else if (is_listing()) {
|
|
||||||
|
|
||||||
find_next_item();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show the previous item
|
|
||||||
function open_previous_item()
|
|
||||||
{
|
|
||||||
var link = document.getElementById("previous-item");
|
|
||||||
|
|
||||||
if (link) {
|
|
||||||
|
|
||||||
link.click();
|
|
||||||
}
|
|
||||||
else if (is_listing()) {
|
|
||||||
|
|
||||||
find_previous_item();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change item status and select the next item in the list
|
|
||||||
function change_item_status()
|
|
||||||
{
|
|
||||||
if (is_listing() && ! document.getElementById("current-item")) {
|
|
||||||
find_next_item();
|
|
||||||
}
|
|
||||||
|
|
||||||
var item = document.getElementById("current-item");
|
|
||||||
|
|
||||||
if (item) {
|
|
||||||
switch_status(item.getAttribute("data-item-id"), item.getAttribute("data-hide"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scroll automatically the page when using keyboard shortcuts
|
|
||||||
function scroll_page_to(item)
|
|
||||||
{
|
|
||||||
var clientHeight = pageYOffset + document.documentElement.clientHeight;
|
|
||||||
var itemPosition = item.offsetTop + item.offsetHeight;
|
|
||||||
|
|
||||||
if (clientHeight - itemPosition < 0 || clientHeight - item.offsetTop > document.documentElement.clientHeight) {
|
|
||||||
window.scrollTo(0, item.offsetTop - 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare the DOM for the selected item
|
|
||||||
function set_links_item(item_id)
|
|
||||||
{
|
|
||||||
var link = document.getElementById("current-item");
|
|
||||||
if (link) scroll_page_to(link);
|
|
||||||
|
|
||||||
var link = document.getElementById("original-item");
|
|
||||||
if (link) link.id = "original-" + link.getAttribute("data-item-id");
|
|
||||||
|
|
||||||
var link = document.getElementById("open-item");
|
|
||||||
if (link) link.id = "open-" + link.getAttribute("data-item-id");
|
|
||||||
|
|
||||||
var link = document.getElementById("original-" + item_id);
|
|
||||||
if (link) link.id = "original-item";
|
|
||||||
|
|
||||||
var link = document.getElementById("open-" + item_id);
|
|
||||||
if (link) link.id = "open-item";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the next item in the listing page
|
|
||||||
function find_next_item()
|
|
||||||
{
|
|
||||||
var items = document.getElementsByTagName("article");
|
|
||||||
|
|
||||||
if (! document.getElementById("current-item")) {
|
|
||||||
|
|
||||||
items[0].id = "current-item";
|
|
||||||
set_links_item(items[0].getAttribute("data-item-id"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
for (var i = 0, ilen = items.length; i < ilen; i++) {
|
|
||||||
|
|
||||||
if (items[i].id == "current-item") {
|
|
||||||
|
|
||||||
items[i].id = "item-" + items[i].getAttribute("data-item-id");
|
|
||||||
|
|
||||||
if (i + 1 < ilen) {
|
|
||||||
|
|
||||||
items[i + 1].id = "current-item";
|
|
||||||
set_links_item(items[i + 1].getAttribute("data-item-id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the previous item in the listing page
|
|
||||||
function find_previous_item()
|
|
||||||
{
|
|
||||||
var items = document.getElementsByTagName("article");
|
|
||||||
|
|
||||||
if (! document.getElementById("current-item")) {
|
|
||||||
|
|
||||||
items[items.length - 1].id = "current-item";
|
|
||||||
set_links_item(items[items.length - 1].getAttribute("data-item-id"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
for (var i = items.length - 1; i >= 0; i--) {
|
|
||||||
|
|
||||||
if (items[i].id == "current-item") {
|
|
||||||
|
|
||||||
items[i].id = "item-" + items[i].getAttribute("data-item-id");
|
|
||||||
|
|
||||||
if (i - 1 >= 0) {
|
|
||||||
|
|
||||||
items[i - 1].id = "current-item";
|
|
||||||
set_links_item(items[i - 1].getAttribute("data-item-id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we are on a listing page
|
|
||||||
function is_listing()
|
|
||||||
{
|
|
||||||
if (document.getElementById("listing")) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authentication with Mozilla Persona
|
|
||||||
function mozilla_auth(action)
|
|
||||||
{
|
|
||||||
navigator.id.watch({
|
|
||||||
onlogin: function(assertion) {
|
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open("POST", "?action=" + action, true);
|
|
||||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
|
||||||
xhr.setRequestHeader("Connection", "close");
|
|
||||||
|
|
||||||
xhr.onload = function () {
|
|
||||||
window.location.href = this.responseText;
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.send("token=" + assertion);
|
|
||||||
},
|
|
||||||
onlogout: function() {}
|
|
||||||
});
|
|
||||||
|
|
||||||
navigator.id.request();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Click event handler, if there is a "data-action" attribute execute the corresponding callback
|
|
||||||
document.onclick = function(e) {
|
|
||||||
|
|
||||||
var action = e.target.getAttribute("data-action");
|
|
||||||
|
|
||||||
if (action) {
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case 'refresh-all':
|
|
||||||
e.preventDefault();
|
|
||||||
refresh_all();
|
|
||||||
break;
|
|
||||||
case 'refresh-feed':
|
|
||||||
e.preventDefault();
|
|
||||||
var feed_id = e.target.getAttribute("data-feed-id");
|
|
||||||
refresh_feed(feed_id);
|
|
||||||
break;
|
|
||||||
case 'mark-read':
|
|
||||||
e.preventDefault();
|
|
||||||
var item_id = e.target.getAttribute("data-item-id");
|
|
||||||
mark_as_read(item_id);
|
|
||||||
break;
|
|
||||||
case 'mark-unread':
|
|
||||||
e.preventDefault();
|
|
||||||
var item_id = e.target.getAttribute("data-item-id");
|
|
||||||
mark_as_unread(item_id);
|
|
||||||
break;
|
|
||||||
case 'mark-all-read':
|
|
||||||
e.preventDefault();
|
|
||||||
mark_items_as_read("?action=unread");
|
|
||||||
break;
|
|
||||||
case 'mark-feed-read':
|
|
||||||
e.preventDefault();
|
|
||||||
mark_items_as_read("?action=feed-items&feed_id=" + e.target.getAttribute("data-feed-id"));
|
|
||||||
break;
|
|
||||||
case 'original-link':
|
|
||||||
var item_id = e.target.getAttribute("data-item-id");
|
|
||||||
mark_as_read(item_id);
|
|
||||||
break;
|
|
||||||
case 'download-item':
|
|
||||||
e.preventDefault();
|
|
||||||
download_item();
|
|
||||||
break;
|
|
||||||
case 'mozilla-login':
|
|
||||||
e.preventDefault();
|
|
||||||
mozilla_auth("mozilla-auth");
|
|
||||||
break;
|
|
||||||
case 'mozilla-link':
|
|
||||||
e.preventDefault();
|
|
||||||
mozilla_auth("mozilla-link");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keyboard handler, handle keyboard shortcuts
|
|
||||||
document.onkeypress = function(e) {
|
|
||||||
|
|
||||||
keyqueue.push(e.keyCode || e.which);
|
|
||||||
|
|
||||||
if (keyqueue[0] == 103) { // g
|
|
||||||
|
|
||||||
switch (keyqueue[1]) {
|
|
||||||
case undefined:
|
|
||||||
break;
|
|
||||||
case 117: // u
|
|
||||||
window.location.href = "?action=unread";
|
|
||||||
keyqueue = [];
|
|
||||||
break;
|
|
||||||
case 98: // b
|
|
||||||
window.location.href = "?action=bookmarks";
|
|
||||||
keyqueue = [];
|
|
||||||
break;
|
|
||||||
case 104: // h
|
|
||||||
window.location.href = "?action=history";
|
|
||||||
keyqueue = [];
|
|
||||||
break;
|
|
||||||
case 115: // s
|
|
||||||
window.location.href = "?action=feeds";
|
|
||||||
keyqueue = [];
|
|
||||||
break;
|
|
||||||
case 112: // p
|
|
||||||
window.location.href = "?action=config";
|
|
||||||
keyqueue = [];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
keyqueue = [];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
keyqueue = [];
|
|
||||||
|
|
||||||
switch (e.keyCode || e.which) {
|
|
||||||
case 100: // d
|
|
||||||
download_item();
|
|
||||||
break;
|
|
||||||
case 112: // p
|
|
||||||
case 107: // k
|
|
||||||
open_previous_item();
|
|
||||||
break;
|
|
||||||
case 110: // n
|
|
||||||
case 106: // j
|
|
||||||
open_next_item();
|
|
||||||
break;
|
|
||||||
case 118: // v
|
|
||||||
open_original_item();
|
|
||||||
break;
|
|
||||||
case 111: // o
|
|
||||||
open_item();
|
|
||||||
break;
|
|
||||||
case 109: // m
|
|
||||||
change_item_status();
|
|
||||||
break;
|
|
||||||
case 102: // f
|
|
||||||
bookmark_item();
|
|
||||||
break;
|
|
||||||
case 104: // h
|
|
||||||
open_previous_page();
|
|
||||||
break
|
|
||||||
case 108: // l
|
|
||||||
open_next_page();
|
|
||||||
break;
|
|
||||||
case 63: // ?
|
|
||||||
open("?action=show-help", "Help", "width=320,height=450,location=no,scrollbars=no,status=no,toolbar=no");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
141
assets/js/event.js
Normal file
141
assets/js/event.js
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
Miniflux.Event = (function() {
|
||||||
|
|
||||||
|
var queue = [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
ListenMouseEvents: function() {
|
||||||
|
|
||||||
|
document.onclick = function(e) {
|
||||||
|
|
||||||
|
var action = e.target.getAttribute("data-action");
|
||||||
|
|
||||||
|
if (action) {
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 'refresh-all':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.Feed.UpdateAll();
|
||||||
|
break;
|
||||||
|
case 'refresh-feed':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.Feed.Update(e.target.getAttribute("data-feed-id"));
|
||||||
|
break;
|
||||||
|
case 'mark-read':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.Item.MarkAsRead(e.target.getAttribute("data-item-id"));
|
||||||
|
break;
|
||||||
|
case 'mark-unread':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.Item.MarkAsUnread(e.target.getAttribute("data-item-id"));
|
||||||
|
break;
|
||||||
|
case 'bookmark':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.Item.SwitchBookmark(Miniflux.Item.Get(e.target.getAttribute("data-item-id")));
|
||||||
|
break;
|
||||||
|
case 'download-item':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.Item.DownloadContent();
|
||||||
|
break;
|
||||||
|
case 'original-link':
|
||||||
|
Miniflux.Item.OpenOriginal(e.target.getAttribute("data-item-id"));
|
||||||
|
break;
|
||||||
|
case 'mark-all-read':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.Item.MarkListingAsRead("?action=unread");
|
||||||
|
break;
|
||||||
|
case 'mark-feed-read':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.Item.MarkListingAsRead("?action=feed-items&feed_id=" + e.target.getAttribute("data-feed-id"));
|
||||||
|
break;
|
||||||
|
case 'mozilla-login':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.App.MozillaAuth("mozilla-auth");
|
||||||
|
break;
|
||||||
|
case 'mozilla-link':
|
||||||
|
e.preventDefault();
|
||||||
|
Miniflux.App.MozillaAuth("mozilla-link");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
ListenKeyboardEvents: function() {
|
||||||
|
|
||||||
|
document.onkeypress = function(e) {
|
||||||
|
|
||||||
|
queue.push(e.keyCode || e.which);
|
||||||
|
|
||||||
|
if (queue[0] == 103) { // g
|
||||||
|
|
||||||
|
switch (queue[1]) {
|
||||||
|
case undefined:
|
||||||
|
break;
|
||||||
|
case 117: // u
|
||||||
|
window.location.href = "?action=unread";
|
||||||
|
queue = [];
|
||||||
|
break;
|
||||||
|
case 98: // b
|
||||||
|
window.location.href = "?action=bookmarks";
|
||||||
|
queue = [];
|
||||||
|
break;
|
||||||
|
case 104: // h
|
||||||
|
window.location.href = "?action=history";
|
||||||
|
queue = [];
|
||||||
|
break;
|
||||||
|
case 115: // s
|
||||||
|
window.location.href = "?action=feeds";
|
||||||
|
queue = [];
|
||||||
|
break;
|
||||||
|
case 112: // p
|
||||||
|
window.location.href = "?action=config";
|
||||||
|
queue = [];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
queue = [];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
queue = [];
|
||||||
|
|
||||||
|
switch (e.keyCode || e.which) {
|
||||||
|
case 100: // d
|
||||||
|
Miniflux.Item.DownloadContent(Miniflux.Nav.GetCurrentItemId());
|
||||||
|
break;
|
||||||
|
case 112: // p
|
||||||
|
case 107: // k
|
||||||
|
Miniflux.Nav.SelectPreviousItem();
|
||||||
|
break;
|
||||||
|
case 110: // n
|
||||||
|
case 106: // j
|
||||||
|
Miniflux.Nav.SelectNextItem();
|
||||||
|
break;
|
||||||
|
case 118: // v
|
||||||
|
Miniflux.Item.OpenOriginal(Miniflux.Nav.GetCurrentItemId());
|
||||||
|
break;
|
||||||
|
case 111: // o
|
||||||
|
Miniflux.Item.Show(Miniflux.Nav.GetCurrentItemId());
|
||||||
|
break;
|
||||||
|
case 109: // m
|
||||||
|
Miniflux.Item.SwitchStatus(Miniflux.Nav.GetCurrentItem());
|
||||||
|
break;
|
||||||
|
case 102: // f
|
||||||
|
Miniflux.Item.SwitchBookmark(Miniflux.Nav.GetCurrentItem());
|
||||||
|
break;
|
||||||
|
case 104: // h
|
||||||
|
Miniflux.Nav.OpenPreviousPage();
|
||||||
|
break
|
||||||
|
case 108: // l
|
||||||
|
Miniflux.Nav.OpenNextPage();
|
||||||
|
break;
|
||||||
|
case 63: // ?
|
||||||
|
Miniflux.Nav.ShowHelp();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
93
assets/js/feed.js
Normal file
93
assets/js/feed.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
Miniflux.Feed = (function() {
|
||||||
|
|
||||||
|
// List of subscriptions
|
||||||
|
var feeds = [];
|
||||||
|
|
||||||
|
// List of feeds currently updating
|
||||||
|
var queue = [];
|
||||||
|
|
||||||
|
// Number of concurrent requests when updating all feeds
|
||||||
|
var queue_length = 5;
|
||||||
|
|
||||||
|
// Show the refresh icon when updating a feed
|
||||||
|
function showRefreshIcon(feed_id)
|
||||||
|
{
|
||||||
|
var container = document.getElementById("loading-feed-" + feed_id);
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
var img = document.createElement("img");
|
||||||
|
img.src = "assets/img/refresh.gif";
|
||||||
|
container.appendChild(img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide the refresh icon after update
|
||||||
|
function hideRefreshIcon(feed_id)
|
||||||
|
{
|
||||||
|
var container = document.getElementById("loading-feed-" + feed_id);
|
||||||
|
if (container) container.innerHTML = "";
|
||||||
|
|
||||||
|
var container = document.getElementById("last-checked-feed-" + feed_id);
|
||||||
|
if (container) container.innerHTML = container.getAttribute("data-after-update");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all subscriptions from the feeds page
|
||||||
|
function loadFeeds()
|
||||||
|
{
|
||||||
|
var links = document.getElementsByTagName("a");
|
||||||
|
|
||||||
|
for (var i = 0, ilen = links.length; i < ilen; i++) {
|
||||||
|
var feed_id = links[i].getAttribute('data-feed-id');
|
||||||
|
if (feed_id) feeds.push(parseInt(feed_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
Update: function(feed_id, callback) {
|
||||||
|
|
||||||
|
showRefreshIcon(feed_id);
|
||||||
|
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.onload = function() {
|
||||||
|
|
||||||
|
hideRefreshIcon(feed_id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (callback) {
|
||||||
|
callback(JSON.parse(this.responseText));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.open("POST", "?action=refresh-feed&feed_id=" + feed_id, true);
|
||||||
|
request.send();
|
||||||
|
},
|
||||||
|
UpdateAll: function() {
|
||||||
|
|
||||||
|
loadFeeds();
|
||||||
|
|
||||||
|
var interval = setInterval(function() {
|
||||||
|
|
||||||
|
while (feeds.length > 0 && queue.length < queue_length) {
|
||||||
|
|
||||||
|
var feed_id = feeds.shift();
|
||||||
|
queue.push(feed_id);
|
||||||
|
|
||||||
|
Miniflux.Feed.Update(feed_id, function(response) {
|
||||||
|
|
||||||
|
var index = queue.indexOf(response.feed_id);
|
||||||
|
if (index >= 0) queue.splice(index, 1);
|
||||||
|
|
||||||
|
if (feeds.length == 0 && queue.length == 0) {
|
||||||
|
clearInterval(interval);
|
||||||
|
window.location.href = "?action=unread";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
314
assets/js/item.js
Normal file
314
assets/js/item.js
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
Miniflux.Item = (function() {
|
||||||
|
|
||||||
|
function getItem(item_id)
|
||||||
|
{
|
||||||
|
var item = document.getElementById("item-" + item_id);
|
||||||
|
|
||||||
|
if (! item) {
|
||||||
|
item = document.getElementById("current-item");
|
||||||
|
if (item.getAttribute("data-item-id") != item_id) item = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeBookmarkLabel(item_id)
|
||||||
|
{
|
||||||
|
var link = document.getElementById("bookmark-" + item_id);
|
||||||
|
|
||||||
|
if (link && link.getAttribute("data-reverse-label")) {
|
||||||
|
var content = link.innerHTML;
|
||||||
|
link.innerHTML = link.getAttribute("data-reverse-label");
|
||||||
|
link.setAttribute("data-reverse-label", content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showItemBookmarked(item_id, item)
|
||||||
|
{
|
||||||
|
if (! Miniflux.Nav.IsListing()) {
|
||||||
|
|
||||||
|
var link = document.getElementById("bookmark-" + item_id);
|
||||||
|
if (link) link.innerHTML = "★";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
var link = document.getElementById("show-" + item_id);
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
var icon = document.createElement("span");
|
||||||
|
icon.id = "bookmark-icon-" + item_id;
|
||||||
|
icon.appendChild(document.createTextNode("★ "));
|
||||||
|
link.parentNode.insertBefore(icon, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
changeBookmarkLabel(item_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideItemBookmarked(item_id, item)
|
||||||
|
{
|
||||||
|
if (! Miniflux.Nav.IsListing()) {
|
||||||
|
|
||||||
|
var link = document.getElementById("bookmark-" + item_id);
|
||||||
|
if (link) link.innerHTML = "☆";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
var icon = document.getElementById("bookmark-icon-" + item_id);
|
||||||
|
if (icon) icon.parentNode.removeChild(icon);
|
||||||
|
|
||||||
|
changeBookmarkLabel(item_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeStatusLabel(item_id)
|
||||||
|
{
|
||||||
|
var link = document.getElementById("status-" + item_id);
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
var content = link.innerHTML;
|
||||||
|
link.innerHTML = link.getAttribute("data-reverse-label");
|
||||||
|
link.setAttribute("data-reverse-label", content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showItemAsRead(item_id)
|
||||||
|
{
|
||||||
|
var item = getItem(item_id);
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
if (item.getAttribute("data-hide")) {
|
||||||
|
hideItem(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
item.setAttribute("data-item-status", "read");
|
||||||
|
changeStatusLabel(item_id);
|
||||||
|
|
||||||
|
// Show icon
|
||||||
|
var link = document.getElementById("show-" + item_id);
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
link.className = "read";
|
||||||
|
|
||||||
|
var icon = document.createElement("span");
|
||||||
|
icon.id = "read-icon-" + item_id;
|
||||||
|
icon.appendChild(document.createTextNode("☑ "));
|
||||||
|
link.parentNode.insertBefore(icon, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change action
|
||||||
|
link = document.getElementById("status-" + item_id);
|
||||||
|
if (link) link.setAttribute("data-action", "mark-unread");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showItemAsUnread(item_id)
|
||||||
|
{
|
||||||
|
var item = getItem(item_id);
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
if (item.getAttribute("data-hide")) {
|
||||||
|
hideItem(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
item.setAttribute("data-item-status", "unread");
|
||||||
|
changeStatusLabel(item_id);
|
||||||
|
|
||||||
|
// Remove icon
|
||||||
|
var link = document.getElementById("show-" + item_id);
|
||||||
|
if (link) link.className = "";
|
||||||
|
|
||||||
|
var icon = document.getElementById("read-icon-" + item_id);
|
||||||
|
if (icon) icon.parentNode.removeChild(icon);
|
||||||
|
|
||||||
|
// Change action
|
||||||
|
link = document.getElementById("status-" + item_id);
|
||||||
|
if (link) link.setAttribute("data-action", "mark-read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideItem(item)
|
||||||
|
{
|
||||||
|
Miniflux.Nav.SelectNextItem();
|
||||||
|
|
||||||
|
item.parentNode.removeChild(item);
|
||||||
|
var container = document.getElementById("page-counter");
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
|
||||||
|
counter = parseInt(container.textContent.trim(), 10) - 1;
|
||||||
|
|
||||||
|
if (counter == 0) {
|
||||||
|
window.location = "?action=feeds¬hing_to_read=1";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
container.textContent = counter + " ";
|
||||||
|
document.title = "miniflux (" + counter + ")";
|
||||||
|
document.getElementById("nav-counter").textContent = "(" + counter + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function markAsRead(item_id)
|
||||||
|
{
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.onload = function() {
|
||||||
|
if (Miniflux.Nav.IsListing()) showItemAsRead(item_id);
|
||||||
|
};
|
||||||
|
request.open("POST", "?action=mark-item-read&id=" + item_id, true);
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function markAsUnread(item_id)
|
||||||
|
{
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.onload = function() {
|
||||||
|
if (Miniflux.Nav.IsListing()) showItemAsUnread(item_id);
|
||||||
|
};
|
||||||
|
request.open("POST", "?action=mark-item-unread&id=" + item_id, true);
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function bookmark(item, value)
|
||||||
|
{
|
||||||
|
var item_id = item.getAttribute("data-item-id");
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.onload = function() {
|
||||||
|
|
||||||
|
item.setAttribute("data-item-bookmark", value);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
showItemBookmarked(item_id, item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hideItemBookmarked(item_id, item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.open("POST", "?action=bookmark&id=" + item_id + "&value=" + value, true);
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
Get: getItem,
|
||||||
|
MarkAsRead: markAsRead,
|
||||||
|
MarkAsUnread: markAsUnread,
|
||||||
|
SwitchBookmark: function(item) {
|
||||||
|
|
||||||
|
var bookmarked = item.getAttribute("data-item-bookmark");
|
||||||
|
|
||||||
|
if (bookmarked == "1") {
|
||||||
|
bookmark(item, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bookmark(item, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SwitchStatus: function(item) {
|
||||||
|
|
||||||
|
var item_id = item.getAttribute("data-item-id");
|
||||||
|
var status = item.getAttribute("data-item-status");
|
||||||
|
|
||||||
|
if (status == "read") {
|
||||||
|
markAsUnread(item_id);
|
||||||
|
}
|
||||||
|
else if (status == "unread") {
|
||||||
|
markAsRead(item_id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ChangeStatus: function(item_id, status) {
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case "read":
|
||||||
|
markAsRead(item_id);
|
||||||
|
break;
|
||||||
|
case "unread":
|
||||||
|
markAsUnread(item_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Show: function(item_id) {
|
||||||
|
var link = document.getElementById("show-" + item_id);
|
||||||
|
if (link) link.click();
|
||||||
|
},
|
||||||
|
OpenOriginal: function(item_id) {
|
||||||
|
|
||||||
|
var link = document.getElementById("original-" + item_id);
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
if (getItem(item_id).getAttribute("data-item-status") == "unread") markAsRead(item_id);
|
||||||
|
link.removeAttribute("data-action");
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DownloadContent: function() {
|
||||||
|
|
||||||
|
var container = document.getElementById("download-item");
|
||||||
|
if (! container) return;
|
||||||
|
|
||||||
|
var item_id = container.getAttribute("data-item-id");
|
||||||
|
var message = container.getAttribute("data-before-message");
|
||||||
|
|
||||||
|
var img = document.createElement("img");
|
||||||
|
img.src = "./assets/img/refresh.gif";
|
||||||
|
|
||||||
|
container.innerHTML = "";
|
||||||
|
container.className = "downloading";
|
||||||
|
container.appendChild(img);
|
||||||
|
container.appendChild(document.createTextNode(" " + message));
|
||||||
|
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.onload = function() {
|
||||||
|
|
||||||
|
var response = JSON.parse(request.responseText);
|
||||||
|
|
||||||
|
if (response.result) {
|
||||||
|
|
||||||
|
var content = document.getElementById("item-content");
|
||||||
|
if (content) content.innerHTML = response.content;
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
var message = container.getAttribute("data-after-message");
|
||||||
|
container.innerHTML = "";
|
||||||
|
container.appendChild(document.createTextNode(" " + message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
var message = container.getAttribute("data-failure-message");
|
||||||
|
container.innerHTML = "";
|
||||||
|
container.appendChild(document.createTextNode(" " + message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.open("POST", "?action=download-item&id=" + item_id, true);
|
||||||
|
request.send();
|
||||||
|
},
|
||||||
|
MarkListingAsRead: function(redirect) {
|
||||||
|
var articles = document.getElementsByTagName("article");
|
||||||
|
var listing = [];
|
||||||
|
|
||||||
|
for (var i = 0, ilen = articles.length; i < ilen; i++) {
|
||||||
|
listing.push(articles[i].getAttribute("data-item-id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.onload = function() {
|
||||||
|
window.location.href = redirect;
|
||||||
|
};
|
||||||
|
|
||||||
|
request.open("POST", "?action=mark-items-as-read", true);
|
||||||
|
request.send(JSON.stringify(listing));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
118
assets/js/nav.js
Normal file
118
assets/js/nav.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
Miniflux.Nav = (function() {
|
||||||
|
|
||||||
|
function scrollPageTo(item)
|
||||||
|
{
|
||||||
|
var clientHeight = pageYOffset + document.documentElement.clientHeight;
|
||||||
|
var itemPosition = item.offsetTop + item.offsetHeight;
|
||||||
|
|
||||||
|
if (clientHeight - itemPosition < 0 || clientHeight - item.offsetTop > document.documentElement.clientHeight) {
|
||||||
|
window.scrollTo(0, item.offsetTop - 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNextItem()
|
||||||
|
{
|
||||||
|
var items = document.getElementsByTagName("article");
|
||||||
|
|
||||||
|
if (! document.getElementById("current-item")) {
|
||||||
|
|
||||||
|
items[0].id = "current-item";
|
||||||
|
scrollPageTo(items[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
for (var i = 0, ilen = items.length; i < ilen; i++) {
|
||||||
|
|
||||||
|
if (items[i].id == "current-item") {
|
||||||
|
|
||||||
|
items[i].id = "item-" + items[i].getAttribute("data-item-id");
|
||||||
|
|
||||||
|
if (i + 1 < ilen) {
|
||||||
|
items[i + 1].id = "current-item";
|
||||||
|
scrollPageTo(items[i + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findPreviousItem()
|
||||||
|
{
|
||||||
|
var items = document.getElementsByTagName("article");
|
||||||
|
|
||||||
|
if (! document.getElementById("current-item")) {
|
||||||
|
|
||||||
|
items[items.length - 1].id = "current-item";
|
||||||
|
scrollPageTo(items[items.length - 1]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
for (var i = items.length - 1; i >= 0; i--) {
|
||||||
|
|
||||||
|
if (items[i].id == "current-item") {
|
||||||
|
|
||||||
|
items[i].id = "item-" + items[i].getAttribute("data-item-id");
|
||||||
|
|
||||||
|
if (i - 1 >= 0) {
|
||||||
|
items[i - 1].id = "current-item";
|
||||||
|
scrollPageTo(items[i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isListing()
|
||||||
|
{
|
||||||
|
if (document.getElementById("listing")) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
GetCurrentItem: function() {
|
||||||
|
return document.getElementById("current-item");
|
||||||
|
},
|
||||||
|
GetCurrentItemId: function() {
|
||||||
|
var item = Miniflux.Nav.GetCurrentItem();
|
||||||
|
if (item) return item.getAttribute("data-item-id");
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
OpenNextPage: function() {
|
||||||
|
var link = document.getElementById("next-page");
|
||||||
|
if (link) link.click();
|
||||||
|
},
|
||||||
|
OpenPreviousPage: function() {
|
||||||
|
var link = document.getElementById("previous-page");
|
||||||
|
if (link) link.click();
|
||||||
|
},
|
||||||
|
SelectNextItem: function() {
|
||||||
|
var link = document.getElementById("next-item");
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
|
else if (isListing()) {
|
||||||
|
findNextItem();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SelectPreviousItem: function() {
|
||||||
|
var link = document.getElementById("previous-item");
|
||||||
|
|
||||||
|
if (link) {
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
|
else if (isListing()) {
|
||||||
|
findPreviousItem();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ShowHelp: function() {
|
||||||
|
open("?action=show-help", "Help", "width=320,height=450,location=no,scrollbars=no,status=no,toolbar=no");
|
||||||
|
},
|
||||||
|
IsListing: isListing
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
41
index.php
41
index.php
@ -23,7 +23,7 @@ Session\open(dirname($_SERVER['PHP_SELF']));
|
|||||||
// Called before each action
|
// Called before each action
|
||||||
Router\before(function($action) {
|
Router\before(function($action) {
|
||||||
|
|
||||||
$ignore_actions = array('login', 'google-auth', 'google-redirect-auth', 'mozilla-auth');
|
$ignore_actions = array('js', 'login', 'google-auth', 'google-redirect-auth', 'mozilla-auth');
|
||||||
|
|
||||||
if (! isset($_SESSION['user']) && ! in_array($action, $ignore_actions)) {
|
if (! isset($_SESSION['user']) && ! in_array($action, $ignore_actions)) {
|
||||||
Response\redirect('?action=login');
|
Response\redirect('?action=login');
|
||||||
@ -49,6 +49,20 @@ Router\before(function($action) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Javascript assets
|
||||||
|
Router\get_action('js', function() {
|
||||||
|
|
||||||
|
$data = file_get_contents('assets/js/app.js');
|
||||||
|
$data .= file_get_contents('assets/js/feed.js');
|
||||||
|
$data .= file_get_contents('assets/js/item.js');
|
||||||
|
$data .= file_get_contents('assets/js/event.js');
|
||||||
|
$data .= file_get_contents('assets/js/nav.js');
|
||||||
|
$data .= 'Miniflux.App.Run();';
|
||||||
|
|
||||||
|
Response\js($data);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Logout and destroy session
|
// Logout and destroy session
|
||||||
Router\get_action('logout', function() {
|
Router\get_action('logout', function() {
|
||||||
|
|
||||||
@ -199,15 +213,6 @@ Router\post_action('mark-item-unread', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Ajax call to bookmark an item
|
|
||||||
Router\post_action('bookmark-item', function() {
|
|
||||||
|
|
||||||
$id = Request\param('id');
|
|
||||||
Model\bookmark_item($id);
|
|
||||||
Response\json(array('Ok'));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Ajax call change item status
|
// Ajax call change item status
|
||||||
Router\post_action('change-item-status', function() {
|
Router\post_action('change-item-status', function() {
|
||||||
|
|
||||||
@ -220,6 +225,18 @@ Router\post_action('change-item-status', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Ajax call to add or remove a bookmark
|
||||||
|
Router\post_action('bookmark', function() {
|
||||||
|
|
||||||
|
$id = Request\param('id');
|
||||||
|
$value = Request\int_param('value');
|
||||||
|
|
||||||
|
Model\set_bookmark_value($id, $value);
|
||||||
|
|
||||||
|
Response\json(array('id' => $id, 'value' => $value));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Add new bookmark
|
// Add new bookmark
|
||||||
Router\get_action('bookmark', function() {
|
Router\get_action('bookmark', function() {
|
||||||
|
|
||||||
@ -253,6 +270,8 @@ Router\get_action('history', function() {
|
|||||||
'updated',
|
'updated',
|
||||||
Model\get_config_value('items_sorting_direction')
|
Model\get_config_value('items_sorting_direction')
|
||||||
),
|
),
|
||||||
|
'order' => '',
|
||||||
|
'direction' => '',
|
||||||
'nb_items' => $nb_items,
|
'nb_items' => $nb_items,
|
||||||
'offset' => $offset,
|
'offset' => $offset,
|
||||||
'items_per_page' => Model\get_config_value('items_per_page'),
|
'items_per_page' => Model\get_config_value('items_per_page'),
|
||||||
@ -294,6 +313,8 @@ Router\get_action('bookmarks', function() {
|
|||||||
$nb_items = Model\count_bookmarks();
|
$nb_items = Model\count_bookmarks();
|
||||||
|
|
||||||
Response\html(Template\layout('bookmarks', array(
|
Response\html(Template\layout('bookmarks', array(
|
||||||
|
'order' => '',
|
||||||
|
'direction' => '',
|
||||||
'items' => Model\get_bookmarks($offset, Model\get_config_value('items_per_page')),
|
'items' => Model\get_bookmarks($offset, Model\get_config_value('items_per_page')),
|
||||||
'nb_items' => $nb_items,
|
'nb_items' => $nb_items,
|
||||||
'offset' => $offset,
|
'offset' => $offset,
|
||||||
|
@ -575,6 +575,7 @@ function get_bookmarks($offset = null, $limit = null)
|
|||||||
'items.title',
|
'items.title',
|
||||||
'items.updated',
|
'items.updated',
|
||||||
'items.url',
|
'items.url',
|
||||||
|
'items.bookmark',
|
||||||
'items.status',
|
'items.status',
|
||||||
'items.content',
|
'items.content',
|
||||||
'items.feed_id',
|
'items.feed_id',
|
||||||
|
21
templates/bookmark_links.php
Normal file
21
templates/bookmark_links.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php if ($item['bookmark']): ?>
|
||||||
|
<a
|
||||||
|
id="bookmark-<?= $item['id'] ?>"
|
||||||
|
href="?action=bookmark&value=0&id=<?= $item['id'] ?>&menu=<?= $menu ?>&offset=<?= $offset ?>&source=<?= $source ?>"
|
||||||
|
data-action="bookmark"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
data-reverse-label="<?= t('bookmark') ?>"
|
||||||
|
>
|
||||||
|
<?= t('remove bookmark') ?>
|
||||||
|
</a> |
|
||||||
|
<?php else: ?>
|
||||||
|
<a
|
||||||
|
id="bookmark-<?= $item['id'] ?>"
|
||||||
|
href="?action=bookmark&value=1&id=<?= $item['id'] ?>&menu=<?= $menu ?>&offset=<?= $offset ?>&source=<?= $source ?>"
|
||||||
|
data-action="bookmark"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
data-reverse-label="<?= t('remove bookmark') ?>"
|
||||||
|
>
|
||||||
|
<?= t('bookmark') ?>
|
||||||
|
</a> |
|
||||||
|
<?php endif ?>
|
@ -1,7 +1,5 @@
|
|||||||
<?php if (empty($items)): ?>
|
<?php if (empty($items)): ?>
|
||||||
|
|
||||||
<p class="alert alert-info"><?= t('No bookmark') ?></p>
|
<p class="alert alert-info"><?= t('No bookmark') ?></p>
|
||||||
|
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
@ -9,53 +7,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="items" id="listing">
|
<section class="items" id="listing">
|
||||||
<?php foreach ($items as $item): ?>
|
<?php foreach ($items as $item): ?>
|
||||||
<article id="item-<?= $item['id'] ?>" data-item-id="<?= $item['id'] ?>">
|
<?= \PicoTools\Template\load('item', array('item' => $item, 'menu' => $menu, 'offset' => $offset, 'hide' => false)) ?>
|
||||||
<h2>
|
<?php endforeach ?>
|
||||||
<a
|
|
||||||
href="?action=show&menu=bookmarks&id=<?= $item['id'] ?>"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
id="open-<?= $item['id'] ?>"
|
|
||||||
>
|
|
||||||
<?= Helper\escape($item['title']) ?>
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
<p class="preview">
|
|
||||||
<?= Helper\escape(Helper\summary(strip_tags($item['content']), 50, 300)) ?>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="?action=feed-items&feed_id=<?= $item['feed_id'] ?>" title="<?= t('Show only this subscription') ?>"><?= Helper\escape($item['feed_title']) ?></a> |
|
|
||||||
<?= dt('%e %B %Y %k:%M', $item['updated']) ?> |
|
|
||||||
|
|
||||||
<span class="hide-mobile">
|
|
||||||
<a href="?action=bookmark&value=0&id=<?= $item['id'] ?>&menu=bookmarks&offset=<?= $offset ?>">
|
|
||||||
<?= t('remove bookmark') ?>
|
|
||||||
</a> |
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="<?= $item['url'] ?>"
|
|
||||||
id="original-<?= $item['id'] ?>"
|
|
||||||
rel="noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
>
|
|
||||||
<?= t('original link') ?>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
<?php endforeach ?>
|
|
||||||
|
|
||||||
<nav id="items-paging">
|
|
||||||
<?php if ($offset > 0): ?>
|
|
||||||
<a id="previous-page" href="?action=bookmarks&offset=<?= ($offset - $items_per_page) ?>">« <?= t('Previous page') ?></a>
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<?php if (($nb_items - $offset) > $items_per_page): ?>
|
|
||||||
<a id="next-page" href="?action=bookmarks&offset=<?= ($offset + $items_per_page) ?>"><?= t('Next page') ?> »</a>
|
|
||||||
<?php endif ?>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
|
<?= \PicoTools\Template\load('paging', array('menu' => $menu, 'nb_items' => $nb_items, 'items_per_page' => $items_per_page, 'offset' => $offset, 'order' => $order, 'direction' => $direction)) ?>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
@ -1,9 +1,7 @@
|
|||||||
<?php if (empty($items)): ?>
|
<?php if (empty($items)): ?>
|
||||||
|
|
||||||
<p class="alert">
|
<p class="alert">
|
||||||
<?= t('This subscription is empty, <a href="?action=unread">go back to unread items</a>') ?>
|
<?= t('This subscription is empty, <a href="?action=unread">go back to unread items</a>') ?>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
@ -19,81 +17,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="items" id="listing">
|
<section class="items" id="listing">
|
||||||
<?php foreach ($items as $item): ?>
|
<?php foreach ($items as $item): ?>
|
||||||
<article id="item-<?= $item['id'] ?>" data-item-id="<?= $item['id'] ?>" data-item-page="<?= $menu ?>">
|
<?= \PicoTools\Template\load('item', array('item' => $item, 'menu' => $menu, 'offset' => $offset, 'hide' => false)) ?>
|
||||||
<h2>
|
<?php endforeach ?>
|
||||||
<?= $item['bookmark'] ? '<span id="bookmark-icon-'.$item['id'].'">★ </span>' : '' ?>
|
|
||||||
<?= $item['status'] === 'read' ? '<span id="read-icon-'.$item['id'].'">☑ </span>' : '' ?>
|
|
||||||
<a
|
|
||||||
href="?action=show&menu=feed-items&id=<?= $item['id'] ?>"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
id="open-<?= $item['id'] ?>"
|
|
||||||
<?= $item['status'] === 'read' ? 'class="read"' : '' ?>
|
|
||||||
>
|
|
||||||
<?= Helper\escape($item['title']) ?>
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
<p class="preview">
|
|
||||||
<?= Helper\escape(Helper\summary(strip_tags($item['content']), 50, 300)) ?>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<?= Helper\get_host_from_url($item['url']) ?> |
|
|
||||||
<span class="hide-mobile"><?= dt('%e %B %Y %k:%M', $item['updated']) ?> |</span>
|
|
||||||
|
|
||||||
<span class="hide-mobile">
|
<div id="bottom-menu">
|
||||||
<?php if ($item['bookmark']): ?>
|
<a href="?action=mark-feed-as-read&feed_id=<?= $feed['id'] ?>" data-action="mark-feed-read" data-feed-id="<?= $feed['id'] ?>"><?= t('mark all as read') ?></a>
|
||||||
<a id="bookmark-<?= $item['id'] ?>" href="?action=bookmark&value=0&id=<?= $item['id'] ?>&menu=feed-items&offset=<?= $offset ?>&feed_id=<?= $item['feed_id'] ?>"><?= t('remove bookmark') ?></a> |
|
</div>
|
||||||
<?php else: ?>
|
|
||||||
<a id="bookmark-<?= $item['id'] ?>" href="?action=bookmark&value=1&id=<?= $item['id'] ?>&menu=feed-items&offset=<?= $offset ?>&feed_id=<?= $item['feed_id'] ?>"><?= t('bookmark') ?></a> |
|
|
||||||
<?php endif ?>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<?php if ($item['status'] == 'unread'): ?>
|
|
||||||
<a
|
|
||||||
href="?action=mark-item-read&id=<?= $item['id'] ?>&offset=<?= $offset ?>&redirect=feed-items&feed_id=<?= $item['feed_id'] ?>"
|
|
||||||
>
|
|
||||||
<?= t('mark as read') ?>
|
|
||||||
</a> |
|
|
||||||
<?php else: ?>
|
|
||||||
<a
|
|
||||||
href="?action=mark-item-unread&id=<?= $item['id'] ?>&offset=<?= $offset ?>&redirect=feed-items&feed_id=<?= $item['feed_id'] ?>"
|
|
||||||
>
|
|
||||||
<?= t('mark as unread') ?>
|
|
||||||
</a> |
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<span class="hide-mobile">
|
|
||||||
<a href="?action=mark-item-removed&id=<?= $item['id'] ?>&offset=<?= $offset ?>&redirect=feed-items&feed_id=<?= $item['feed_id'] ?>"><?= t('remove') ?></a> |
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="<?= $item['url'] ?>"
|
|
||||||
id="original-<?= $item['id'] ?>"
|
|
||||||
rel="noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
>
|
|
||||||
<?= t('original link') ?>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
<?php endforeach ?>
|
|
||||||
|
|
||||||
<div id="bottom-menu">
|
|
||||||
<a href="?action=mark-feed-as-read&feed_id=<?= $feed['id'] ?>" data-action="mark-feed-read" data-feed-id="<?= $feed['id'] ?>"><?= t('mark all as read') ?></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="items-paging">
|
|
||||||
<?php if ($offset > 0): ?>
|
|
||||||
<a id="previous-page" href="?action=feed-items&feed_id=<?= $feed['id'] ?>&offset=<?= ($offset - $items_per_page) ?>&order=<?= $order ?>&direction=<?= $direction ?>">« <?= t('Previous page') ?></a>
|
|
||||||
-
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<?php if (($nb_items - $offset) > $items_per_page): ?>
|
|
||||||
<a id="next-page" href="?action=feed-items&feed_id=<?= $feed['id'] ?>&offset=<?= ($offset + $items_per_page) ?>&order=<?= $order ?>&direction=<?= $direction ?>"><?= t('Next page') ?> »</a>
|
|
||||||
<?php endif ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<?= \PicoTools\Template\load('paging', array('menu' => $menu, 'nb_items' => $nb_items, 'items_per_page' => $items_per_page, 'offset' => $offset, 'order' => $order, 'direction' => $direction, 'feed_id' => $feed['id'])) ?>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
@ -10,68 +10,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="items" id="listing">
|
<section class="items" id="listing">
|
||||||
<?php foreach ($items as $item): ?>
|
<?php foreach ($items as $item): ?>
|
||||||
<article id="item-<?= $item['id'] ?>" data-item-id="<?= $item['id'] ?>" data-item-page="<?= $menu ?>" data-hide="true">
|
<?= \PicoTools\Template\load('item', array('item' => $item, 'menu' => $menu, 'offset' => $offset, 'hide' => true)) ?>
|
||||||
<h2>
|
<?php endforeach ?>
|
||||||
<?= $item['bookmark'] ? '★ ' : '' ?>
|
|
||||||
<a
|
|
||||||
href="?action=show&menu=history&id=<?= $item['id'] ?>"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
id="open-<?= $item['id'] ?>"
|
|
||||||
>
|
|
||||||
<?= Helper\escape($item['title']) ?>
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
<p class="preview">
|
|
||||||
<?= Helper\escape(Helper\summary(strip_tags($item['content']), 50, 300)) ?>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="?action=feed-items&feed_id=<?= $item['feed_id'] ?>" title="<?= t('Show only this subscription') ?>"><?= Helper\escape($item['feed_title']) ?></a> |
|
|
||||||
|
|
||||||
<span class="hide-mobile"><?= dt('%e %B %Y %k:%M', $item['updated']) ?> |</span>
|
|
||||||
|
|
||||||
<?php if (! $item['bookmark']): ?>
|
|
||||||
<span class="hide-mobile">
|
|
||||||
<a id="bookmark-<?= $item['id'] ?>" href="?action=bookmark&value=1&id=<?= $item['id'] ?>&menu=history&offset=<?= $offset ?>"><?= t('bookmark') ?></a> |
|
|
||||||
</span>
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="?action=mark-item-unread&id=<?= $item['id'] ?>&offset=<?= $offset ?>"
|
|
||||||
data-action="mark-unread"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
data-hide="true"
|
|
||||||
>
|
|
||||||
<?= t('mark as unread') ?>
|
|
||||||
</a> |
|
|
||||||
|
|
||||||
<span class="hide-mobile">
|
|
||||||
<a href="?action=mark-item-removed&id=<?= $item['id'] ?>&offset=<?= $offset ?>"><?= t('remove') ?></a> |
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="<?= $item['url'] ?>"
|
|
||||||
id="original-<?= $item['id'] ?>"
|
|
||||||
rel="noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
>
|
|
||||||
<?= t('original link') ?>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
<?php endforeach ?>
|
|
||||||
|
|
||||||
<nav id="items-paging">
|
|
||||||
<?php if ($offset > 0): ?>
|
|
||||||
<a id="previous-page" href="?action=history&offset=<?= ($offset - $items_per_page) ?>">« <?= t('Previous page') ?></a>
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<?php if (($nb_items - $offset) > $items_per_page): ?>
|
|
||||||
<a id="next-page" href="?action=history&offset=<?= ($offset + $items_per_page) ?>"><?= t('Next page') ?> »</a>
|
|
||||||
<?php endif ?>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
|
<?= \PicoTools\Template\load('paging', array('menu' => $menu, 'nb_items' => $nb_items, 'items_per_page' => $items_per_page, 'offset' => $offset, 'order' => $order, 'direction' => $direction)) ?>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
48
templates/item.php
Normal file
48
templates/item.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<article
|
||||||
|
id="item-<?= $item['id'] ?>"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
data-item-status="<?= $item['status'] ?>"
|
||||||
|
data-item-bookmark="<?= $item['bookmark'] ?>"
|
||||||
|
data-item-page="<?= $menu ?>"
|
||||||
|
<?= $hide ? 'data-hide="true"' : '' ?>
|
||||||
|
>
|
||||||
|
<h2>
|
||||||
|
<?= $item['bookmark'] ? '<span id="bookmark-icon-'.$item['id'].'">★ </span>' : '' ?>
|
||||||
|
<?= $item['status'] === 'read' ? '<span id="read-icon-'.$item['id'].'">☑ </span>' : '' ?>
|
||||||
|
<a
|
||||||
|
href="?action=show&menu=<?= $menu ?>&id=<?= $item['id'] ?>"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
id="show-<?= $item['id'] ?>"
|
||||||
|
<?= $item['status'] === 'read' ? 'class="read"' : '' ?>
|
||||||
|
>
|
||||||
|
<?= Helper\escape($item['title']) ?>
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
<p class="preview">
|
||||||
|
<?= Helper\escape(Helper\summary(strip_tags($item['content']), 50, 300)) ?>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<?php if (! isset($item['feed_title'])): ?>
|
||||||
|
<?= Helper\get_host_from_url($item['url']) ?> |
|
||||||
|
<?php else: ?>
|
||||||
|
<a href="?action=feed-items&feed_id=<?= $item['feed_id'] ?>" title="<?= t('Show only this subscription') ?>"><?= Helper\escape($item['feed_title']) ?></a> |
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
<span class="hide-mobile">
|
||||||
|
<?= dt('%e %B %Y %k:%M', $item['updated']) ?> |
|
||||||
|
<?= \PicoTools\Template\load('bookmark_links', array('item' => $item, 'menu' => $menu, 'offset' => $offset, 'source' => '')) ?>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<?= \PicoTools\Template\load('status_links', array('item' => $item, 'redirect' => $menu, 'offset' => $offset)) ?>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="<?= $item['url'] ?>"
|
||||||
|
id="original-<?= $item['id'] ?>"
|
||||||
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
>
|
||||||
|
<?= t('original link') ?>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</article>
|
@ -9,9 +9,9 @@
|
|||||||
<link rel="apple-touch-icon" sizes="72x72" href="assets/img/touch-icon-ipad.png">
|
<link rel="apple-touch-icon" sizes="72x72" href="assets/img/touch-icon-ipad.png">
|
||||||
<link rel="apple-touch-icon" sizes="114x114" href="assets/img/touch-icon-iphone-retina.png">
|
<link rel="apple-touch-icon" sizes="114x114" href="assets/img/touch-icon-iphone-retina.png">
|
||||||
<link rel="apple-touch-icon" sizes="144x144" href="assets/img/touch-icon-ipad-retina.png">
|
<link rel="apple-touch-icon" sizes="144x144" href="assets/img/touch-icon-ipad-retina.png">
|
||||||
<title><?= isset($title) ? Helper\escape($title) : 'miniflux' ?></title>
|
<title><?= isset($title) ? Helper\escape($title) : 'Miniflux' ?></title>
|
||||||
<link href="<?= Helper\css() ?>" rel="stylesheet" media="screen">
|
<link href="<?= Helper\css() ?>" rel="stylesheet" media="screen">
|
||||||
<script type="text/javascript" src="assets/js/app.js?version=<?= filemtime('assets/js/app.js') ?>" defer></script>
|
<script type="text/javascript" src="?action=js" defer></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
<link rel="apple-touch-icon" sizes="72x72" href="./assets/img/touch-icon-ipad.png">
|
<link rel="apple-touch-icon" sizes="72x72" href="./assets/img/touch-icon-ipad.png">
|
||||||
<link rel="apple-touch-icon" sizes="114x114" href="./assets/img/touch-icon-iphone-retina.png">
|
<link rel="apple-touch-icon" sizes="114x114" href="./assets/img/touch-icon-iphone-retina.png">
|
||||||
<link rel="apple-touch-icon" sizes="144x144" href="./assets/img/touch-icon-ipad-retina.png">
|
<link rel="apple-touch-icon" sizes="144x144" href="./assets/img/touch-icon-ipad-retina.png">
|
||||||
<title>miniflux</title>
|
<title>Miniflux</title>
|
||||||
<link href="<?= Helper\css() ?>" rel="stylesheet" media="screen">
|
<link href="<?= Helper\css() ?>" rel="stylesheet" media="screen">
|
||||||
<script type="text/javascript" src="assets/js/app.js?version=<?= filemtime('assets/js/app.js') ?>" defer></script>
|
|
||||||
<?php if ($mozilla_auth_enable): ?>
|
<?php if ($mozilla_auth_enable): ?>
|
||||||
|
<script type="text/javascript" src="?action=js" defer></script>
|
||||||
<script type="text/javascript" src="assets/js/persona.js" defer></script>
|
<script type="text/javascript" src="assets/js/persona.js" defer></script>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</head>
|
</head>
|
||||||
|
9
templates/paging.php
Normal file
9
templates/paging.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div id="items-paging">
|
||||||
|
<?php if ($offset > 0): ?>
|
||||||
|
<a id="previous-page" href="?action=<?= $menu ?>&offset=<?= ($offset - $items_per_page) ?>&order=<?= $order ?>&direction=<?= $direction ?><?= isset($feed_id) ? '&feed_id='.$feed_id : '' ?>">« <?= t('Previous page') ?></a>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
<?php if (($nb_items - $offset) > $items_per_page): ?>
|
||||||
|
<a id="next-page" href="?action=<?= $menu ?>&offset=<?= ($offset + $items_per_page) ?>&order=<?= $order ?>&direction=<?= $direction ?><?= isset($feed_id) ? '&feed_id='.$feed_id : '' ?>"><?= t('Next page') ?> »</a>
|
||||||
|
<?php endif ?>
|
||||||
|
</div>
|
@ -3,23 +3,44 @@
|
|||||||
<p class="alert alert-info"><?= t('Item not found') ?></p>
|
<p class="alert alert-info"><?= t('Item not found') ?></p>
|
||||||
|
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<article class="item" id="current-item" data-item-id="<?= $item['id'] ?>" data-item-page="<?= $menu ?>">
|
<article
|
||||||
|
class="item"
|
||||||
|
id="current-item"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
data-item-status="<?= $item['status'] ?>"
|
||||||
|
data-item-bookmark="<?= $item['bookmark'] ?>"
|
||||||
|
data-item-page="<?= $menu ?>"
|
||||||
|
>
|
||||||
<h1>
|
<h1>
|
||||||
<a href="<?= $item['url'] ?>" rel="noreferrer" target="_blank" id="original-item">
|
<a href="<?= $item['url'] ?>" rel="noreferrer" target="_blank" id="original-<?= $item['id'] ?>">
|
||||||
<?= Helper\escape($item['title']) ?>
|
<?= Helper\escape($item['title']) ?>
|
||||||
</a>
|
</a>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p class="infos">
|
<p class="infos">
|
||||||
<?php if ($item['bookmark']): ?>
|
<?php if ($item['bookmark']): ?>
|
||||||
<a id="bookmark-<?=$item['id'] ?>" href="?action=bookmark&value=0&id=<?= $item['id'] ?>&source=show&menu=<?= $menu ?>" title="<?= t('remove bookmark') ?>" class="bookmark-icon">★</a>
|
<a
|
||||||
|
id="bookmark-<?=$item['id'] ?>"
|
||||||
|
href="?action=bookmark&value=0&id=<?= $item['id'] ?>&source=show&menu=<?= $menu ?>"
|
||||||
|
title="<?= t('remove bookmark') ?>"
|
||||||
|
class="bookmark-icon"
|
||||||
|
data-action="bookmark"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
>★</a>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<a id="bookmark-<?=$item['id'] ?>" href="?action=bookmark&value=1&id=<?= $item['id'] ?>&source=show&menu=<?= $menu ?>" title="<?= t('bookmark') ?>" class="bookmark-icon">☆</a>
|
<a
|
||||||
|
id="bookmark-<?=$item['id'] ?>"
|
||||||
|
href="?action=bookmark&value=1&id=<?= $item['id'] ?>&source=show&menu=<?= $menu ?>"
|
||||||
|
title="<?= t('bookmark') ?>"
|
||||||
|
class="bookmark-icon"
|
||||||
|
data-action="bookmark"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
>☆</a>
|
||||||
<?php endif ?> |
|
<?php endif ?> |
|
||||||
|
|
||||||
<a href="?action=feed-items&feed_id=<?= $feed['id'] ?>"><?= Helper\escape($feed['title']) ?></a> |
|
<a href="?action=feed-items&feed_id=<?= $feed['id'] ?>"><?= Helper\escape($feed['title']) ?></a> |
|
||||||
|
|
||||||
<span class="hide-mobile"><?= dt('%e %B %Y - %k:%M', $item['updated']) ?> |</span>
|
<span class="hide-mobile"><?= dt('%e %B %Y %k:%M', $item['updated']) ?> |</span>
|
||||||
|
|
||||||
<span id="download-item"
|
<span id="download-item"
|
||||||
data-item-id="<?= $item['id'] ?>"
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
28
templates/status_links.php
Normal file
28
templates/status_links.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php if ($item['status'] == 'unread'): ?>
|
||||||
|
<a
|
||||||
|
id="status-<?= $item['id'] ?>"
|
||||||
|
href="?action=mark-item-read&id=<?= $item['id'] ?>&offset=<?= $offset ?>&redirect=<?= $redirect ?>&feed_id=<?= $item['feed_id'] ?>"
|
||||||
|
data-action="mark-read"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
data-reverse-label="<?= t('mark as unread') ?>"
|
||||||
|
>
|
||||||
|
<?= t('mark as read') ?>
|
||||||
|
</a> |
|
||||||
|
<?php else: ?>
|
||||||
|
<a
|
||||||
|
id="status-<?= $item['id'] ?>"
|
||||||
|
href="?action=mark-item-unread&id=<?= $item['id'] ?>&offset=<?= $offset ?>&redirect=<?= $redirect ?>&feed_id=<?= $item['feed_id'] ?>"
|
||||||
|
data-action="mark-unread"
|
||||||
|
data-item-id="<?= $item['id'] ?>"
|
||||||
|
data-reverse-label="<?= t('mark as read') ?>"
|
||||||
|
>
|
||||||
|
<?= t('mark as unread') ?>
|
||||||
|
</a> |
|
||||||
|
<?php endif ?>
|
||||||
|
<span class="hide-mobile">
|
||||||
|
<a
|
||||||
|
href="?action=mark-item-removed&id=<?= $item['id'] ?>&offset=<?= $offset ?>&redirect=<?= $redirect ?>&feed_id=<?= $item['feed_id'] ?>"
|
||||||
|
>
|
||||||
|
<?= t('remove') ?>
|
||||||
|
</a> |
|
||||||
|
</span>
|
@ -1,7 +1,5 @@
|
|||||||
<?php if (empty($items)): ?>
|
<?php if (empty($items)): ?>
|
||||||
|
|
||||||
<p class="alert alert-info"><?= t('Nothing to read') ?></p>
|
<p class="alert alert-info"><?= t('Nothing to read') ?></p>
|
||||||
|
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
@ -17,70 +15,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="items" id="listing">
|
<section class="items" id="listing">
|
||||||
<?php foreach ($items as $item): ?>
|
<?php foreach ($items as $item): ?>
|
||||||
<article id="item-<?= $item['id'] ?>" data-item-id="<?= $item['id'] ?>" data-item-page="<?= $menu ?>" data-hide="true">
|
<?= \PicoTools\Template\load('item', array('item' => $item, 'menu' => $menu, 'offset' => $offset, 'hide' => true)) ?>
|
||||||
<h2>
|
<?php endforeach ?>
|
||||||
<?= $item['bookmark'] ? '★ ' : '' ?>
|
|
||||||
<a
|
|
||||||
href="?action=show&menu=unread&id=<?= $item['id'] ?>"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
id="open-<?= $item['id'] ?>"
|
|
||||||
>
|
|
||||||
<?= Helper\escape($item['title']) ?>
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
<p class="preview">
|
|
||||||
<?= Helper\escape(Helper\summary(strip_tags($item['content']), 50, 300)) ?>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="?action=feed-items&feed_id=<?= $item['feed_id'] ?>" title="<?= t('Show only this subscription') ?>"><?= Helper\escape($item['feed_title']) ?></a> |
|
|
||||||
<span class="hide-mobile"><?= dt('%e %B %Y %k:%M', $item['updated']) ?> |</span>
|
|
||||||
|
|
||||||
<span class="hide-mobile">
|
<div id="bottom-menu">
|
||||||
<?php if ($item['bookmark']): ?>
|
<a href="?action=mark-as-read" data-action="mark-all-read"><?= t('mark all as read') ?></a>
|
||||||
<a id="bookmark-<?= $item['id'] ?>" href="?action=bookmark&value=0&id=<?= $item['id'] ?>&menu=unread&offset=<?= $offset ?>"><?= t('remove bookmark') ?></a> |
|
</div>
|
||||||
<?php else: ?>
|
|
||||||
<a id="bookmark-<?= $item['id'] ?>" href="?action=bookmark&value=1&id=<?= $item['id'] ?>&menu=unread&offset=<?= $offset ?>"><?= t('bookmark') ?></a> |
|
|
||||||
<?php endif ?>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="?action=mark-item-read&id=<?= $item['id'] ?>&offset=<?= $offset ?>"
|
|
||||||
data-action="mark-read"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
data-hide="true"
|
|
||||||
>
|
|
||||||
<?= t('mark as read') ?>
|
|
||||||
</a> |
|
|
||||||
<a
|
|
||||||
href="<?= $item['url'] ?>"
|
|
||||||
id="original-<?= $item['id'] ?>"
|
|
||||||
rel="noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
data-item-id="<?= $item['id'] ?>"
|
|
||||||
data-action="original-link"
|
|
||||||
data-hide="true"
|
|
||||||
>
|
|
||||||
<?= t('original link') ?>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
<?php endforeach ?>
|
|
||||||
|
|
||||||
<div id="bottom-menu">
|
|
||||||
<a href="?action=mark-as-read" data-action="mark-all-read"><?= t('mark all as read') ?></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="items-paging">
|
|
||||||
<?php if ($offset > 0): ?>
|
|
||||||
<a id="previous-page" href="?action=unread&offset=<?= ($offset - $items_per_page) ?>&order=<?= $order ?>&direction=<?= $direction ?>">« <?= t('Previous page') ?></a>
|
|
||||||
<?php endif ?>
|
|
||||||
|
|
||||||
<?php if (($nb_items - $offset) > $items_per_page): ?>
|
|
||||||
<a id="next-page" href="?action=unread&offset=<?= ($offset + $items_per_page) ?>&order=<?= $order ?>&direction=<?= $direction ?>"><?= t('Next page') ?> »</a>
|
|
||||||
<?php endif ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<?= \PicoTools\Template\load('paging', array('menu' => $menu, 'nb_items' => $nb_items, 'items_per_page' => $items_per_page, 'offset' => $offset, 'order' => $order, 'direction' => $direction)) ?>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
9
vendor/PicoTools/AuthProvider.php
vendored
9
vendor/PicoTools/AuthProvider.php
vendored
@ -77,9 +77,16 @@ function mozilla_validate($token)
|
|||||||
'content' => http_build_query($params, '', '&')
|
'content' => http_build_query($params, '', '&')
|
||||||
)));
|
)));
|
||||||
|
|
||||||
$body = file_get_contents('https://verifier.login.persona.org/verify', false, $context);
|
$body = @file_get_contents('https://verifier.login.persona.org/verify', false, $context);
|
||||||
$response = json_decode($body, true);
|
$response = json_decode($body, true);
|
||||||
|
|
||||||
|
if (! $response) {
|
||||||
|
return array(
|
||||||
|
false,
|
||||||
|
''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
$response['status'] === 'okay',
|
$response['status'] === 'okay',
|
||||||
$response['email']
|
$response['email']
|
||||||
|
Loading…
Reference in New Issue
Block a user