Improve items paging, get config values, add option to set the number of items per page and add comments
This commit is contained in:
parent
3af0f43207
commit
a79211d47f
@ -58,9 +58,9 @@
|
|||||||
if (item) {
|
if (item) {
|
||||||
|
|
||||||
var item_id = item.getAttribute("data-item-id");
|
var item_id = item.getAttribute("data-item-id");
|
||||||
var redirect = item.getAttribute("data-item-page");
|
var link = document.getElementById("bookmark-" + item_id);
|
||||||
|
|
||||||
window.location = "?action=bookmark&value=1&id=" + item_id + "&redirect=" + redirect;
|
if (link) link.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,11 +354,7 @@
|
|||||||
|
|
||||||
function is_listing()
|
function is_listing()
|
||||||
{
|
{
|
||||||
if (document.getElementById("listing")) {
|
if (document.getElementById("listing")) return true;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,12 +10,9 @@ require 'schema.php';
|
|||||||
require 'model.php';
|
require 'model.php';
|
||||||
|
|
||||||
|
|
||||||
const DB_VERSION = 8;
|
const DB_VERSION = 9;
|
||||||
const APP_VERSION = 'master';
|
const APP_VERSION = 'master';
|
||||||
const APP_USERAGENT = 'Miniflux - http://miniflux.net';
|
|
||||||
const HTTP_TIMEOUT = 10;
|
const HTTP_TIMEOUT = 10;
|
||||||
const LIMIT_ALL = -1;
|
|
||||||
const ITEMS_PER_PAGE = 80;
|
|
||||||
|
|
||||||
|
|
||||||
function get_db_filename()
|
function get_db_filename()
|
||||||
|
@ -15,11 +15,11 @@ else {
|
|||||||
$options = $_GET;
|
$options = $_GET;
|
||||||
}
|
}
|
||||||
|
|
||||||
$limit = ! empty($options['limit']) && ctype_digit($options['limit']) ? (int) $options['limit'] : LIMIT_ALL;
|
$limit = ! empty($options['limit']) && ctype_digit($options['limit']) ? (int) $options['limit'] : Model\LIMIT_ALL;
|
||||||
$update_interval = ! empty($options['update-interval']) && ctype_digit($options['update-interval']) ? (int) $options['update-interval'] : null;
|
$update_interval = ! empty($options['update-interval']) && ctype_digit($options['update-interval']) ? (int) $options['update-interval'] : null;
|
||||||
$call_interval = ! empty($options['call-interval']) && ctype_digit($options['call-interval']) ? (int) $options['call-interval'] : null;
|
$call_interval = ! empty($options['call-interval']) && ctype_digit($options['call-interval']) ? (int) $options['call-interval'] : null;
|
||||||
|
|
||||||
if ($update_interval !== null && $call_interval !== null && $limit === LIMIT_ALL && $update_interval >= $call_interval) {
|
if ($update_interval !== null && $call_interval !== null && $limit === Model\LIMIT_ALL && $update_interval >= $call_interval) {
|
||||||
|
|
||||||
$feeds_count = \PicoTools\singleton('db')->table('feeds')->count();
|
$feeds_count = \PicoTools\singleton('db')->table('feeds')->count();
|
||||||
$limit = ceil($feeds_count / ($update_interval / $call_interval));
|
$limit = ceil($feeds_count / ($update_interval / $call_interval));
|
||||||
|
115
index.php
115
index.php
@ -18,6 +18,7 @@ use PicoTools\Template;
|
|||||||
Session\open(dirname($_SERVER['PHP_SELF']));
|
Session\open(dirname($_SERVER['PHP_SELF']));
|
||||||
|
|
||||||
|
|
||||||
|
// Called before each action
|
||||||
Router\before(function($action) {
|
Router\before(function($action) {
|
||||||
|
|
||||||
if ($action !== 'login' && ! isset($_SESSION['user'])) {
|
if ($action !== 'login' && ! isset($_SESSION['user'])) {
|
||||||
@ -54,6 +55,7 @@ Router\before(function($action) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Logout and destroy session
|
||||||
Router\get_action('logout', function() {
|
Router\get_action('logout', function() {
|
||||||
|
|
||||||
Session\close();
|
Session\close();
|
||||||
@ -61,12 +63,10 @@ Router\get_action('logout', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Display form login
|
||||||
Router\get_action('login', function() {
|
Router\get_action('login', function() {
|
||||||
|
|
||||||
if (isset($_SESSION['user'])) {
|
if (isset($_SESSION['user'])) Response\redirect('index.php');
|
||||||
|
|
||||||
Response\redirect('./index.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
Response\html(Template\load('login', array(
|
Response\html(Template\load('login', array(
|
||||||
'errors' => array(),
|
'errors' => array(),
|
||||||
@ -75,15 +75,13 @@ Router\get_action('login', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Check credentials and redirect to unread items
|
||||||
Router\post_action('login', function() {
|
Router\post_action('login', function() {
|
||||||
|
|
||||||
$values = Request\values();
|
$values = Request\values();
|
||||||
list($valid, $errors) = Model\validate_login($values);
|
list($valid, $errors) = Model\validate_login($values);
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) Response\redirect('?action=unread');
|
||||||
|
|
||||||
Response\redirect('?action=default');
|
|
||||||
}
|
|
||||||
|
|
||||||
Response\html(Template\load('login', array(
|
Response\html(Template\load('login', array(
|
||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
@ -92,6 +90,7 @@ Router\post_action('login', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Show item without bottom nav
|
||||||
Router\get_action('show', function() {
|
Router\get_action('show', function() {
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
@ -105,6 +104,7 @@ Router\get_action('show', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Show item with bottom nav
|
||||||
Router\get_action('read', function() {
|
Router\get_action('read', function() {
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
@ -121,30 +121,46 @@ Router\get_action('read', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Mark item as read and redirect to the listing page
|
||||||
Router\get_action('mark-item-read', function() {
|
Router\get_action('mark-item-read', function() {
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
|
$redirect = Request\param('redirect', 'unread');
|
||||||
|
$offset = Request\int_param('offset', 0);
|
||||||
|
|
||||||
Model\set_item_read($id);
|
Model\set_item_read($id);
|
||||||
Response\Redirect('?action='.Request\param('redirect', 'default'));
|
|
||||||
|
Response\Redirect('?action='.$redirect.'&offset='.$offset);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Mark item as unread and redirect to the listing page
|
||||||
Router\get_action('mark-item-unread', function() {
|
Router\get_action('mark-item-unread', function() {
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
|
$redirect = Request\param('redirect', 'history');
|
||||||
|
$offset = Request\int_param('offset', 0);
|
||||||
|
|
||||||
Model\set_item_unread($id);
|
Model\set_item_unread($id);
|
||||||
Response\Redirect('?action='.Request\param('redirect', 'history'));
|
|
||||||
|
Response\Redirect('?action='.$redirect.'&offset='.$offset);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Mark item as removed and redirect to the listing page
|
||||||
Router\get_action('mark-item-removed', function() {
|
Router\get_action('mark-item-removed', function() {
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
|
$redirect = Request\param('redirect', 'history');
|
||||||
|
$offset = Request\int_param('offset', 0);
|
||||||
|
|
||||||
Model\set_item_removed($id);
|
Model\set_item_removed($id);
|
||||||
Response\Redirect('?action='.Request\param('redirect', 'history'));
|
|
||||||
|
Response\Redirect('?action='.$redirect.'&offset='.$offset);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Ajax call to mark item read
|
||||||
Router\post_action('mark-item-read', function() {
|
Router\post_action('mark-item-read', function() {
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
@ -153,6 +169,7 @@ Router\post_action('mark-item-read', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Ajax call to mark item unread
|
||||||
Router\post_action('mark-item-unread', function() {
|
Router\post_action('mark-item-unread', function() {
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
@ -161,6 +178,7 @@ Router\post_action('mark-item-unread', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Ajax call to bookmark an item
|
||||||
Router\post_action('bookmark-item', function() {
|
Router\post_action('bookmark-item', function() {
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
@ -169,11 +187,25 @@ Router\post_action('bookmark-item', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Ajax call change item status
|
||||||
|
Router\post_action('change-item-status', function() {
|
||||||
|
|
||||||
|
$id = Model\decode_item_id(Request\param('id'));
|
||||||
|
|
||||||
|
Response\json(array(
|
||||||
|
'item_id' => Model\encode_item_id($id),
|
||||||
|
'status' => Model\switch_item_status($id)
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Add new bookmark
|
||||||
Router\get_action('bookmark', function() {
|
Router\get_action('bookmark', function() {
|
||||||
|
|
||||||
$param_id = Request\param('id');
|
$param_id = Request\param('id');
|
||||||
$id = Model\decode_item_id($param_id);
|
$id = Model\decode_item_id($param_id);
|
||||||
$redirect = Request\param('redirect', 'unread');
|
$redirect = Request\param('redirect', 'unread');
|
||||||
|
$offset = Request\int_param('offset', 0);
|
||||||
|
|
||||||
Model\set_bookmark_value($id, Request\int_param('value'));
|
Model\set_bookmark_value($id, Request\int_param('value'));
|
||||||
|
|
||||||
@ -186,52 +218,46 @@ Router\get_action('bookmark', function() {
|
|||||||
Response\Redirect('?action=read&id='.$param_id);
|
Response\Redirect('?action=read&id='.$param_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Response\Redirect('?action='.$redirect);
|
Response\Redirect('?action='.$redirect.'&offset='.$offset);
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Router\post_action('change-item-status', function() {
|
|
||||||
|
|
||||||
$id = Model\decode_item_id(Request\param('id'));
|
|
||||||
|
|
||||||
Response\json(array(
|
|
||||||
'item_id' => Model\encode_item_id($id),
|
|
||||||
'status' => Model\switch_item_status($id)
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Display history page
|
||||||
Router\get_action('history', function() {
|
Router\get_action('history', function() {
|
||||||
|
|
||||||
$offset = Request\int_param('offset', 0);
|
$offset = Request\int_param('offset', 0);
|
||||||
$nb_items = Model\count_items('read');
|
$nb_items = Model\count_items('read');
|
||||||
|
|
||||||
Response\html(Template\layout('history', array(
|
Response\html(Template\layout('history', array(
|
||||||
'items' => Model\get_read_items($offset, ITEMS_PER_PAGE),
|
'items' => Model\get_read_items($offset, Model\get_config_value('items_per_page')),
|
||||||
'nb_items' => $nb_items,
|
'nb_items' => $nb_items,
|
||||||
'offset' => $offset,
|
'offset' => $offset,
|
||||||
|
'items_per_page' => Model\get_config_value('items_per_page'),
|
||||||
'menu' => 'history',
|
'menu' => 'history',
|
||||||
'title' => t('History').' ('.$nb_items.')'
|
'title' => t('History').' ('.$nb_items.')'
|
||||||
)));
|
)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Display bookmarks page
|
||||||
Router\get_action('bookmarks', function() {
|
Router\get_action('bookmarks', function() {
|
||||||
|
|
||||||
$offset = Request\int_param('offset', 0);
|
$offset = Request\int_param('offset', 0);
|
||||||
$nb_items = Model\count_bookmarks();
|
$nb_items = Model\count_bookmarks();
|
||||||
|
|
||||||
Response\html(Template\layout('bookmarks', array(
|
Response\html(Template\layout('bookmarks', array(
|
||||||
'items' => Model\get_bookmarks($offset, 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,
|
||||||
|
'items_per_page' => Model\get_config_value('items_per_page'),
|
||||||
'menu' => 'bookmarks',
|
'menu' => 'bookmarks',
|
||||||
'title' => t('Bookmarks').' ('.$nb_items.')'
|
'title' => t('Bookmarks').' ('.$nb_items.')'
|
||||||
)));
|
)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Router\get_action('confirm-remove', function() {
|
// Confirmation box to remove a feed
|
||||||
|
Router\get_action('confirm-remove-feed', function() {
|
||||||
|
|
||||||
$id = Request\int_param('feed_id');
|
$id = Request\int_param('feed_id');
|
||||||
|
|
||||||
@ -243,7 +269,8 @@ Router\get_action('confirm-remove', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Router\get_action('remove', function() {
|
// Remove a feed
|
||||||
|
Router\get_action('remove-feed', function() {
|
||||||
|
|
||||||
$id = Request\int_param('feed_id');
|
$id = Request\int_param('feed_id');
|
||||||
|
|
||||||
@ -260,25 +287,22 @@ Router\get_action('remove', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Refresh one feed and redirect to unread items
|
||||||
Router\get_action('refresh-feed', function() {
|
Router\get_action('refresh-feed', function() {
|
||||||
|
|
||||||
$id = Request\int_param('feed_id');
|
$id = Request\int_param('feed_id');
|
||||||
|
if ($id) Model\update_feed($id);
|
||||||
if ($id) {
|
|
||||||
|
|
||||||
Model\update_feed($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Response\redirect('?action=unread');
|
Response\redirect('?action=unread');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Ajax call to refresh one feed
|
||||||
Router\post_action('refresh-feed', function() {
|
Router\post_action('refresh-feed', function() {
|
||||||
|
|
||||||
$id = Request\int_param('feed_id');
|
$id = Request\int_param('feed_id');
|
||||||
|
|
||||||
if ($id) {
|
if ($id) {
|
||||||
|
|
||||||
Response\json(array('feed_id' => $id, 'result' => Model\update_feed($id)));
|
Response\json(array('feed_id' => $id, 'result' => Model\update_feed($id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +310,7 @@ Router\post_action('refresh-feed', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Mark all unread items as read
|
||||||
Router\get_action('mark-as-read', function() {
|
Router\get_action('mark-as-read', function() {
|
||||||
|
|
||||||
Model\mark_as_read();
|
Model\mark_as_read();
|
||||||
@ -293,6 +318,7 @@ Router\get_action('mark-as-read', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Confirmation box to flush history
|
||||||
Router\get_action('confirm-flush-history', function() {
|
Router\get_action('confirm-flush-history', function() {
|
||||||
|
|
||||||
Response\html(Template\layout('confirm_flush_items', array(
|
Response\html(Template\layout('confirm_flush_items', array(
|
||||||
@ -302,6 +328,7 @@ Router\get_action('confirm-flush-history', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Flush history
|
||||||
Router\get_action('flush-history', function() {
|
Router\get_action('flush-history', function() {
|
||||||
|
|
||||||
Model\mark_as_removed();
|
Model\mark_as_removed();
|
||||||
@ -309,6 +336,7 @@ Router\get_action('flush-history', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Refresh all feeds, used when Javascript is disabled
|
||||||
Router\get_action('refresh-all', function() {
|
Router\get_action('refresh-all', function() {
|
||||||
|
|
||||||
Model\update_feeds();
|
Model\update_feeds();
|
||||||
@ -317,6 +345,7 @@ Router\get_action('refresh-all', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Display all feeds
|
||||||
Router\get_action('feeds', function() {
|
Router\get_action('feeds', function() {
|
||||||
|
|
||||||
Response\html(Template\layout('feeds', array(
|
Response\html(Template\layout('feeds', array(
|
||||||
@ -328,6 +357,7 @@ Router\get_action('feeds', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Display form to add one feed
|
||||||
Router\get_action('add', function() {
|
Router\get_action('add', function() {
|
||||||
|
|
||||||
Response\html(Template\layout('add', array(
|
Response\html(Template\layout('add', array(
|
||||||
@ -339,6 +369,7 @@ Router\get_action('add', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Add the feed
|
||||||
Router\post_action('add', function() {
|
Router\post_action('add', function() {
|
||||||
|
|
||||||
if (Model\import_feed($_POST['url'])) {
|
if (Model\import_feed($_POST['url'])) {
|
||||||
@ -359,6 +390,7 @@ Router\post_action('add', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Optimize the database manually
|
||||||
Router\get_action('optimize-db', function() {
|
Router\get_action('optimize-db', function() {
|
||||||
|
|
||||||
\PicoTools\singleton('db')->getConnection()->exec('VACUUM');
|
\PicoTools\singleton('db')->getConnection()->exec('VACUUM');
|
||||||
@ -366,6 +398,7 @@ Router\get_action('optimize-db', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Download the compressed database
|
||||||
Router\get_action('download-db', function() {
|
Router\get_action('download-db', function() {
|
||||||
|
|
||||||
Response\force_download('db.sqlite.gz');
|
Response\force_download('db.sqlite.gz');
|
||||||
@ -373,6 +406,7 @@ Router\get_action('download-db', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// OPML export
|
||||||
Router\get_action('export', function() {
|
Router\get_action('export', function() {
|
||||||
|
|
||||||
Response\force_download('feeds.opml');
|
Response\force_download('feeds.opml');
|
||||||
@ -380,6 +414,7 @@ Router\get_action('export', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// OPML import form
|
||||||
Router\get_action('import', function() {
|
Router\get_action('import', function() {
|
||||||
|
|
||||||
Response\html(Template\layout('import', array(
|
Response\html(Template\layout('import', array(
|
||||||
@ -390,6 +425,7 @@ Router\get_action('import', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// OPML importation
|
||||||
Router\post_action('import', function() {
|
Router\post_action('import', function() {
|
||||||
|
|
||||||
if (Model\import_feeds(Request\file_content('file'))) {
|
if (Model\import_feeds(Request\file_content('file'))) {
|
||||||
@ -405,6 +441,7 @@ Router\post_action('import', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Display preferences page
|
||||||
Router\get_action('config', function() {
|
Router\get_action('config', function() {
|
||||||
|
|
||||||
Response\html(Template\layout('config', array(
|
Response\html(Template\layout('config', array(
|
||||||
@ -413,12 +450,14 @@ Router\get_action('config', function() {
|
|||||||
'db_size' => filesize(get_db_filename()),
|
'db_size' => filesize(get_db_filename()),
|
||||||
'languages' => Model\get_languages(),
|
'languages' => Model\get_languages(),
|
||||||
'autoflush_options' => Model\get_autoflush_options(),
|
'autoflush_options' => Model\get_autoflush_options(),
|
||||||
|
'paging_options' => Model\get_paging_options(),
|
||||||
'menu' => 'config',
|
'menu' => 'config',
|
||||||
'title' => t('Preferences')
|
'title' => t('Preferences')
|
||||||
)));
|
)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Update preferences
|
||||||
Router\post_action('config', function() {
|
Router\post_action('config', function() {
|
||||||
|
|
||||||
$values = Request\values() + array('nocontent' => 0);
|
$values = Request\values() + array('nocontent' => 0);
|
||||||
@ -444,30 +483,30 @@ Router\post_action('config', function() {
|
|||||||
'db_size' => filesize(get_db_filename()),
|
'db_size' => filesize(get_db_filename()),
|
||||||
'languages' => Model\get_languages(),
|
'languages' => Model\get_languages(),
|
||||||
'autoflush_options' => Model\get_autoflush_options(),
|
'autoflush_options' => Model\get_autoflush_options(),
|
||||||
|
'paging_options' => Model\get_paging_options(),
|
||||||
'menu' => 'config',
|
'menu' => 'config',
|
||||||
'title' => t('Preferences')
|
'title' => t('Preferences')
|
||||||
)));
|
)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Display unread items
|
||||||
Router\notfound(function() {
|
Router\notfound(function() {
|
||||||
|
|
||||||
Model\autoflush();
|
Model\autoflush();
|
||||||
|
|
||||||
$offset = Request\int_param('offset', 0);
|
$offset = Request\int_param('offset', 0);
|
||||||
$items = Model\get_unread_items($offset, ITEMS_PER_PAGE);
|
$items = Model\get_unread_items($offset, Model\get_config_value('items_per_page'));
|
||||||
$nb_items = Model\count_items('unread');;
|
$nb_items = Model\count_items('unread');;
|
||||||
|
|
||||||
if ($nb_items === 0) {
|
if ($nb_items === 0) Response\redirect('?action=feeds¬hing_to_read=1');
|
||||||
|
|
||||||
Response\redirect('?action=feeds¬hing_to_read=1');
|
|
||||||
}
|
|
||||||
|
|
||||||
Response\html(Template\layout('unread_items', array(
|
Response\html(Template\layout('unread_items', array(
|
||||||
'items' => $items,
|
'items' => $items,
|
||||||
'nb_items' => $nb_items,
|
'nb_items' => $nb_items,
|
||||||
'nb_unread_items' => $nb_items,
|
'nb_unread_items' => $nb_items,
|
||||||
'offset' => $offset,
|
'offset' => $offset,
|
||||||
|
'items_per_page' => Model\get_config_value('items_per_page'),
|
||||||
'title' => 'miniflux ('.$nb_items.')',
|
'title' => 'miniflux ('.$nb_items.')',
|
||||||
'menu' => 'unread'
|
'menu' => 'unread'
|
||||||
)));
|
)));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'Items per page' => 'Artikel pro Seite',
|
||||||
'Previous page' => 'Vorheriger Seite',
|
'Previous page' => 'Vorheriger Seite',
|
||||||
'Next page' => 'Nächster Seite',
|
'Next page' => 'Nächster Seite',
|
||||||
'Do not fetch the content of articles' => 'Lade die Inhalte der Feeds nicht',
|
'Do not fetch the content of articles' => 'Lade die Inhalte der Feeds nicht',
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
'Items per page' => 'Nombre d\'éléments par page',
|
||||||
'Previous page' => 'Page précédente',
|
'Previous page' => 'Page précédente',
|
||||||
'Next page' => 'Page suivante',
|
'Next page' => 'Page suivante',
|
||||||
'Do not fetch the content of articles' => 'Ne pas récupérer le contenu des articles',
|
'Do not fetch the content of articles' => 'Ne pas récupérer le contenu des articles',
|
||||||
|
62
model.php
62
model.php
@ -13,6 +13,7 @@ require_once 'vendor/SimpleValidator/Validators/MaxLength.php';
|
|||||||
require_once 'vendor/SimpleValidator/Validators/MinLength.php';
|
require_once 'vendor/SimpleValidator/Validators/MinLength.php';
|
||||||
require_once 'vendor/SimpleValidator/Validators/Integer.php';
|
require_once 'vendor/SimpleValidator/Validators/Integer.php';
|
||||||
require_once 'vendor/SimpleValidator/Validators/Equals.php';
|
require_once 'vendor/SimpleValidator/Validators/Equals.php';
|
||||||
|
require_once 'vendor/SimpleValidator/Validators/Integer.php';
|
||||||
|
|
||||||
use SimpleValidator\Validator;
|
use SimpleValidator\Validator;
|
||||||
use SimpleValidator\Validators;
|
use SimpleValidator\Validators;
|
||||||
@ -21,6 +22,10 @@ use PicoFeed\Reader;
|
|||||||
use PicoFeed\Export;
|
use PicoFeed\Export;
|
||||||
|
|
||||||
|
|
||||||
|
const HTTP_USERAGENT = 'Miniflux - http://miniflux.net';
|
||||||
|
const LIMIT_ALL = -1;
|
||||||
|
|
||||||
|
|
||||||
function get_languages()
|
function get_languages()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
@ -43,6 +48,18 @@ function get_autoflush_options()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function get_paging_options()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
50 => 50,
|
||||||
|
100 => 100,
|
||||||
|
150 => 150,
|
||||||
|
200 => 200,
|
||||||
|
250 => 250,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function encode_item_id($input)
|
function encode_item_id($input)
|
||||||
{
|
{
|
||||||
return strtr(base64_encode($input), '+/=', '-_,');
|
return strtr(base64_encode($input), '+/=', '-_,');
|
||||||
@ -97,7 +114,7 @@ function import_feeds($content)
|
|||||||
function import_feed($url)
|
function import_feed($url)
|
||||||
{
|
{
|
||||||
$reader = new Reader;
|
$reader = new Reader;
|
||||||
$resource = $reader->download($url, '', '', HTTP_TIMEOUT, APP_USERAGENT);
|
$resource = $reader->download($url, '', '', HTTP_TIMEOUT, HTTP_USERAGENT);
|
||||||
|
|
||||||
$parser = $reader->getParser();
|
$parser = $reader->getParser();
|
||||||
|
|
||||||
@ -157,16 +174,13 @@ function update_feed($feed_id)
|
|||||||
$feed['last_modified'],
|
$feed['last_modified'],
|
||||||
$feed['etag'],
|
$feed['etag'],
|
||||||
HTTP_TIMEOUT,
|
HTTP_TIMEOUT,
|
||||||
APP_USERAGENT
|
HTTP_USERAGENT
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update the `last_checked` column each time, HTTP cache or not
|
// Update the `last_checked` column each time, HTTP cache or not
|
||||||
update_feed_last_checked($feed_id);
|
update_feed_last_checked($feed_id);
|
||||||
|
|
||||||
if (! $resource->isModified()) {
|
if (! $resource->isModified()) return true;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$parser = $reader->getParser();
|
$parser = $reader->getParser();
|
||||||
|
|
||||||
@ -437,7 +451,7 @@ function mark_as_removed()
|
|||||||
|
|
||||||
function autoflush()
|
function autoflush()
|
||||||
{
|
{
|
||||||
$autoflush = \PicoTools\singleton('db')->table('config')->findOneColumn('autoflush');
|
$autoflush = get_config_value('autoflush');
|
||||||
|
|
||||||
if ($autoflush) {
|
if ($autoflush) {
|
||||||
|
|
||||||
@ -453,7 +467,7 @@ function autoflush()
|
|||||||
|
|
||||||
function update_items($feed_id, array $items)
|
function update_items($feed_id, array $items)
|
||||||
{
|
{
|
||||||
$nocontent = (bool) \PicoTools\singleton('db')->table('config')->findOneColumn('nocontent');
|
$nocontent = (bool) get_config_value('nocontent');
|
||||||
|
|
||||||
$items_in_feed = array();
|
$items_in_feed = array();
|
||||||
$db = \PicoTools\singleton('db');
|
$db = \PicoTools\singleton('db');
|
||||||
@ -501,11 +515,32 @@ function update_items($feed_id, array $items)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function get_config_value($name)
|
||||||
|
{
|
||||||
|
if (! isset($_SESSION)) {
|
||||||
|
|
||||||
|
return \PicoTools\singleton('db')->table('config')->findOneColumn($name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
if (! isset($_SESSION['config'])) {
|
||||||
|
$_SESSION['config'] = get_config();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_SESSION['config'][$name])) {
|
||||||
|
return $_SESSION['config'][$name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function get_config()
|
function get_config()
|
||||||
{
|
{
|
||||||
return \PicoTools\singleton('db')
|
return \PicoTools\singleton('db')
|
||||||
->table('config')
|
->table('config')
|
||||||
->columns('username', 'language', 'autoflush', 'nocontent')
|
->columns('username', 'language', 'autoflush', 'nocontent', 'items_per_page')
|
||||||
->findOne();
|
->findOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +573,9 @@ function validate_login(array $values)
|
|||||||
if ($user && \password_verify($values['password'], $user['password'])) {
|
if ($user && \password_verify($values['password'], $user['password'])) {
|
||||||
|
|
||||||
unset($user['password']);
|
unset($user['password']);
|
||||||
|
|
||||||
$_SESSION['user'] = $user;
|
$_SESSION['user'] = $user;
|
||||||
|
$_SESSION['config'] = get_config();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
@ -565,7 +602,9 @@ function validate_config_update(array $values)
|
|||||||
new Validators\MinLength('password', t('The minimum length is 6 characters'), 6),
|
new Validators\MinLength('password', t('The minimum length is 6 characters'), 6),
|
||||||
new Validators\Required('confirmation', t('The confirmation is required')),
|
new Validators\Required('confirmation', t('The confirmation is required')),
|
||||||
new Validators\Equals('password', 'confirmation', t('Passwords doesn\'t match')),
|
new Validators\Equals('password', 'confirmation', t('Passwords doesn\'t match')),
|
||||||
new Validators\Required('autoflush', t('Value required'))
|
new Validators\Required('autoflush', t('Value required')),
|
||||||
|
new Validators\Required('items_per_page', t('Value required')),
|
||||||
|
new Validators\Integer('items_per_page', t('Must be an integer')),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -596,6 +635,9 @@ function save_config(array $values)
|
|||||||
|
|
||||||
unset($values['confirmation']);
|
unset($values['confirmation']);
|
||||||
|
|
||||||
|
// Reload configuration in session
|
||||||
|
$_SESSION['config'] = $values;
|
||||||
|
|
||||||
$_SESSION['user']['language'] = $values['language'];
|
$_SESSION['user']['language'] = $values['language'];
|
||||||
unset($_COOKIE['language']);
|
unset($_COOKIE['language']);
|
||||||
|
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
namespace Schema;
|
namespace Schema;
|
||||||
|
|
||||||
|
|
||||||
|
function version_9($pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE config ADD COLUMN items_per_page INTEGER DEFAULT 100');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function version_8($pdo)
|
function version_8($pdo)
|
||||||
{
|
{
|
||||||
$pdo->exec('ALTER TABLE items ADD COLUMN bookmark INTEGER DEFAULT 0');
|
$pdo->exec('ALTER TABLE items ADD COLUMN bookmark INTEGER DEFAULT 0');
|
||||||
@ -77,7 +83,7 @@ function version_1($pdo)
|
|||||||
title TEXT,
|
title TEXT,
|
||||||
author TEXT,
|
author TEXT,
|
||||||
content TEXT,
|
content TEXT,
|
||||||
updated TEXT,
|
updated INTEGER,
|
||||||
status TEXT,
|
status TEXT,
|
||||||
feed_id INTEGER,
|
feed_id INTEGER,
|
||||||
FOREIGN KEY(feed_id) REFERENCES feeds(id) ON DELETE CASCADE
|
FOREIGN KEY(feed_id) REFERENCES feeds(id) ON DELETE CASCADE
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<a class="logo" href="?">mini<span>flux</span></a>
|
<a class="logo" href="?">mini<span>flux</span></a>
|
||||||
<ul>
|
<ul>
|
||||||
<li <?= isset($menu) && $menu === 'unread' ? 'class="active"' : '' ?>>
|
<li <?= isset($menu) && $menu === 'unread' ? 'class="active"' : '' ?>>
|
||||||
<a href="?action=default"><?= t('unread') ?> <span id="nav-counter"><?= isset($nb_unread_items) ? '('.$nb_unread_items.')' : '' ?></span></a>
|
<a href="?action=unread"><?= t('unread') ?> <span id="nav-counter"><?= isset($nb_unread_items) ? '('.$nb_unread_items.')' : '' ?></span></a>
|
||||||
</li>
|
</li>
|
||||||
<li <?= isset($menu) && $menu === 'bookmarks' ? 'class="active"' : '' ?>>
|
<li <?= isset($menu) && $menu === 'bookmarks' ? 'class="active"' : '' ?>>
|
||||||
<a href="?action=bookmarks"><?= t('bookmarks') ?></a>
|
<a href="?action=bookmarks"><?= t('bookmarks') ?></a>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<p>
|
<p>
|
||||||
<?= Helper\get_host_from_url($item['url']) ?> |
|
<?= Helper\get_host_from_url($item['url']) ?> |
|
||||||
<?= dt('%e %B %Y %k:%M', $item['updated']) ?> |
|
<?= dt('%e %B %Y %k:%M', $item['updated']) ?> |
|
||||||
<a href="?action=bookmark&value=0&id=<?= $item_id ?>&redirect=bookmarks"><?= t('remove bookmark') ?></a> |
|
<a href="?action=bookmark&value=0&id=<?= $item_id ?>&redirect=bookmarks&offset=<?= $offset ?>"><?= t('remove bookmark') ?></a> |
|
||||||
<a
|
<a
|
||||||
href="<?= $item['url'] ?>"
|
href="<?= $item['url'] ?>"
|
||||||
id="original-<?= $item_id ?>"
|
id="original-<?= $item_id ?>"
|
||||||
@ -39,11 +39,11 @@
|
|||||||
|
|
||||||
<nav id="items-paging">
|
<nav id="items-paging">
|
||||||
<?php if ($offset > 0): ?>
|
<?php if ($offset > 0): ?>
|
||||||
<a id="previous-page" href="?action=bookmarks&offset=<?= ($offset - ITEMS_PER_PAGE) ?>">⇽ <?= t('Previous page') ?></a>
|
<a id="previous-page" href="?action=bookmarks&offset=<?= ($offset - $items_per_page) ?>">⇽ <?= t('Previous page') ?></a>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (($nb_items - $offset) > ITEMS_PER_PAGE): ?>
|
<?php if (($nb_items - $offset) > $items_per_page): ?>
|
||||||
<a id="next-page" href="?action=bookmarks&offset=<?= ($offset + ITEMS_PER_PAGE) ?>"><?= t('Next page') ?> ⇾</a>
|
<a id="next-page" href="?action=bookmarks&offset=<?= ($offset + $items_per_page) ?>"><?= t('Next page') ?> ⇾</a>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
<?= Helper\form_label(t('Remove automatically read items'), 'autoflush') ?>
|
<?= Helper\form_label(t('Remove automatically read items'), 'autoflush') ?>
|
||||||
<?= Helper\form_select('autoflush', $autoflush_options, $values, $errors) ?><br/>
|
<?= Helper\form_select('autoflush', $autoflush_options, $values, $errors) ?><br/>
|
||||||
|
|
||||||
|
<?= Helper\form_label(t('Items per page'), 'items_per_page') ?>
|
||||||
|
<?= Helper\form_select('items_per_page', $paging_options, $values, $errors) ?><br/>
|
||||||
|
|
||||||
<?= Helper\form_checkbox('nocontent', t('Do not fetch the content of articles'), 1, isset($values['nocontent']) ? $values['nocontent'] : false) ?><br />
|
<?= Helper\form_checkbox('nocontent', t('Do not fetch the content of articles'), 1, isset($values['nocontent']) ? $values['nocontent'] : false) ?><br />
|
||||||
|
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
|
@ -5,6 +5,6 @@
|
|||||||
<p class="alert alert-info"><?= t('Do you really want to remove this subscription: "%s"?', Helper\escape($feed['title'])) ?></p>
|
<p class="alert alert-info"><?= t('Do you really want to remove this subscription: "%s"?', Helper\escape($feed['title'])) ?></p>
|
||||||
|
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<a href="?action=remove&feed_id=<?= $feed['id'] ?>" class="btn btn-red"><?= t('Yes') ?></a>
|
<a href="?action=remove-feed&feed_id=<?= $feed['id'] ?>" class="btn btn-red"><?= t('Yes') ?></a>
|
||||||
<?= t('or') ?> <a href="?action=feeds"><?= t('cancel') ?></a>
|
<?= t('or') ?> <a href="?action=feeds"><?= t('cancel') ?></a>
|
||||||
</div>
|
</div>
|
@ -28,7 +28,7 @@
|
|||||||
<p>
|
<p>
|
||||||
<a href="<?= $feed['site_url'] ?>" rel="noreferrer" target="_blank"><?= Helper\get_host_from_url($feed['site_url']) ?></a> |
|
<a href="<?= $feed['site_url'] ?>" rel="noreferrer" target="_blank"><?= Helper\get_host_from_url($feed['site_url']) ?></a> |
|
||||||
<a href="<?= Helper\escape($feed['feed_url']) ?>" rel="noreferrer" target="_blank"><?= t('feed link') ?></a> |
|
<a href="<?= Helper\escape($feed['feed_url']) ?>" rel="noreferrer" target="_blank"><?= t('feed link') ?></a> |
|
||||||
<a href="?action=confirm-remove&feed_id=<?= $feed['id'] ?>"><?= t('remove') ?></a> |
|
<a href="?action=confirm-remove-feed&feed_id=<?= $feed['id'] ?>"><?= t('remove') ?></a> |
|
||||||
<a href="?action=refresh-feed&feed_id=<?= $feed['id'] ?>" data-feed-id="<?= $feed['id'] ?>" data-action="refresh-feed"><?= t('refresh') ?></a>
|
<a href="?action=refresh-feed&feed_id=<?= $feed['id'] ?>" data-feed-id="<?= $feed['id'] ?>" data-action="refresh-feed"><?= t('refresh') ?></a>
|
||||||
</p>
|
</p>
|
||||||
</article>
|
</article>
|
||||||
|
@ -25,13 +25,13 @@
|
|||||||
<p>
|
<p>
|
||||||
<?= Helper\get_host_from_url($item['url']) ?> |
|
<?= Helper\get_host_from_url($item['url']) ?> |
|
||||||
<?= dt('%e %B %Y %k:%M', $item['updated']) ?> |
|
<?= dt('%e %B %Y %k:%M', $item['updated']) ?> |
|
||||||
<a href="?action=mark-item-unread&id=<?= $item_id ?>"><?= t('mark as unread') ?></a> |
|
<a href="?action=mark-item-unread&id=<?= $item_id ?>&offset=<?= $offset ?>"><?= t('mark as unread') ?></a> |
|
||||||
|
|
||||||
<?php if (! $item['bookmark']): ?>
|
<?php if (! $item['bookmark']): ?>
|
||||||
<a href="?action=bookmark&value=1&id=<?= $item_id ?>&redirect=history"><?= t('bookmark') ?></a> |
|
<a href="?action=bookmark&value=1&id=<?= $item_id ?>&redirect=history&offset=<?= $offset ?>"><?= t('bookmark') ?></a> |
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<a href="?action=mark-item-removed&id=<?= $item_id ?>"><?= t('remove') ?></a> |
|
<a href="?action=mark-item-removed&id=<?= $item_id ?>&offset=<?= $offset ?>"><?= t('remove') ?></a> |
|
||||||
<a
|
<a
|
||||||
href="<?= $item['url'] ?>"
|
href="<?= $item['url'] ?>"
|
||||||
id="original-<?= $item_id ?>"
|
id="original-<?= $item_id ?>"
|
||||||
@ -47,11 +47,11 @@
|
|||||||
|
|
||||||
<nav id="items-paging">
|
<nav id="items-paging">
|
||||||
<?php if ($offset > 0): ?>
|
<?php if ($offset > 0): ?>
|
||||||
<a id="previous-page" href="?action=history&offset=<?= ($offset - ITEMS_PER_PAGE) ?>">⇽ <?= t('Previous page') ?></a>
|
<a id="previous-page" href="?action=history&offset=<?= ($offset - $items_per_page) ?>">⇽ <?= t('Previous page') ?></a>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (($nb_items - $offset) > ITEMS_PER_PAGE): ?>
|
<?php if (($nb_items - $offset) > $items_per_page): ?>
|
||||||
<a id="next-page" href="?action=history&offset=<?= ($offset + ITEMS_PER_PAGE) ?>"><?= t('Next page') ?> ⇾</a>
|
<a id="next-page" href="?action=history&offset=<?= ($offset + $items_per_page) ?>"><?= t('Next page') ?> ⇾</a>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
@ -32,12 +32,12 @@
|
|||||||
<?= dt('%e %B %Y %k:%M', $item['updated']) ?> |
|
<?= dt('%e %B %Y %k:%M', $item['updated']) ?> |
|
||||||
|
|
||||||
<?php if ($item['bookmark']): ?>
|
<?php if ($item['bookmark']): ?>
|
||||||
<a href="?action=bookmark&value=0&id=<?= $item_id ?>&redirect=unread"><?= t('remove bookmark') ?></a> |
|
<a id="bookmark-<?= $item_id ?>" href="?action=bookmark&value=0&id=<?= $item_id ?>&redirect=unread&offset=<?= $offset ?>"><?= t('remove bookmark') ?></a> |
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<a href="?action=bookmark&value=1&id=<?= $item_id ?>&redirect=unread"><?= t('bookmark') ?></a> |
|
<a id="bookmark-<?= $item_id ?>" href="?action=bookmark&value=1&id=<?= $item_id ?>&redirect=unread&offset=<?= $offset ?>"><?= t('bookmark') ?></a> |
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<a href="?action=mark-item-read&id=<?= $item_id ?>"><?= t('mark as read') ?></a> |
|
<a href="?action=mark-item-read&id=<?= $item_id ?>&offset=<?= $offset ?>"><?= t('mark as read') ?></a> |
|
||||||
<a
|
<a
|
||||||
href="<?= $item['url'] ?>"
|
href="<?= $item['url'] ?>"
|
||||||
id="original-<?= $item_id ?>"
|
id="original-<?= $item_id ?>"
|
||||||
@ -54,11 +54,11 @@
|
|||||||
|
|
||||||
<nav id="items-paging">
|
<nav id="items-paging">
|
||||||
<?php if ($offset > 0): ?>
|
<?php if ($offset > 0): ?>
|
||||||
<a id="previous-page" href="?action=unread&offset=<?= ($offset - ITEMS_PER_PAGE) ?>">⇽ <?= t('Previous page') ?></a>
|
<a id="previous-page" href="?action=unread&offset=<?= ($offset - $items_per_page) ?>">⇽ <?= t('Previous page') ?></a>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
<?php if (($nb_items - $offset) > ITEMS_PER_PAGE): ?>
|
<?php if (($nb_items - $offset) > $items_per_page): ?>
|
||||||
<a id="next-page" href="?action=unread&offset=<?= ($offset + ITEMS_PER_PAGE) ?>"><?= t('Next page') ?> ⇾</a>
|
<a id="next-page" href="?action=unread&offset=<?= ($offset + $items_per_page) ?>"><?= t('Next page') ?> ⇾</a>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user