From 4888f919f104b2d170302565e481a0b731eb4145 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 25 Dec 2018 01:30:28 +0100 Subject: Prepare for batch mark as read --- app/Controllers/entryController.php | 13 +++---- app/Models/EntryDAO.php | 2 +- app/Models/TagDAO.php | 48 ++++++++++++++++--------- app/views/entry/read.phtml | 10 ------ app/views/helpers/javascript_vars.phtml | 3 +- p/scripts/main.js | 62 +++++++++++++++++++-------------- 6 files changed, 76 insertions(+), 62 deletions(-) diff --git a/app/Controllers/entryController.php b/app/Controllers/entryController.php index fc0af0639..9c5ee2616 100755 --- a/app/Controllers/entryController.php +++ b/app/Controllers/entryController.php @@ -97,14 +97,15 @@ class FreshRSS_entry_Controller extends Minz_ActionController { } } } else { - $entryDAO->markRead($id, $is_read); - + $ids = is_array($id) ? $id : array($id); + $entryDAO->markRead($ids, $is_read); $tagDAO = FreshRSS_Factory::createTagDao(); - foreach ($tagDAO->getTagsForEntry($id) as $tag) { - if (!empty($tag['checked'])) { - $this->view->tags[] = $tag['id']; - } + $tagsForEntries = $tagDAO->getTagsForEntries($ids); + $tags = array(); + foreach ($tagsForEntries as $line) { + $tags['t_' . $line['id_tag']][] = $line['id_entry']; } + $this->view->tags = $tags; } if (!$this->ajax) { diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 6d77a33cd..9ae1ed797 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -383,7 +383,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable { */ public function markRead($ids, $is_read = true) { FreshRSS_UserDAO::touch(); - if (is_array($ids)) { //Many IDs at once (used by API) + if (is_array($ids)) { //Many IDs at once if (count($ids) < 6) { //Speed heuristics $affected = 0; foreach ($ids as $id) { diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php index b55d2b35d..0b4428f17 100644 --- a/app/Models/TagDAO.php +++ b/app/Models/TagDAO.php @@ -256,42 +256,56 @@ class FreshRSS_TagDAO extends Minz_ModelPdo implements FreshRSS_Searchable { } } - //For API - public function getEntryIdsTagNames($entries) { - $sql = 'SELECT et.id_entry, t.name ' + public function getTagsForEntries($entries) { + $sql = 'SELECT et.id_entry, et.id_tag, t.name ' . 'FROM `' . $this->prefix . 'tag` t ' . 'INNER JOIN `' . $this->prefix . 'entrytag` et ON et.id_tag = t.id'; $values = array(); if (is_array($entries) && count($entries) > 0) { $sql .= ' AND et.id_entry IN (' . str_repeat('?,', count($entries) - 1). '?)'; - foreach ($entries as $entry) { - $values[] = is_array($entry) ? $entry['id'] : $entry->id(); + if (is_array($entries[0])) { + foreach ($entries as $entry) { + $values[] = $entry['id']; + } + } elseif (is_object($entries[0])) { + foreach ($entries as $entry) { + $values[] = $entry->id(); + } + } else { + foreach ($entries as $entry) { + $values[] = $entry; + } } } $stm = $this->bd->prepare($sql); if ($stm && $stm->execute($values)) { - $result = array(); - foreach ($stm->fetchAll(PDO::FETCH_ASSOC) as $line) { - $entryId = 'e_' . $line['id_entry']; - $tagName = $line['name']; - if (empty($result[$entryId])) { - $result[$entryId] = array(); - } - $result[$entryId][] = $tagName; - } - return $result; + return $stm->fetchAll(PDO::FETCH_ASSOC); } else { $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo(); if ($this->autoUpdateDb($info)) { - return $this->getTagNamesEntryIds($id_entry); + return $this->getTagsForEntries($entries); } - Minz_Log::error('SQL error getTagNamesEntryIds: ' . $info[2]); + Minz_Log::error('SQL error getTagsForEntries: ' . $info[2]); return false; } } + //For API + public function getEntryIdsTagNames($entries) { + $result = array(); + foreach ($this->getTagsForEntries($entries) as $line) { + $entryId = 'e_' . $line['id_entry']; + $tagName = $line['name']; + if (empty($result[$entryId])) { + $result[$entryId] = array(); + } + $result[$entryId][] = $tagName; + } + return $result; + } + public static function daoToTag($listDAO) { $list = array(); if (!is_array($listDAO)) { diff --git a/app/views/entry/read.phtml b/app/views/entry/read.phtml index fb9e129f2..44193da9c 100755 --- a/app/views/entry/read.phtml +++ b/app/views/entry/read.phtml @@ -1,17 +1,7 @@ Minz_Request::controllerName(), - 'a' => Minz_Request::actionName(), - 'params' => Minz_Request::fetchGET(), -); - -$url['params']['is_read'] = Minz_Request::param('is_read', true) ? '0' : '1'; - FreshRSS::loadStylesAndScripts(); echo json_encode(array( - 'url' => str_ireplace('&', '&', Minz_Url::display($url)), - 'icon' => _i($url['params']['is_read'] === '1' ? 'unread' : 'read'), 'tags' => $this->tags, )); diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index a434a04a3..b950b6a1f 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -56,6 +56,7 @@ echo htmlspecialchars(json_encode(array( 'category_empty' => _t('gen.js.category_empty'), ), 'icons' => array( - 'close' => _i('close'), + 'read' => rawurlencode(_i('read')), + 'unread' => rawurlencode(_i('unread')), ), ), JSON_UNESCAPED_UNICODE), ENT_NOQUOTES, 'UTF-8'); diff --git a/p/scripts/main.js b/p/scripts/main.js index 4ba329dc1..65310fe9f 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -7,6 +7,8 @@ var $stream = null, shares = 0, ajax_loading = false; +if (!NodeList.prototype.forEach) { NodeList.prototype.forEach = Array.prototype.forEach; } //IE11 + function redirect(url, new_tab) { if (url) { if (new_tab) { @@ -89,7 +91,7 @@ function incUnreadsFeed(article, feed_id, nb) { } //Update unread: favourites - if (article && article.closest('div').hasClass('favorite')) { + if (article && $(article).closest('div').hasClass('favorite')) { elem = $('#aside_feed .favorites .title').get(0); if (elem) { feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; @@ -115,7 +117,7 @@ function incUnreadsFeed(article, feed_id, nb) { } function incUnreadsTag(tag_id, nb) { - var $t = $('#t_' + tag_id); + var $t = $('#' + tag_id); var unreads = str2int($t.attr('data-unread')); $t.attr('data-unread', unreads + nb) .children('.item-title').attr('data-unread', numberFormat(unreads + nb)); @@ -126,20 +128,20 @@ function incUnreadsTag(tag_id, nb) { } var pending_entries = {}; -function mark_read(active, only_not_read) { - if ((active.length === 0) || (!active.attr('id')) || - context.anonymous || - (only_not_read && !active.hasClass("not_read"))) { +function mark_read($active, only_not_read) { + let div = $active ? $active[0] : null; + if (!div || !div.id || context.anonymous || + (only_not_read && !div.classList.contains('not_read'))) { return false; } - if (pending_entries[active.attr('id')]) { + if (pending_entries[div.id]) { return false; } - pending_entries[active.attr('id')] = true; + pending_entries[div.id] = true; - var url = '.?c=entry&a=read&id=' + active.attr('id').replace(/^flux_/, '') + - (active.hasClass('not_read') ? '' : '&is_read=0'); + let url = '.?c=entry&a=read&id=' + div.id.replace(/^flux_/, '') + + (div.classList.contains('not_read') ? '' : '&is_read=0'); $.ajax({ type: 'POST', @@ -149,35 +151,39 @@ function mark_read(active, only_not_read) { _csrf: context.csrf, }, }).done(function (data) { - var $r = active.find("a.read").attr("href", data.url), - inc = 0; - if (active.hasClass("not_read")) { - active.removeClass("not_read"); + let inc = 0; + if (div.classList.contains('not_read')) { + div.classList.remove('not_read'); + div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=0', '') + '&is_read=1'); }); + div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = icons.read; }); inc--; } else { - active.addClass("not_read"); - active.addClass("keep_unread"); + div.classList.add('not_read', 'keep_unread'); + div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=1', '')); }); + div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = icons.unread; }); inc++; } - $r.find('.icon').replaceWith(data.icon); - var feed_url = active.find(".website>a").attr("href"); - if (feed_url) { - var feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); - incUnreadsFeed(active, feed_id, inc); + let feed_link = div.querySelector('.website > a'); + if (feed_link) { + let feed_url = feed_link.getAttribute('href'); + let feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); + incUnreadsFeed(div, feed_id, inc); } faviconNbUnread(); if (data.tags) { - for (var i = data.tags.length - 1; i >= 0; i--) { - incUnreadsTag(data.tags[i], inc); + let tagIds = Object.keys(data.tags); + for (let i = tagIds.length - 1; i >= 0; i--) { + let tagId = tagIds[i]; + incUnreadsTag(tagId, inc * data.tags[tagId].length); } } - delete pending_entries[active.attr('id')]; + delete pending_entries[div.id]; }).fail(function (data) { openNotification(i18n.notif_request_failed, 'bad'); - delete pending_entries[active.attr('id')]; + delete pending_entries[div.id]; }); } @@ -911,7 +917,7 @@ function init_dynamic_tags() { }) .done(function () { if ($entry.hasClass('not_read')) { - incUnreadsTag(tagId, isChecked ? 1 : -1); + incUnreadsTag('t_' + tagId, isChecked ? 1 : -1); } }) .fail(function () { @@ -1079,7 +1085,7 @@ function notifs_html5_show(nb) { var notification = new window.Notification(i18n.notif_title_articles, { icon: "../themes/icons/favicon-256.png", body: i18n.notif_body_articles.replace('%d', nb), - tag: "freshRssNewArticles" + tag: 'freshRssNewArticles', }); notification.onclick = function() { @@ -1491,6 +1497,8 @@ function parseJsonVars() { window.url = json.url; window.i18n = json.i18n; window.icons = json.icons; + icons.read = decodeURIComponent(icons.read); + icons.unread = decodeURIComponent(icons.unread); } function init_normal() { -- cgit v1.2.3 From eefeb2341915d677e446cd733fc58b45efb7f5d9 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 25 Dec 2018 05:11:38 +0100 Subject: jQuery ES6 partial refactoring Prefix jQuery variables with $ Start avoiding jQuery in easy cases Use let/const --- app/views/helpers/javascript_vars.phtml | 2 +- p/scripts/main.js | 681 ++++++++++++++++---------------- 2 files changed, 346 insertions(+), 337 deletions(-) diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index b950b6a1f..b62263ecf 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -42,7 +42,7 @@ echo htmlspecialchars(json_encode(array( 'reading_view' => @$s['reading_view'], 'rss_view' => @$s['rss_view'], ), - 'url' => array( + 'urls' => array( 'index' => _url('index', 'index'), 'login' => Minz_Url::display(array('c' => 'auth', 'a' => 'login'), 'php'), 'logout' => Minz_Url::display(array('c' => 'auth', 'a' => 'logout'), 'php'), diff --git a/p/scripts/main.js b/p/scripts/main.js index 65310fe9f..555e92a40 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1,13 +1,44 @@ "use strict"; -/* globals $, jQuery, context, i18n, shortcut, shortcuts, url */ -/* jshint strict:global */ +/* globals $, jQuery, shortcut */ +/* jshint esversion:6, strict:global */ + +// +if (!NodeList.prototype.forEach) NodeList.prototype.forEach = Array.prototype.forEach; +if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.webkitMatchesSelector; +if (!Element.prototype.closest) { + Element.prototype.closest = function (s) { + let el = this; + if (!document.documentElement.contains(el)) return null; + do { + if (el.matches(s)) return el; + el = el.parentElement || el.parentNode; + } while (el !== null && el.nodeType == 1); + return null; + }; +} +// + +// +var context, i18n, icons, shortcuts, urls; + +(function parseJsonVars() { + const jsonVars = document.getElementById('jsonVars'), + json = JSON.parse(jsonVars.innerHTML); + jsonVars.outerHTML = ''; + context = json.context; + i18n = json.i18n; + shortcuts = json.shortcuts; + urls = json.urls; + icons = json.icons; + icons.read = decodeURIComponent(icons.read); + icons.unread = decodeURIComponent(icons.unread); +}()); var $stream = null, + ajax_loading = false, isCollapsed = true, - shares = 0, - ajax_loading = false; - -if (!NodeList.prototype.forEach) { NodeList.prototype.forEach = Array.prototype.forEach; } //IE11 + $nav_entries = null; +// function redirect(url, new_tab) { if (url) { @@ -20,7 +51,7 @@ function redirect(url, new_tab) { } function needsScroll($elem) { - var $win = $(window), + const $win = $(window), winTop = $win.scrollTop(), winHeight = $win.height(), winBottom = winTop + winHeight, @@ -42,10 +73,10 @@ function numberFormat(nStr) { } // http://www.mredkj.com/javascript/numberFormat.html nStr += ''; - var x = nStr.split('.'), - x1 = x[0], + const x = nStr.split('.'), x2 = x.length > 1 ? '.' + x[1] : '', rgx = /(\d+)(\d{3})/; + let x1 = x[0]; while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + ' ' + '$2'); } @@ -53,29 +84,29 @@ function numberFormat(nStr) { } function incLabel(p, inc, spaceAfter) { - var i = str2int(p) + inc; + const i = str2int(p) + inc; return i > 0 ? ((spaceAfter ? '' : ' ') + '(' + numberFormat(i) + ')' + (spaceAfter ? ' ' : '')) : ''; } function incUnreadsFeed(article, feed_id, nb) { //Update unread: feed - var elem = $('#' + feed_id).get(0), + let elem = document.getElementById(feed_id), feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0, feed_priority = elem ? str2int(elem.getAttribute('data-priority')) : 0; if (elem) { elem.setAttribute('data-unread', feed_unreads + nb); - elem = $(elem).children('.item-title').get(0); + elem = elem.querySelector('.item-title'); if (elem) { elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); } } //Update unread: category - elem = $('#' + feed_id).parents('.category').get(0); + elem = document.getElementById(feed_id).closest('.category'); feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; if (elem) { elem.setAttribute('data-unread', feed_unreads + nb); - elem = $(elem).find('.title').get(0); + elem = elem.querySelector('.title'); if (elem) { elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); } @@ -83,7 +114,7 @@ function incUnreadsFeed(article, feed_id, nb) { //Update unread: all if (feed_priority > 0) { - elem = $('#aside_feed .all .title').get(0); + elem = document.querySelector('#aside_feed .all .title'); if (elem) { feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); @@ -91,22 +122,22 @@ function incUnreadsFeed(article, feed_id, nb) { } //Update unread: favourites - if (article && $(article).closest('div').hasClass('favorite')) { - elem = $('#aside_feed .favorites .title').get(0); + if (article && article.closest('div').classList.contains('favorite')) { + elem = document.querySelector('#aside_feed .favorites .title'); if (elem) { feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; elem.setAttribute('data-unread', numberFormat(feed_unreads + nb)); } } - var isCurrentView = false; + let isCurrentView = false; // Update unread: title document.title = document.title.replace(/^((?:\([ 0-9]+\) )?)/, function (m, p1) { - var $feed = $('#' + feed_id); - if (article || ($feed.closest('.active').length > 0 && $feed.siblings('.active').length === 0)) { + const feed = document.getElementById(feed_id); + if (article || (feed.closest('.active') && $(feed).siblings('.active').length === 0)) { isCurrentView = true; return incLabel(p1, nb, true); - } else if ($('.all.active').length > 0) { + } else if (document.querySelector('.all.active')) { isCurrentView = feed_priority > 0; return incLabel(p1, feed_priority > 0 ? nb : 0, true); } else { @@ -117,19 +148,22 @@ function incUnreadsFeed(article, feed_id, nb) { } function incUnreadsTag(tag_id, nb) { - var $t = $('#' + tag_id); - var unreads = str2int($t.attr('data-unread')); - $t.attr('data-unread', unreads + nb) - .children('.item-title').attr('data-unread', numberFormat(unreads + nb)); - - $t = $('.category.tags').find('.title'); - unreads = str2int($t.attr('data-unread')); - $t.attr('data-unread', numberFormat(unreads + nb)); + let t = document.getElementById(tag_id); + if (t) { + let unreads = str2int(t.getAttribute('data-unread')); + t.setAttribute('data-unread', unreads + nb); + t.querySelector('.item-title').setAttribute('data-unread', numberFormat(unreads + nb)); + } + t = document.querySelector('.category.tags .title'); + if (t) { + let unreads = str2int(t.getAttribute('data-unread')); + t.setAttribute('data-unread', numberFormat(unreads + nb)); + } } var pending_entries = {}; -function mark_read($active, only_not_read) { - let div = $active ? $active[0] : null; + +function mark_read(div, only_not_read) { if (!div || !div.id || context.anonymous || (only_not_read && !div.classList.contains('not_read'))) { return false; @@ -187,20 +221,21 @@ function mark_read($active, only_not_read) { }); } -function mark_favorite(active) { - if (active.length === 0) { +function mark_favorite(div) { + if (!div) { return false; } - var url = active.find("a.bookmark").attr("href"); - if (url === undefined) { + let a = div.querySelector('a.bookmark'), + url = a ? a.getAttribute('href') : ''; + if (!url) { return false; } - if (pending_entries[active.attr('id')]) { + if (pending_entries[div.id]) { return false; } - pending_entries[active.attr('id')] = true; + pending_entries[div.id] = true; $.ajax({ type: 'POST', @@ -210,77 +245,77 @@ function mark_favorite(active) { _csrf: context.csrf, }, }).done(function (data) { - var $b = active.find("a.bookmark").attr("href", data.url), - inc = 0; - if (active.hasClass("favorite")) { - active.removeClass("favorite"); + let inc = 0; + if (div.classList.contains('favorite')) { + div.classList.remove('favorite'); inc--; } else { - active.addClass("favorite").find('.bookmark'); + div.classList.add('favorite'); inc++; } - $b.find('.icon').replaceWith(data.icon); + div.querySelectorAll('a.bookmark').forEach(function (a) { a.setAttribute('href', data.url); }); + div.querySelectorAll('a.bookmark > .icon').forEach(function (img) { img.outerHTML = data.icon; }); - var favourites = $('#aside_feed .favorites .title').contents().last().get(0); + const favourites = $('#aside_feed .favorites .title').contents().last().get(0); if (favourites && favourites.textContent) { favourites.textContent = favourites.textContent.replace(/((?: \([ 0-9]+\))?\s*)$/, function (m, p1) { return incLabel(p1, inc, false); }); } - if (active.closest('div').hasClass('not_read')) { - var elem = $('#aside_feed .favorites .title').get(0), + if (div.classList.contains('not_read')) { + const elem = document.querySelector('#aside_feed .favorites .title'), feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; if (elem) { elem.setAttribute('data-unread', numberFormat(feed_unreads + inc)); } } - delete pending_entries[active.attr('id')]; + delete pending_entries[div.id]; }).fail(function (data) { openNotification(i18n.notif_request_failed, 'bad'); - delete pending_entries[active.attr('id')]; + delete pending_entries[div.id]; }); } -function toggleContent(new_active, old_active, skipping) { +function toggleContent($new_active, $old_active, skipping) { // If skipping, move current without activating or marking as read - if (new_active.length === 0) { + if ($new_active.length === 0) { return; } if (context.does_lazyload && !skipping) { - new_active.find('img[data-original], iframe[data-original]').each(function () { + $new_active.find('img[data-original], iframe[data-original]').each(function () { this.setAttribute('src', this.getAttribute('data-original')); this.removeAttribute('data-original'); }); } - if (old_active[0] !== new_active[0]) { + if ($old_active[0] !== $new_active[0]) { if (isCollapsed && !skipping) { // BUG?: isCollapsed can only ever be true - new_active.addClass("active"); + $new_active.addClass('active'); } - old_active.removeClass("active current"); - new_active.addClass("current"); - if (context.auto_remove_article && !old_active.hasClass('not_read') && !skipping) { - auto_remove(old_active); + $old_active.removeClass('active current'); + $new_active.addClass('current'); + if (context.auto_remove_article && !$old_active.hasClass('not_read') && !skipping) { + auto_remove($old_active); } } else { // collapse_entry calls toggleContent(flux_current, flux_current, false) - new_active.toggleClass('active'); + $new_active.toggleClass('active'); } - var relative_move = context.current_view === 'global', - box_to_move = $(relative_move ? "#panel" : "html,body"); + const relative_move = context.current_view === 'global', + $box_to_move = $(relative_move ? '#panel' : 'html,body'); if (context.sticky_post) { - var prev_article = new_active.prevAll('.flux'), - new_pos = new_active.offset().top, - old_scroll = box_to_move.scrollTop(); + let prev_article = $new_active.prevAll('.flux'), + new_pos = $new_active.offset().top, + old_scroll = $box_to_move.scrollTop(); if (prev_article.length > 0 && new_pos - prev_article.offset().top <= 150) { new_pos = prev_article.offset().top; if (relative_move) { - new_pos -= box_to_move.offset().top; + new_pos -= $box_to_move.offset().top; } } @@ -293,104 +328,104 @@ function toggleContent(new_active, old_active, skipping) { new_pos += old_scroll; } - new_active.children(".flux_content").first().each(function () { - box_to_move.scrollTop(new_pos).scrollTop(); + $new_active.children('.flux_content').first().each(function () { + $box_to_move.scrollTop(new_pos).scrollTop(); }); } else { if (relative_move) { new_pos += old_scroll; } - box_to_move.scrollTop(new_pos).scrollTop(); + $box_to_move.scrollTop(new_pos).scrollTop(); } } - if (context.auto_mark_article && new_active.hasClass('active') && !skipping) { - mark_read(new_active, true); + if (context.auto_mark_article && $new_active.hasClass('active') && !skipping) { + mark_read($new_active[0], true); } } -function auto_remove(element) { - var p = element.prev(); - var n = element.next(); - if (p.hasClass('day') && n.hasClass('day')) { - p.remove(); +function auto_remove($element) { + let $p = $element.prev(), + $n = $element.next(); + if ($p.hasClass('day') && $n.hasClass('day')) { + $p.remove(); } - element.remove(); + $element.remove(); $('#stream > .flux:not(.not_read):not(.active)').remove(); } function prev_entry() { - var old_active = $(".flux.current"), - new_active = old_active.length === 0 ? $(".flux:last") : old_active.prevAll(".flux:first"); - toggleContent(new_active, old_active, false); + let $old_active = $('.flux.current'), + $new_active = $old_active.length === 0 ? $('.flux:last') : $old_active.prevAll('.flux:first'); + toggleContent($new_active, $old_active, false); } function next_entry() { - var old_active = $(".flux.current"), - new_active = old_active.length === 0 ? $(".flux:first") : old_active.nextAll(".flux:first"); - toggleContent(new_active, old_active, false); + let $old_active = $('.flux.current'), + $new_active = $old_active.length === 0 ? $('.flux:first') : $old_active.nextAll('.flux:first'); + toggleContent($new_active, $old_active, false); - if (new_active.nextAll().length < 3) { + if ($new_active.nextAll().length < 3) { load_more_posts(); } } function skip_prev_entry() { - var old_active = $(".flux.current"), - new_active = old_active.length === 0 ? $(".flux:last") : old_active.prevAll(".flux:first"); - toggleContent(new_active, old_active, true); + let $old_active = $('.flux.current'), + $new_active = $old_active.length === 0 ? $('.flux:last') : $old_active.prevAll('.flux:first'); + toggleContent($new_active, $old_active, true); } function skip_next_entry() { - var old_active = $(".flux.current"), - new_active = old_active.length === 0 ? $(".flux:first") : old_active.nextAll(".flux:first"); - toggleContent(new_active, old_active, true); + let $old_active = $('.flux.current'), + $new_active = $old_active.length === 0 ? $('.flux:first') : $old_active.nextAll('.flux:first'); + toggleContent($new_active, $old_active, true); - if (new_active.nextAll().length < 3) { + if ($new_active.nextAll().length < 3) { load_more_posts(); } } function prev_feed() { - var active_feed = $("#aside_feed .tree-folder-items .item.active"); - if (active_feed.length > 0) { - active_feed.prevAll(':visible:first').find('a').each(function(){this.click();}); + let $active_feed = $('#aside_feed .tree-folder-items .item.active'); + if ($active_feed.length > 0) { + $active_feed.prevAll(':visible:first').find('a').each(function () { this.click(); }); } else { last_feed(); } } function next_feed() { - var active_feed = $("#aside_feed .tree-folder-items .item.active"); - if (active_feed.length > 0) { - active_feed.nextAll(':visible:first').find('a').each(function(){this.click();}); + let $active_feed = $('#aside_feed .tree-folder-items .item.active'); + if ($active_feed.length > 0) { + $active_feed.nextAll(':visible:first').find('a').each(function () { this.click(); }); } else { first_feed(); } } function first_feed() { - var feed = $("#aside_feed .tree-folder-items.active .item:visible:first"); - if (feed.length > 0) { - feed.find('a')[1].click(); + let $feed = $('#aside_feed .tree-folder-items.active .item:visible:first'); + if ($feed.length > 0) { + $feed.find('a')[1].click(); } } function last_feed() { - var feed = $("#aside_feed .tree-folder-items.active .item:visible:last"); - if (feed.length > 0) { - feed.find('a')[1].click(); + let $feed = $('#aside_feed .tree-folder-items.active .item:visible:last'); + if ($feed.length > 0) { + $feed.find('a')[1].click(); } } function prev_category() { - var active_cat = $("#aside_feed .tree-folder.active"); + let $active_cat = $('#aside_feed .tree-folder.active'); - if (active_cat.length > 0) { - var prev_cat = active_cat.prevAll(':visible:first').find('.tree-folder-title .title'); - if (prev_cat.length > 0) { - prev_cat[0].click(); + if ($active_cat.length > 0) { + let $prev_cat = $active_cat.prevAll(':visible:first').find('.tree-folder-title .title'); + if ($prev_cat.length > 0) { + $prev_cat[0].click(); } } else { last_category(); @@ -399,12 +434,12 @@ function prev_category() { } function next_category() { - var active_cat = $("#aside_feed .tree-folder.active"); + let $active_cat = $('#aside_feed .tree-folder.active'); - if (active_cat.length > 0) { - var next_cat = active_cat.nextAll(':visible:first').find('.tree-folder-title .title'); - if (next_cat.length > 0) { - next_cat[0].click(); + if ($active_cat.length > 0) { + let $next_cat = $active_cat.nextAll(':visible:first').find('.tree-folder-title .title'); + if ($next_cat.length > 0) { + $next_cat[0].click(); } } else { first_category(); @@ -413,35 +448,35 @@ function next_category() { } function first_category() { - var cat = $("#aside_feed .tree-folder:visible:first"); - if (cat.length > 0) { - cat.find('.tree-folder-title .title')[0].click(); + let $cat = $('#aside_feed .tree-folder:visible:first'); + if ($cat.length > 0) { + $cat.find('.tree-folder-title .title')[0].click(); } } function last_category() { - var cat = $("#aside_feed .tree-folder:visible:last"); - if (cat.length > 0) { - cat.find('.tree-folder-title .title')[0].click(); + let $cat = $('#aside_feed .tree-folder:visible:last'); + if ($cat.length > 0) { + $cat.find('.tree-folder-title .title')[0].click(); } } function collapse_entry() { - var flux_current = $(".flux.current"); - toggleContent(flux_current, flux_current, false); + let $flux_current = $('.flux.current'); + toggleContent($flux_current, $flux_current, false); } function user_filter(key) { - var filter = $('#dropdown-query'); - var filters = filter.siblings('.dropdown-menu').find('.item.query a'); - if (typeof key === "undefined") { + const filter = $('#dropdown-query'), + filters = filter.siblings('.dropdown-menu').find('.item.query a'); + if (typeof key === 'undefined') { if (!filter.length) { return; } // Display the filter div window.location.hash = filter.attr('id'); // Force scrolling to the filter div - var scroll = needsScroll($('.header')); + const scroll = needsScroll($('.header')); if (scroll !== 0) { $('html,body').scrollTop(scroll); } @@ -460,21 +495,21 @@ function user_filter(key) { } function auto_share(key) { - var share = $(".flux.current.active").find('.dropdown-target[id^="dropdown-share"]'); - var shares = share.siblings('.dropdown-menu').find('.item a'); - if (typeof key === "undefined") { - if (!share.length) { + const $share = $('.flux.current.active').find('.dropdown-target[id^="dropdown-share"]'), + $shares = $share.siblings('.dropdown-menu').find('.item a'); + if (typeof key === 'undefined') { + if (!$share.length) { return; } // Display the share div - window.location.hash = share.attr('id'); + window.location.hash = $share.attr('id'); // Force scrolling to the share div - var scroll = needsScroll(share.closest('.bottom')); + const scroll = needsScroll($share.closest('.bottom')); if (scroll !== 0) { $('html,body').scrollTop(scroll); } // Force the key value if there is only one action, so we can trigger it automatically - if (shares.length === 1) { + if ($shares.length === 1) { key = 1; } else { return; @@ -482,54 +517,54 @@ function auto_share(key) { } // Trigger selected share action and hide the share div key = parseInt(key); - if (key <= shares.length) { - shares[key - 1].click(); - share.siblings('.dropdown-menu').find('.dropdown-close a')[0].click(); + if (key <= $shares.length) { + $shares[key - 1].click(); + $share.siblings('.dropdown-menu').find('.dropdown-close a')[0].click(); } } -function scrollAsRead(box_to_follow) { - var minTop = 40 + (context.current_view === 'global' ? box_to_follow.offset().top : box_to_follow.scrollTop()); +function scrollAsRead($box_to_follow) { + const minTop = 40 + (context.current_view === 'global' ? $box_to_follow.offset().top : $box_to_follow.scrollTop()); $('.not_read:not(.keep_unread):visible').each(function () { - var $this = $(this); + const $this = $(this); if ($this.offset().top + $this.height() < minTop) { - mark_read($this, true); + mark_read(this, true); } }); } function init_posts() { - var box_to_follow = context.current_view === 'global' ? $("#panel") : $(window); + let $box_to_follow = context.current_view === 'global' ? $('#panel') : $(window); if (context.auto_mark_scroll) { - var lastScroll = 0, //Throttle + let lastScroll = 0, //Throttle timerId = 0; - box_to_follow.scroll(function () { + $box_to_follow.scroll(function () { window.clearTimeout(timerId); if (lastScroll + 500 < Date.now()) { lastScroll = Date.now(); - scrollAsRead(box_to_follow); + scrollAsRead($box_to_follow); } else { timerId = window.setTimeout(function() { - scrollAsRead(box_to_follow); + scrollAsRead($box_to_follow); }, 500); } }); } if (context.auto_load_more) { - box_to_follow.scroll(function () { - var load_more = $("#load_more"); - if (!load_more.is(':visible')) { + $box_to_follow.scroll(function () { + const $load_more = $('#load_more'); + if (!$load_more.is(':visible')) { return; } - var boxBot = box_to_follow.scrollTop() + box_to_follow.height(), - load_more_top = load_more.offset().top; + const boxBot = $box_to_follow.scrollTop() + $box_to_follow.height(), + load_more_top = $load_more.offset().top; if (boxBot >= load_more_top) { load_more_posts(); } }); - box_to_follow.scroll(); + $box_to_follow.scroll(); } } @@ -548,9 +583,9 @@ function init_column_categories() { this.alt = '▽'; } }); - $(this).parent().next(".tree-folder-items").slideToggle(300, function () { + $(this).parent().next('.tree-folder-items').slideToggle(300, function () { //Workaround for Gecko bug in Firefox 64-65(+?): - var sidebar = document.getElementById('sidebar'); + const sidebar = document.getElementById('sidebar'); if (sidebar && sidebar.scrollHeight > sidebar.clientHeight && //if needs scrollbar sidebar.scrollWidth >= sidebar.offsetWidth) { //but no scrollbar sidebar.style['overflow-y'] = 'scroll'; //then force scrollbar @@ -561,7 +596,7 @@ function init_column_categories() { }); $('#aside_feed').on('click', '.tree-folder-items .feed .dropdown-toggle', function () { - var itemId = $(this).closest('.item').attr('id'), + const itemId = $(this).closest('.item').attr('id'), templateId = itemId.substring(0, 2) === 't_' ? 'tag_config_template' : 'feed_config_template', id = itemId.substr(2), feed_web = $(this).data('fweb'), @@ -572,10 +607,10 @@ function init_column_categories() { .append(template).find('button.confirm').removeAttr('disabled'); } else { if ($(this).next('.dropdown-menu').css('display') === 'none') { - id = $(this).closest('.item').attr('id').substr(2); - $(this).attr('href', '#dropdown-' + id); + const id2 = $(this).closest('.item').attr('id').substr(2); + $(this).attr('href', '#dropdown-' + id2); } else { - $(this).attr('href', "#close"); + $(this).attr('href', '#close'); } } }); @@ -592,21 +627,19 @@ function init_shortcuts() { // Manipulation shortcuts shortcut.add(shortcuts.mark_read, function () { // Toggle the read state - var active = $(".flux.current"); - mark_read(active, false); + mark_read(document.querySelector('.flux.current'), false); }, { 'disable_in_input': true }); - shortcut.add("shift+" + shortcuts.mark_read, function () { + shortcut.add('shift+' + shortcuts.mark_read, function () { // Mark everything as read - $(".nav_menu .read_all").click(); + $('.nav_menu .read_all').click(); }, { 'disable_in_input': true }); shortcut.add(shortcuts.mark_favorite, function () { // Toggle the favorite state - var active = $(".flux.current"); - mark_favorite(active); + mark_favorite(document.querySelector('.flux.current')); }, { 'disable_in_input': true }); @@ -637,7 +670,7 @@ function init_shortcuts() { auto_share(String.fromCharCode(evt.keyCode)); } } - for (var i = 1; i < 10; i++) { + for (let i = 1; i < 10; i++) { shortcut.add(i.toString(), addShortcut, { 'disable_in_input': true }); @@ -651,11 +684,11 @@ function init_shortcuts() { 'disable_in_input': true }); shortcut.add(shortcuts.first_entry, function () { - var old_active = $(".flux.current"), - first = $(".flux:first"); + const $old_active = $('.flux.current'), + $first = $('.flux:first'); - if (first.hasClass("flux")) { - toggleContent(first, old_active, false); + if ($first.hasClass('flux')) { + toggleContent($first, $old_active, false); } }, { 'disable_in_input': true @@ -667,48 +700,48 @@ function init_shortcuts() { 'disable_in_input': true }); shortcut.add(shortcuts.last_entry, function () { - var old_active = $(".flux.current"), - last = $(".flux:last"); + const $old_active = $('.flux.current'), + $last = $('.flux:last'); - if (last.hasClass("flux")) { - toggleContent(last, old_active, false); + if ($last.hasClass('flux')) { + toggleContent($last, $old_active, false); } }, { 'disable_in_input': true }); // Feed navigation shortcuts - shortcut.add("shift+" + shortcuts.prev_entry, prev_feed, { + shortcut.add('shift+' + shortcuts.prev_entry, prev_feed, { 'disable_in_input': true }); - shortcut.add("shift+" + shortcuts.next_entry, next_feed, { + shortcut.add('shift+' + shortcuts.next_entry, next_feed, { 'disable_in_input': true }); - shortcut.add("shift+" + shortcuts.first_entry, first_feed, { + shortcut.add('shift+' + shortcuts.first_entry, first_feed, { 'disable_in_input': true }); - shortcut.add("shift+" + shortcuts.last_entry, last_feed, { + shortcut.add('shift+' + shortcuts.last_entry, last_feed, { 'disable_in_input': true }); // Category navigation shortcuts - shortcut.add("alt+" + shortcuts.prev_entry, prev_category, { + shortcut.add('alt+' + shortcuts.prev_entry, prev_category, { 'disable_in_input': true }); - shortcut.add("alt+" + shortcuts.next_entry, next_category, { + shortcut.add('alt+' + shortcuts.next_entry, next_category, { 'disable_in_input': true }); - shortcut.add("alt+" + shortcuts.first_entry, first_category, { + shortcut.add('alt+' + shortcuts.first_entry, first_category, { 'disable_in_input': true }); - shortcut.add("alt+" + shortcuts.last_entry, last_category, { + shortcut.add('alt+' + shortcuts.last_entry, last_category, { 'disable_in_input': true }); shortcut.add(shortcuts.go_website, function () { - var url_website = $('.flux.current a.go_website').attr("href"); + const url_website = $('.flux.current a.go_website').attr('href'); if (context.auto_mark_site) { - $(".flux.current").each(function () { - mark_read($(this), true); + $('.flux.current').each(function () { + mark_read(this, true); }); } @@ -730,7 +763,7 @@ function init_shortcuts() { }); shortcut.add(shortcuts.help, function () { - redirect(url.help, true); + redirect(urls.help, true); }, { 'disable_in_input': true }); @@ -775,8 +808,8 @@ function init_stream(divStream) { // setting for not-closing after clicking outside article area return; } - var old_active = $(".flux.current"), - new_active = $(this).parent(); + const old_active = document.querySelector('.flux.current'), + new_active = this.parentNode; isCollapsed = true; if (e.target.tagName.toUpperCase() === 'A') { //Leave real links alone if (context.auto_mark_article) { @@ -784,21 +817,20 @@ function init_stream(divStream) { } return true; } - toggleContent(new_active, old_active, false); + toggleContent($(new_active), $(old_active), false); }); divStream.on('click', '.flux a.read', function () { - var active = $(this).parents(".flux"); - if (context.auto_remove_article && active.hasClass('not_read')) { - auto_remove(active); + const $active = $(this).parents('.flux'); + if (context.auto_remove_article && $active.hasClass('not_read')) { + auto_remove($active); } - mark_read(active, false); + mark_read($active[0], false); return false; }); divStream.on('click', '.flux a.bookmark', function () { - var active = $(this).parents(".flux"); - mark_favorite(active); + mark_favorite(this.closest('.flux')); return false; }); @@ -815,7 +847,7 @@ function init_stream(divStream) { if (e.which == 2) { // If middle click, we want same behaviour as CTRL+click. - var ev = jQuery.Event("click"); + const ev = jQuery.Event('click'); ev.ctrlKey = true; $(this).trigger(ev); } else if(e.which == 1) { @@ -838,13 +870,11 @@ function init_stream(divStream) { return; } - mark_read($(this).parents(".flux"), true); + mark_read(this.closest('.flux'), true); }); } } -var $nav_entries = null; - function init_nav_entries() { $nav_entries = $('#nav_entries'); $nav_entries.find('.previous_entry').click(function () { @@ -856,14 +886,14 @@ function init_nav_entries() { return false; }); $nav_entries.find('.up').click(function () { - var active_item = $(".flux.current"), + const $active_item = $('.flux.current'), windowTop = $(window).scrollTop(), - item_top = active_item.offset().top; + item_top = $active_item.offset().top; if (windowTop > item_top) { - $("html,body").scrollTop(item_top); + $('html,body').scrollTop(item_top); } else { - $("html,body").scrollTop(0); + $('html,body').scrollTop(0); } return false; }); @@ -872,14 +902,14 @@ function init_nav_entries() { function loadDynamicTags($div) { $div.removeClass('dynamictags'); $div.find('li.item').remove(); - var entryId = $div.closest('div.flux').attr('id').replace(/^flux_/, ''); + const entryId = $div.closest('div.flux').attr('id').replace(/^flux_/, ''); $.getJSON('./?c=tag&a=getTagsForEntry&id_entry=' + entryId) .done(function (data) { - var $ul = $div.find('.dropdown-menu'); + const $ul = $div.find('.dropdown-menu'); $ul.append('
  • '); if (data && data.length) { - for (var i = 0; i < data.length; i++) { - var tag = data[i]; + for (let i = 0; i < data.length; i++) { + const tag = data[i]; $ul.append('
  • '); } @@ -897,13 +927,13 @@ function init_dynamic_tags() { }); $stream.on('change', '.checkboxTag', function (ev) { - var $checkbox = $(this); + const $checkbox = $(this), + isChecked = $checkbox.prop('checked'), + tagId = $checkbox.attr('name').replace(/^t_/, ''), + tagName = $checkbox.siblings('input[name]').val(), + $entry = $checkbox.closest('div.flux'), + entryId = $entry.attr('id').replace(/^flux_/, ''); $checkbox.prop('disabled', true); - var isChecked = $checkbox.prop('checked'); - var tagId = $checkbox.attr('name').replace(/^t_/, ''); - var tagName = $checkbox.siblings('input[name]').val(); - var $entry = $checkbox.closest('div.flux'); - var entryId = $entry.attr('id').replace(/^flux_/, ''); $.ajax({ type: 'POST', url: './?c=tag&a=tagEntry', @@ -936,7 +966,7 @@ function init_dynamic_tags() { var feed_processed = 0; function updateFeed(feeds, feeds_count) { - var feed = feeds.pop(); + const feed = feeds.pop(); if (!feed) { return; } @@ -949,8 +979,8 @@ function updateFeed(feeds, feeds_count) { }, }).always(function (data) { feed_processed++; - $("#actualizeProgress .progress").html(feed_processed + " / " + feeds_count); - $("#actualizeProgress .title").html(feed.title); + $('#actualizeProgress .progress').html(feed_processed + ' / ' + feeds_count); + $('#actualizeProgress .title').html(feed.title); if (feed_processed === feeds_count) { $.ajax({ //Empty request to commit new articles @@ -970,9 +1000,9 @@ function updateFeed(feeds, feeds_count) { } function init_actualize() { - var auto = false; + let auto = false; - $("#actualize").click(function () { + $('#actualize').click(function () { if (ajax_loading) { return false; } @@ -985,7 +1015,7 @@ function init_actualize() { return false; } if (data.feeds.length === 0) { - openNotification(data.feedback_no_refresh, "good"); + openNotification(data.feedback_no_refresh, 'good'); $.ajax({ //Empty request to force refresh server database cache type: 'POST', url: './?c=feed&a=actualize&id=-1&ajax=1', @@ -999,11 +1029,11 @@ function init_actualize() { return; } //Progress bar - var feeds_count = data.feeds.length; + const feeds_count = data.feeds.length; $('body').after('
    ' + data.feedback_actualize + '
    /
    0 / ' + feeds_count + '
    '); - for (var i = 10; i > 0; i--) { + for (let i = 10; i > 0; i--) { updateFeed(data.feeds, feeds_count); } }); @@ -1013,13 +1043,13 @@ function init_actualize() { if (context.auto_actualize_feeds) { auto = true; - $("#actualize").click(); + $('#actualize').click(); } } // // -var notification = null, +var $notification = null, notification_interval = null, notification_working = false; @@ -1030,19 +1060,19 @@ function openNotification(msg, status) { notification_working = true; - notification.removeClass(); - notification.addClass("notification"); - notification.addClass(status); - notification.find(".msg").html(msg); - notification.fadeIn(300); + $notification.removeClass(); + $notification.addClass('notification'); + $notification.addClass(status); + $notification.find('.msg').html(msg); + $notification.fadeIn(300); notification_interval = window.setTimeout(closeNotification, 4000); } function closeNotification() { - notification.fadeOut(600, function() { - notification.removeClass(); - notification.addClass('closed'); + $notification.fadeOut(600, function() { + $notification.removeClass(); + $notification.addClass('closed'); window.clearInterval(notification_interval); notification_working = false; @@ -1050,14 +1080,14 @@ function closeNotification() { } function init_notifications() { - notification = $("#notification"); + $notification = $('#notification'); - notification.find("a.close").click(function () { + $notification.find('a.close').click(function () { closeNotification(); return false; }); - if (notification.find(".msg").html().length > 0) { + if ($notification.find('.msg').html().length > 0) { notification_working = true; notification_interval = window.setTimeout(closeNotification, 4000); } @@ -1078,12 +1108,12 @@ function notifs_html5_ask_permission() { } function notifs_html5_show(nb) { - if (notifs_html5_permission !== "granted") { + if (notifs_html5_permission !== 'granted') { return; } - var notification = new window.Notification(i18n.notif_title_articles, { - icon: "../themes/icons/favicon-256.png", + const notification = new window.Notification(i18n.notif_title_articles, { + icon: '../themes/icons/favicon-256.png', body: i18n.notif_body_articles.replace('%d', nb), tag: 'freshRssNewArticles', }); @@ -1112,12 +1142,12 @@ function init_notifs_html5() { function refreshUnreads() { $.getJSON('./?c=javascript&a=nbUnreadsPerFeed').done(function (data) { - var isAll = $('.category.all.active').length > 0, - new_articles = false; + const isAll = document.querySelector('.category.all.active'); + let new_articles = false; $.each(data.feeds, function(feed_id, nbUnreads) { feed_id = 'f_' + feed_id; - var elem = $('#' + feed_id).get(0), + const elem = document.getElementById(feed_id), feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; if ((incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads) || isAll) && //Update of current view? @@ -1127,7 +1157,7 @@ function refreshUnreads() { } }); - var nbUnreadTags = 0; + let nbUnreadTags = 0; $.each(data.tags, function(tag_id, nbUnreads) { nbUnreadTags += nbUnreads; @@ -1138,7 +1168,7 @@ function refreshUnreads() { $('.category.tags').attr('data-unread', nbUnreadTags) .find('.title').attr('data-unread', numberFormat(nbUnreadTags)); - var nb_unreads = str2int($('.category.all .title').attr('data-unread')); + const nb_unreads = str2int($('.category.all .title').attr('data-unread')); if (nb_unreads > 0 && new_articles) { faviconNbUnread(nb_unreads); @@ -1148,7 +1178,7 @@ function refreshUnreads() { } // -var url_load_more = "", +var url_load_more = '', load_more = false, box_load_more = null; @@ -1158,7 +1188,7 @@ function load_more_posts() { } load_more = true; - $('#load_more').addClass('loading'); + document.getElementById('load_more').classList.add('loading'); $.get(url_load_more, function (data) { box_load_more.children('.flux:last').after($('#stream', data).children('.flux, .day')); $('.pagination').replaceWith($('.pagination', data)); @@ -1173,7 +1203,7 @@ function load_more_posts() { } $('[id^=day_]').each(function (i) { - var ids = $('[id="' + this.id + '"]'); + const ids = $('[id="' + this.id + '"]'); if (ids.length > 1) { $('[id="' + this.id + '"]:gt(0)').remove(); } @@ -1181,8 +1211,8 @@ function load_more_posts() { init_load_more(box_load_more); - $('#load_more').removeClass('loading'); - $('#bigMarkAsRead').removeAttr('disabled'); + document.getElementById('load_more').classList.remove('loading'); + document.getElementById('bigMarkAsRead').removeAttribute('disabled'); load_more = false; }); } @@ -1198,14 +1228,14 @@ function init_load_more(box) { box_load_more = box; document.body.dispatchEvent(freshrssLoadMoreEvent); - var $next_link = $("#load_more"); + const $next_link = $('#load_more'); if (!$next_link.length) { // no more article to load - url_load_more = ""; + url_load_more = ''; return; } - url_load_more = $next_link.attr("href"); + url_load_more = $next_link.attr('href'); $next_link.click(function () { load_more_posts(); @@ -1216,9 +1246,9 @@ function init_load_more(box) { // function poormanSalt() { //If crypto.getRandomValues is not available - var text = '$2a$04$', - base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789/abcdefghijklmnopqrstuvwxyz'; - for (var i = 22; i > 0; i--) { + const base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789/abcdefghijklmnopqrstuvwxyz'; + let text = '$2a$04$'; + for (let i = 22; i > 0; i--) { text += base.charAt(Math.floor(Math.random() * 64)); } return text; @@ -1226,7 +1256,7 @@ function poormanSalt() { //If crypto.getRandomValues is not available function init_crypto_form() { /* globals dcodeIO */ - var $crypto_form = $('#crypto-form'); + const $crypto_form = $('#crypto-form'); if ($crypto_form.length === 0) { return; } @@ -1240,10 +1270,10 @@ function init_crypto_form() { } $crypto_form.on('submit', function() { - var $submit_button = $(this).find('button[type="submit"]'); + const $submit_button = $(this).find('button[type="submit"]'); $submit_button.attr('disabled', ''); - var success = false; + let success = false; $.ajax({ url: './?c=javascript&a=nonce&user=' + $('#username').val(), dataType: 'json', @@ -1253,7 +1283,7 @@ function init_crypto_form() { openNotification('Invalid user!', 'bad'); } else { try { - var strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function'), + const strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function'), s = dcodeIO.bcrypt.hashSync($('#passwordPlain').val(), data.salt1), c = dcodeIO.bcrypt.hashSync(data.nonce + s, strong ? dcodeIO.bcrypt.genSaltSync(4) : poormanSalt()); $('#challenge').val(c); @@ -1278,7 +1308,7 @@ function init_crypto_form() { function init_confirm_action() { $('body').on('click', '.confirm', function () { - var str_confirmation = $(this).attr('data-str-confirm'); + let str_confirmation = $(this).attr('data-str-confirm'); if (!str_confirmation) { str_confirmation = i18n.confirmation_default; } @@ -1290,15 +1320,15 @@ function init_confirm_action() { function init_print_action() { $('.item.share > a[href="#"]').click(function (e) { - var content = "" + + const content = '' + $(e.target).closest('.flux_content').find('.content').html() + - ""; + ''; - var tmp_window = window.open(); + const tmp_window = window.open(); tmp_window.document.writeln(content); tmp_window.document.close(); tmp_window.focus(); @@ -1310,25 +1340,27 @@ function init_print_action() { } function init_post_action() { - $('.item.share > a[href="POST"]').click(function (event) { - event.preventDefault(); - var form = $(this).next('form'); - $.post(form.data('url'), form.serialize()); + $('.item.share > a[href="POST"]').click(function (e) { + e.preventDefault(); + const $form = $(this).next('form'); + $.post($form.data('url'), $form.serialize()); }); } +var shares = 0; + function init_share_observers() { shares = $('.group-share').length; - $('.share.add').on('click', function(e) { - var opt = $(this).siblings('select').find(':selected'); - var row = $(this).parents('form').data(opt.data('form')); - row = row.replace(/##label##/g, opt.html().trim()); - row = row.replace(/##type##/g, opt.val()); - row = row.replace(/##help##/g, opt.data('help')); + $('.share.add').on('click', function (e) { + const $opt = $(this).siblings('select').find(':selected'); + let row = $(this).parents('form').data($opt.data('form')); + row = row.replace(/##label##/g, $opt.html().trim()); + row = row.replace(/##type##/g, $opt.val()); + row = row.replace(/##help##/g, $opt.data('help')); row = row.replace(/##key##/g, shares); - row = row.replace(/##method##/g, opt.data('method')); - row = row.replace(/##field##/g, opt.data('field')); + row = row.replace(/##method##/g, $opt.data('method')); + row = row.replace(/##field##/g, $opt.data('field')); $(this).parents('.form-group').before(row); shares++; @@ -1343,44 +1375,39 @@ function init_stats_observers() { } function init_remove_observers() { - $('.post').on('click', 'a.remove', function(e) { - var remove_what = $(this).attr('data-remove'); - + $('.post').on('click', 'a.remove', function (e) { + const remove_what = $(this).attr('data-remove'); if (remove_what !== undefined) { - var remove_obj = $('#' + remove_what); - remove_obj.remove(); + $('#' + remove_what).remove(); } - return false; }); } function init_feed_observers() { - $('select[id="category"]').on('change', function() { - var detail = $('#new_category_name').parent(); + $('select[id="category"]').on('change', function () { + const $detail = $('#new_category_name').parent(); if ($(this).val() === 'nc') { - detail.attr('aria-hidden', 'false').show(); - detail.find('input').focus(); + $detail.attr('aria-hidden', 'false').show(); + $detail.find('input').focus(); } else { - detail.attr('aria-hidden', 'true').hide(); + $detail.attr('aria-hidden', 'true').hide(); } }); } function init_password_observers() { - $('.toggle-password').on('mousedown', function(e) { - var button = $(this); - var passwordField = $('#' + button.attr('data-toggle')); - passwordField.attr('type', 'text'); - button.addClass('active'); - + $('.toggle-password').on('mousedown', function (e) { + const $button = $(this), + $passwordField = $('#' + $button.attr('data-toggle')); + $passwordField.attr('type', 'text'); + $button.addClass('active'); return false; - }).on('mouseup', function(e) { - var button = $(this); - var passwordField = $('#' + button.attr('data-toggle')); - passwordField.attr('type', 'password'); - button.removeClass('active'); - + }).on('mouseup', function (e) { + const $button = $(this), + $passwordField = $('#' + $button.attr('data-toggle')); + $passwordField.attr('type', 'password'); + $button.removeClass('active'); return false; }); } @@ -1390,16 +1417,16 @@ function faviconNbUnread(n) { n = str2int($('.category.all .title').attr('data-unread')); } //http://remysharp.com/2010/08/24/dynamic-favicons/ - var canvas = document.createElement('canvas'), + const canvas = document.createElement('canvas'), link = document.getElementById('favicon').cloneNode(true); if (canvas.getContext && link) { canvas.height = canvas.width = 16; - var img = document.createElement('img'); + const img = document.createElement('img'); img.onload = function () { - var ctx = canvas.getContext('2d'); + const ctx = canvas.getContext('2d'); ctx.drawImage(this, 0, 0, canvas.width, canvas.height); if (n > 0) { - var text = ''; + let text = ''; if (n < 1000) { text = n; } else if (n < 100000) { @@ -1422,9 +1449,9 @@ function faviconNbUnread(n) { } function init_slider_observers() { - var slider = $('#slider'), - closer = $('#close-slider'); - if (slider.length < 1) { + const $slider = $('#slider'), + $closer = $('#close-slider'); + if ($slider.length < 1) { return; } @@ -1434,51 +1461,47 @@ function init_slider_observers() { } ajax_loading = true; - var url_slide = $(this).attr('href'); $.ajax({ type: 'GET', - url: url_slide, + url: $(this).attr('href'), data: { ajax: true } }).done(function (data) { - slider.html(data); - closer.addClass('active'); - slider.addClass('active'); + $slider.html(data); + $closer.addClass('active'); + $slider.addClass('active'); ajax_loading = false; }); return false; }); - closer.on('click', function() { - closer.removeClass('active'); - slider.removeClass('active'); + $closer.on('click', function() { + $closer.removeClass('active'); + $slider.removeClass('active'); return false; }); } function init_configuration_alert() { - $(window).on('submit', function(e) { + $(window).on('submit', function (e) { window.hasSubmit = true; }); - $(window).on('beforeunload', function(e) { + $(window).on('beforeunload', function (e) { if (window.hasSubmit) { return; } - var fields = $("[data-leave-validation]"); - for (var i = 0; i < fields.length; i++) { - if ($(fields[i]).attr('type') === 'checkbox' || $(fields[i]).attr('type') === 'radio') { - // The use of != is done on purpose to check boolean against integer - if ($(fields[i]).is(':checked') != $(fields[i]).attr('data-leave-validation')) { - return false; - } - } else { - if ($(fields[i]).attr('data-leave-validation') !== $(fields[i]).val()) { + const inputs = document.querySelectorAll('[data-leave-validation]'); + for (let i = inputs.length - 1; i >= 0; i--) { + const input = inputs[i]; + if (input.type === 'checkbox' || input.type === 'radio') { + if (input.checked != input.getAttribute('data-leave-validation')) { return false; } + } else if (input.value != input.getAttribute('data-leave-validation')) { + return false; } } - return; }); } @@ -1488,19 +1511,6 @@ function init_subscription() { }); } -function parseJsonVars() { - var jsonVars = document.getElementById('jsonVars'), - json = JSON.parse(jsonVars.innerHTML); - jsonVars.outerHTML = ''; - window.context = json.context; - window.shortcuts = json.shortcuts; - window.url = json.url; - window.i18n = json.i18n; - window.icons = json.icons; - icons.read = decodeURIComponent(icons.read); - icons.unread = decodeURIComponent(icons.unread); -} - function init_normal() { $stream = $('#stream'); if ($stream.length < 1) { @@ -1567,7 +1577,6 @@ function init_afterDOM() { } } -parseJsonVars(); init_beforeDOM(); //Can be called before DOM is fully loaded if (document.readyState && document.readyState !== 'loading') { -- cgit v1.2.3 From cd9a9a93099b80fb3f8c2ba09266aa31955cbdd6 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 25 Dec 2018 15:34:25 +0100 Subject: First version of batch scroll as read Mark-as-read requests are queued and sent max once per second --- p/scripts/main.js | 109 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 38 deletions(-) diff --git a/p/scripts/main.js b/p/scripts/main.js index 555e92a40..a3a9317d6 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -161,22 +161,15 @@ function incUnreadsTag(tag_id, nb) { } } -var pending_entries = {}; +var pending_entries = {}, + mark_read_queue = []; -function mark_read(div, only_not_read) { - if (!div || !div.id || context.anonymous || - (only_not_read && !div.classList.contains('not_read'))) { - return false; +function send_mark_read_queue(queue, asRead) { + let url = '.?c=entry&a=read' + (asRead ? '' : '&is_read=0'); + for (let i = queue.length - 1; i >= 0; i--) { + url += '&id[]=' + queue[i]; } - if (pending_entries[div.id]) { - return false; - } - pending_entries[div.id] = true; - - let url = '.?c=entry&a=read&id=' + div.id.replace(/^flux_/, '') + - (div.classList.contains('not_read') ? '' : '&is_read=0'); - $.ajax({ type: 'POST', url: url, @@ -185,42 +178,75 @@ function mark_read(div, only_not_read) { _csrf: context.csrf, }, }).done(function (data) { - let inc = 0; - if (div.classList.contains('not_read')) { - div.classList.remove('not_read'); - div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=0', '') + '&is_read=1'); }); - div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = icons.read; }); - inc--; - } else { - div.classList.add('not_read', 'keep_unread'); - div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=1', '')); }); - div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = icons.unread; }); - inc++; - } - - let feed_link = div.querySelector('.website > a'); - if (feed_link) { - let feed_url = feed_link.getAttribute('href'); - let feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); - incUnreadsFeed(div, feed_id, inc); + for (let i = queue.length - 1; i >= 0; i--) { + const div = document.getElementById('flux_' + queue[i]), + myIcons = icons; + let inc = 0; + if (div.classList.contains('not_read')) { + div.classList.remove('not_read'); + div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=0', '') + '&is_read=1'); }); + div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.read; }); + inc--; + } else { + div.classList.add('not_read', 'keep_unread'); + div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=1', '')); }); + div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.unread; }); + inc++; + } + let feed_link = div.querySelector('.website > a'); + if (feed_link) { + let feed_url = feed_link.getAttribute('href'); + let feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); + incUnreadsFeed(div, feed_id, inc); + } + delete pending_entries[queue[i]]; } faviconNbUnread(); - if (data.tags) { let tagIds = Object.keys(data.tags); for (let i = tagIds.length - 1; i >= 0; i--) { let tagId = tagIds[i]; - incUnreadsTag(tagId, inc * data.tags[tagId].length); + incUnreadsTag(tagId, (asRead ? -1 : 1) * data.tags[tagId].length); } } - - delete pending_entries[div.id]; }).fail(function (data) { openNotification(i18n.notif_request_failed, 'bad'); - delete pending_entries[div.id]; + for (let i = queue.length - 1; i >= 0; i--) { + delete pending_entries[queue[i]]; + } }); } +var send_mark_read_queue_timeout = 0; + +function mark_read(div, only_not_read) { + if (!div || !div.id || context.anonymous || + (only_not_read && !div.classList.contains('not_read'))) { + return false; + } + const entryId = div.id.replace(/^flux_/, ''); + if (pending_entries[entryId]) { + return false; + } + pending_entries[entryId] = true; + + const asRead = div.classList.contains('not_read'); + if (asRead) { + mark_read_queue.push(entryId); + if (send_mark_read_queue_timeout == 0) { + send_mark_read_queue_timeout = setTimeout(function () { + send_mark_read_queue_timeout = 0; + const queue = mark_read_queue.slice(0); + mark_read_queue = []; + send_mark_read_queue(queue, asRead); + }, 1000); + } + } else { + const queue = [ entryId ]; + send_mark_read_queue(queue, asRead); + } +} + function mark_favorite(div) { if (!div) { return false; @@ -1211,8 +1237,15 @@ function load_more_posts() { init_load_more(box_load_more); - document.getElementById('load_more').classList.remove('loading'); - document.getElementById('bigMarkAsRead').removeAttribute('disabled'); + const bigMarkAsRead = document.getElementById('bigMarkAsRead'), + div_load_more = document.getElementById('load_more'); + if (bigMarkAsRead) { + bigMarkAsRead.removeAttribute('disabled'); + } + if (div_load_more) { + div_load_more.classList.remove('loading'); + } + load_more = false; }); } -- cgit v1.2.3 From 6fa09318ce4d510535c7c13723502b9917a78e85 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 25 Dec 2018 16:09:48 +0100 Subject: Semove superfluous window. object --- p/scripts/main.js | 56 +++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/p/scripts/main.js b/p/scripts/main.js index a3a9317d6..d6d018bda 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -500,7 +500,7 @@ function user_filter(key) { return; } // Display the filter div - window.location.hash = filter.attr('id'); + location.hash = filter.attr('id'); // Force scrolling to the filter div const scroll = needsScroll($('.header')); if (scroll !== 0) { @@ -528,7 +528,7 @@ function auto_share(key) { return; } // Display the share div - window.location.hash = $share.attr('id'); + location.hash = $share.attr('id'); // Force scrolling to the share div const scroll = needsScroll($share.closest('.bottom')); if (scroll !== 0) { @@ -566,12 +566,12 @@ function init_posts() { let lastScroll = 0, //Throttle timerId = 0; $box_to_follow.scroll(function () { - window.clearTimeout(timerId); + clearTimeout(timerId); if (lastScroll + 500 < Date.now()) { lastScroll = Date.now(); scrollAsRead($box_to_follow); } else { - timerId = window.setTimeout(function() { + timerId = setTimeout(function () { scrollAsRead($box_to_follow); }, 500); } @@ -600,7 +600,7 @@ function init_column_categories() { } $('#aside_feed').on('click', '.tree-folder>.tree-folder-title>a.dropdown-toggle', function () { - $(this).children().each(function() { + $(this).children().each(function () { if (this.alt === '▽') { this.src = this.src.replace('/icons/down.', '/icons/up.'); this.alt = '△'; @@ -643,11 +643,11 @@ function init_column_categories() { } function init_shortcuts() { - if (!(window.shortcut && window.shortcuts)) { + if (!(window.shortcut)) { if (window.console) { console.log('FreshRSS waiting for shortcut.js…'); } - window.setTimeout(init_shortcuts, 200); + setTimeout(init_shortcuts, 200); return; } // Manipulation shortcuts @@ -795,7 +795,7 @@ function init_shortcuts() { }); shortcut.add(shortcuts.close_dropdown, function () { - window.location.hash = null; + location.hash = null; }, { 'disable_in_input': true }); @@ -1017,7 +1017,7 @@ function updateFeed(feeds, feeds_count) { noCommit: 0, }, }).always(function (data) { - window.location.reload(); + location.reload(); }); } else { updateFeed(feeds, feeds_count); @@ -1092,15 +1092,15 @@ function openNotification(msg, status) { $notification.find('.msg').html(msg); $notification.fadeIn(300); - notification_interval = window.setTimeout(closeNotification, 4000); + notification_interval = setTimeout(closeNotification, 4000); } function closeNotification() { - $notification.fadeOut(600, function() { + $notification.fadeOut(600, function () { $notification.removeClass(); $notification.addClass('closed'); - window.clearInterval(notification_interval); + clearInterval(notification_interval); notification_working = false; }); } @@ -1115,7 +1115,7 @@ function init_notifications() { if ($notification.find('.msg').html().length > 0) { notification_working = true; - notification_interval = window.setTimeout(closeNotification, 4000); + notification_interval = setTimeout(closeNotification, 4000); } } // @@ -1144,14 +1144,14 @@ function notifs_html5_show(nb) { tag: 'freshRssNewArticles', }); - notification.onclick = function() { - window.location.reload(); + notification.onclick = function () { + location.reload(); window.focus(); notification.close(); }; if (context.html5_notif_timeout !== 0) { - setTimeout(function() { + setTimeout(function () { notification.close(); }, context.html5_notif_timeout * 1000); } @@ -1171,7 +1171,7 @@ function refreshUnreads() { const isAll = document.querySelector('.category.all.active'); let new_articles = false; - $.each(data.feeds, function(feed_id, nbUnreads) { + $.each(data.feeds, function (feed_id, nbUnreads) { feed_id = 'f_' + feed_id; const elem = document.getElementById(feed_id), feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; @@ -1185,7 +1185,7 @@ function refreshUnreads() { let nbUnreadTags = 0; - $.each(data.tags, function(tag_id, nbUnreads) { + $.each(data.tags, function (tag_id, nbUnreads) { nbUnreadTags += nbUnreads; $('#t_' + tag_id).attr('data-unread', nbUnreads) .children('.item-title').attr('data-unread', numberFormat(nbUnreads)); @@ -1298,11 +1298,11 @@ function init_crypto_form() { if (window.console) { console.log('FreshRSS waiting for bcrypt.js…'); } - window.setTimeout(init_crypto_form, 100); + setTimeout(init_crypto_form, 100); return; } - $crypto_form.on('submit', function() { + $crypto_form.on('submit', function () { const $submit_button = $(this).find('button[type="submit"]'); $submit_button.attr('disabled', ''); @@ -1329,7 +1329,7 @@ function init_crypto_form() { openNotification('Crypto exception! ' + e, 'bad'); } } - }).fail(function() { + }).fail(function () { openNotification('Communication error!', 'bad'); }); @@ -1402,7 +1402,7 @@ function init_share_observers() { } function init_stats_observers() { - $('.select-change').on('change', function(e) { + $('.select-change').on('change', function (e) { redirect($(this).find(':selected').data('url')); }); } @@ -1488,7 +1488,7 @@ function init_slider_observers() { return; } - $('.post').on('click', '.open-slider', function() { + $('.post').on('click', '.open-slider', function () { if (ajax_loading) { return false; } @@ -1509,7 +1509,7 @@ function init_slider_observers() { return false; }); - $closer.on('click', function() { + $closer.on('click', function () { $closer.removeClass('active'); $slider.removeClass('active'); return false; @@ -1550,7 +1550,7 @@ function init_normal() { if (window.console) { console.log('FreshRSS waiting for content…'); } - window.setTimeout(init_normal, 100); + setTimeout(init_normal, 100); return; } init_column_categories(); @@ -1565,7 +1565,7 @@ function init_beforeDOM() { if (window.console) { console.log('FreshRSS waiting for jQuery…'); } - window.setTimeout(init_beforeDOM, 100); + setTimeout(init_beforeDOM, 100); return; } if (['normal', 'reader', 'global'].indexOf(context.current_view) >= 0) { @@ -1578,7 +1578,7 @@ function init_afterDOM() { if (window.console) { console.log('FreshRSS waiting again for jQuery…'); } - window.setTimeout(init_afterDOM, 100); + setTimeout(init_afterDOM, 100); return; } init_notifications(); @@ -1592,7 +1592,7 @@ function init_afterDOM() { init_print_action(); init_post_action(); init_notifs_html5(); - window.setInterval(refreshUnreads, 120000); + setInterval(refreshUnreads, 120000); } else { init_subscription(); init_crypto_form(); -- cgit v1.2.3 From 8f03b370cc79f275e92b04ca6f25ef2b13fa867f Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 25 Dec 2018 16:10:20 +0100 Subject: Send item queue as POST Which also simplifies the request --- p/scripts/main.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/p/scripts/main.js b/p/scripts/main.js index d6d018bda..5d5679839 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -165,17 +165,13 @@ var pending_entries = {}, mark_read_queue = []; function send_mark_read_queue(queue, asRead) { - let url = '.?c=entry&a=read' + (asRead ? '' : '&is_read=0'); - for (let i = queue.length - 1; i >= 0; i--) { - url += '&id[]=' + queue[i]; - } - $.ajax({ type: 'POST', - url: url, + url: '.?c=entry&a=read' + (asRead ? '' : '&is_read=0'), data: { ajax: true, _csrf: context.csrf, + 'id[]': queue, }, }).done(function (data) { for (let i = queue.length - 1; i >= 0; i--) { -- cgit v1.2.3 From caa893e14b46bc9b52f251ca93eada0c57634302 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 27 Dec 2018 03:34:56 +0100 Subject: Optimise onscroll routines Much lighter rework: auto-mark-as-read, auto-remove-articles, auto-load-more. In particular, use a single onscroll event handler with a throtte. Continue removing jQuery when possible. --- p/scripts/main.js | 350 ++++++++++++++++++++++++------------------------------ 1 file changed, 157 insertions(+), 193 deletions(-) diff --git a/p/scripts/main.js b/p/scripts/main.js index 5d5679839..227a4b47a 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -5,17 +5,15 @@ // if (!NodeList.prototype.forEach) NodeList.prototype.forEach = Array.prototype.forEach; if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.webkitMatchesSelector; -if (!Element.prototype.closest) { - Element.prototype.closest = function (s) { +if (!Element.prototype.closest) Element.prototype.closest = function (s) { let el = this; - if (!document.documentElement.contains(el)) return null; do { if (el.matches(s)) return el; - el = el.parentElement || el.parentNode; - } while (el !== null && el.nodeType == 1); + el = el.parentElement; + } while (el); return null; }; -} +if (!Element.prototype.remove) Element.prototype.remove = function () { if (this.parentNode) this.parentNode.removeChild(this); }; // // @@ -36,7 +34,6 @@ var context, i18n, icons, shortcuts, urls; var $stream = null, ajax_loading = false, - isCollapsed = true, $nav_entries = null; // @@ -50,14 +47,11 @@ function redirect(url, new_tab) { } } -function needsScroll($elem) { - const $win = $(window), - winTop = $win.scrollTop(), - winHeight = $win.height(), - winBottom = winTop + winHeight, - elemTop = $elem.offset().top, - elemBottom = elemTop + $elem.outerHeight(); - return (elemTop < winTop || elemBottom > winBottom) ? elemTop - (winHeight / 2) : 0; +function needsScroll(elem) { + const winBottom = document.documentElement.scrollTop + document.documentElement.clientHeight, + elemBottom = elem.offsetTop + elem.offsetHeight; + return (elem.offsetTop < document.documentElement.scrollTop || elemBottom > winBottom) ? + elem.offsetTop - (document.documentElement.clientHeight / 2) : 0; } function str2int(str) { @@ -134,7 +128,7 @@ function incUnreadsFeed(article, feed_id, nb) { // Update unread: title document.title = document.title.replace(/^((?:\([ 0-9]+\) )?)/, function (m, p1) { const feed = document.getElementById(feed_id); - if (article || (feed.closest('.active') && $(feed).siblings('.active').length === 0)) { + if (article || feed.closest('.active')) { isCurrentView = true; return incLabel(p1, nb, true); } else if (document.querySelector('.all.active')) { @@ -195,7 +189,7 @@ function send_mark_read_queue(queue, asRead) { let feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); incUnreadsFeed(div, feed_id, inc); } - delete pending_entries[queue[i]]; + delete pending_entries['flux_' + queue[i]]; } faviconNbUnread(); if (data.tags) { @@ -205,10 +199,11 @@ function send_mark_read_queue(queue, asRead) { incUnreadsTag(tagId, (asRead ? -1 : 1) * data.tags[tagId].length); } } + onScroll(); }).fail(function (data) { openNotification(i18n.notif_request_failed, 'bad'); for (let i = queue.length - 1; i >= 0; i--) { - delete pending_entries[queue[i]]; + delete pending_entries['flux_' + queue[i]]; } }); } @@ -220,13 +215,13 @@ function mark_read(div, only_not_read) { (only_not_read && !div.classList.contains('not_read'))) { return false; } - const entryId = div.id.replace(/^flux_/, ''); - if (pending_entries[entryId]) { + if (pending_entries[div.id]) { return false; } - pending_entries[entryId] = true; + pending_entries[div.id] = true; - const asRead = div.classList.contains('not_read'); + const asRead = div.classList.contains('not_read'), + entryId = div.id.replace(/^flux_/, ''); if (asRead) { mark_read_queue.push(entryId); if (send_mark_read_queue_timeout == 0) { @@ -278,8 +273,8 @@ function mark_favorite(div) { div.querySelectorAll('a.bookmark').forEach(function (a) { a.setAttribute('href', data.url); }); div.querySelectorAll('a.bookmark > .icon').forEach(function (img) { img.outerHTML = data.icon; }); - const favourites = $('#aside_feed .favorites .title').contents().last().get(0); - if (favourites && favourites.textContent) { + const favourites = document.querySelector('#aside_feed .favorites .title'); + if (favourites) { favourites.textContent = favourites.textContent.replace(/((?: \([ 0-9]+\))?\s*)$/, function (m, p1) { return incLabel(p1, inc, false); }); @@ -300,117 +295,77 @@ function mark_favorite(div) { }); } -function toggleContent($new_active, $old_active, skipping) { +function toggleContent(new_active, old_active, skipping) { // If skipping, move current without activating or marking as read - if ($new_active.length === 0) { + if (!new_active) { return; } if (context.does_lazyload && !skipping) { - $new_active.find('img[data-original], iframe[data-original]').each(function () { - this.setAttribute('src', this.getAttribute('data-original')); - this.removeAttribute('data-original'); + new_active.querySelectorAll('img[data-original], iframe[data-original]').forEach(function (elem) { + elem.setAttribute('src', elem.getAttribute('data-original')); + elem.removeAttribute('data-original'); }); } - if ($old_active[0] !== $new_active[0]) { - if (isCollapsed && !skipping) { // BUG?: isCollapsed can only ever be true - $new_active.addClass('active'); + if (old_active !== new_active) { + if (!skipping) { + new_active.classList.add('active'); } - $old_active.removeClass('active current'); - $new_active.addClass('current'); - if (context.auto_remove_article && !$old_active.hasClass('not_read') && !skipping) { - auto_remove($old_active); + new_active.classList.add('current'); + if (old_active) { + old_active.classList.remove('active'); + old_active.classList.remove('current'); //Split for IE11 } } else { // collapse_entry calls toggleContent(flux_current, flux_current, false) - $new_active.toggleClass('active'); + new_active.classList.toggle('active'); } const relative_move = context.current_view === 'global', - $box_to_move = $(relative_move ? '#panel' : 'html,body'); + box_to_move = relative_move ? document.getElementById('#panel') : document.documentElement; if (context.sticky_post) { - let prev_article = $new_active.prevAll('.flux'), - new_pos = $new_active.offset().top, - old_scroll = $box_to_move.scrollTop(); + let prev_article = new_active.previousElementSibling, + new_pos = new_active.offsetTop + document.documentElement.scrollTop, + old_scroll = box_to_move.scrollTop; - if (prev_article.length > 0 && new_pos - prev_article.offset().top <= 150) { - new_pos = prev_article.offset().top; + if (prev_article && new_active.offsetTop - prev_article.offsetTop <= 150) { + new_pos = prev_article.offsetTop; if (relative_move) { - new_pos -= $box_to_move.offset().top; + new_pos -= box_to_move.offsetTop; } } if (skipping) { // when skipping, this feels more natural if it's not so near the top - new_pos -= $(window).height() / 4; + new_pos -= document.body.clientHeight / 4; } - if (context.hide_posts) { - if (relative_move) { - new_pos += old_scroll; - } - - $new_active.children('.flux_content').first().each(function () { - $box_to_move.scrollTop(new_pos).scrollTop(); - }); - } else { - if (relative_move) { - new_pos += old_scroll; - } - - $box_to_move.scrollTop(new_pos).scrollTop(); + if (relative_move) { + new_pos += old_scroll; } + box_to_move.scrollTop = new_pos; } - if (context.auto_mark_article && $new_active.hasClass('active') && !skipping) { - mark_read($new_active[0], true); + if (context.auto_mark_article && new_active.classList.contains('active') && !skipping) { + mark_read(new_active, true); } + onScroll(); } -function auto_remove($element) { - let $p = $element.prev(), - $n = $element.next(); - if ($p.hasClass('day') && $n.hasClass('day')) { - $p.remove(); - } - $element.remove(); - $('#stream > .flux:not(.not_read):not(.active)').remove(); +function prev_entry(skipping) { + const old_active = document.querySelector('.flux.current'), + new_active = old_active ? old_active.previousElementSibling : document.querySelector('.flux'); + toggleContent(new_active, old_active, skipping); } -function prev_entry() { - let $old_active = $('.flux.current'), - $new_active = $old_active.length === 0 ? $('.flux:last') : $old_active.prevAll('.flux:first'); - toggleContent($new_active, $old_active, false); -} - -function next_entry() { - let $old_active = $('.flux.current'), - $new_active = $old_active.length === 0 ? $('.flux:first') : $old_active.nextAll('.flux:first'); - toggleContent($new_active, $old_active, false); - - if ($new_active.nextAll().length < 3) { - load_more_posts(); - } -} - -function skip_prev_entry() { - let $old_active = $('.flux.current'), - $new_active = $old_active.length === 0 ? $('.flux:last') : $old_active.prevAll('.flux:first'); - toggleContent($new_active, $old_active, true); -} - -function skip_next_entry() { - let $old_active = $('.flux.current'), - $new_active = $old_active.length === 0 ? $('.flux:first') : $old_active.nextAll('.flux:first'); - toggleContent($new_active, $old_active, true); - - if ($new_active.nextAll().length < 3) { - load_more_posts(); - } +function next_entry(skipping) { + const old_active = document.querySelector('.flux.current'), + new_active = old_active ? old_active.nextElementSibling : document.querySelector('.flux'); + toggleContent(new_active, old_active, skipping); } function prev_feed() { - let $active_feed = $('#aside_feed .tree-folder-items .item.active'); + const $active_feed = $('#aside_feed .tree-folder-items .item.active'); if ($active_feed.length > 0) { $active_feed.prevAll(':visible:first').find('a').each(function () { this.click(); }); } else { @@ -419,7 +374,7 @@ function prev_feed() { } function next_feed() { - let $active_feed = $('#aside_feed .tree-folder-items .item.active'); + const $active_feed = $('#aside_feed .tree-folder-items .item.active'); if ($active_feed.length > 0) { $active_feed.nextAll(':visible:first').find('a').each(function () { this.click(); }); } else { @@ -428,24 +383,24 @@ function next_feed() { } function first_feed() { - let $feed = $('#aside_feed .tree-folder-items.active .item:visible:first'); - if ($feed.length > 0) { - $feed.find('a')[1].click(); + const a = document.querySelector('#aside_feed .category.active .feed:not([data-unread="0"]) a.item-title'); + if (a) { + a.click(); } } function last_feed() { - let $feed = $('#aside_feed .tree-folder-items.active .item:visible:last'); - if ($feed.length > 0) { - $feed.find('a')[1].click(); + const links = document.querySelectorAll('#aside_feed .category.active .feed:not([data-unread="0"]) a.item-title'); + if (links && links.length > 0) { + links[links.length - 1].click(); } } function prev_category() { - let $active_cat = $('#aside_feed .tree-folder.active'); + const $active_cat = $('#aside_feed .tree-folder.active'); if ($active_cat.length > 0) { - let $prev_cat = $active_cat.prevAll(':visible:first').find('.tree-folder-title .title'); + const $prev_cat = $active_cat.prevAll(':visible:first').find('.tree-folder-title .title'); if ($prev_cat.length > 0) { $prev_cat[0].click(); } @@ -456,10 +411,10 @@ function prev_category() { } function next_category() { - let $active_cat = $('#aside_feed .tree-folder.active'); + const $active_cat = $('#aside_feed .tree-folder.active'); if ($active_cat.length > 0) { - let $next_cat = $active_cat.nextAll(':visible:first').find('.tree-folder-title .title'); + const $next_cat = $active_cat.nextAll(':visible:first').find('.tree-folder-title .title'); if ($next_cat.length > 0) { $next_cat[0].click(); } @@ -470,40 +425,40 @@ function next_category() { } function first_category() { - let $cat = $('#aside_feed .tree-folder:visible:first'); - if ($cat.length > 0) { - $cat.find('.tree-folder-title .title')[0].click(); + const a = document.querySelector('#aside_feed .category:not([data-unread="0"]) a.title'); + if (a) { + a.click(); } } function last_category() { - let $cat = $('#aside_feed .tree-folder:visible:last'); - if ($cat.length > 0) { - $cat.find('.tree-folder-title .title')[0].click(); + const links = document.querySelectorAll('#aside_feed .category:not([data-unread="0"]) a.title'); + if (links && links.length > 0) { + links[links.length - 1].click(); } } function collapse_entry() { - let $flux_current = $('.flux.current'); - toggleContent($flux_current, $flux_current, false); + const flux_current = document.querySelector('.flux.current'); + toggleContent(flux_current, flux_current, false); } function user_filter(key) { - const filter = $('#dropdown-query'), - filters = filter.siblings('.dropdown-menu').find('.item.query a'); + const $filter = $('#dropdown-query'), + $filters = $filter.siblings('.dropdown-menu').find('.item.query a'); if (typeof key === 'undefined') { - if (!filter.length) { + if (!$filters.length) { return; } // Display the filter div - location.hash = filter.attr('id'); + location.hash = $filters.attr('id'); // Force scrolling to the filter div - const scroll = needsScroll($('.header')); + const scroll = needsScroll(document.querySelector('.header')); if (scroll !== 0) { - $('html,body').scrollTop(scroll); + document.documentElement.scrollTop = scroll; } // Force the key value if there is only one action, so we can trigger it automatically - if (filters.length === 1) { + if ($filters.length === 1) { key = 1; } else { return; @@ -511,27 +466,27 @@ function user_filter(key) { } // Trigger selected share action key = parseInt(key); - if (key <= filters.length) { - filters[key - 1].click(); + if (key <= $filters.length) { + $filters[key - 1].click(); } } function auto_share(key) { - const $share = $('.flux.current.active').find('.dropdown-target[id^="dropdown-share"]'), - $shares = $share.siblings('.dropdown-menu').find('.item a'); + const share = document.querySelector('.flux.current.active .dropdown-target[id^="dropdown-share"]'); + if (!share) { + return; + } + const shares = share.parentElement.querySelectorAll('.dropdown-menu .item a'); if (typeof key === 'undefined') { - if (!$share.length) { - return; - } // Display the share div - location.hash = $share.attr('id'); + location.hash = share.id; // Force scrolling to the share div - const scroll = needsScroll($share.closest('.bottom')); - if (scroll !== 0) { - $('html,body').scrollTop(scroll); + const scrollTop = needsScroll(share.closest('.bottom')); + if (scrollTop !== 0) { + document.documentElement.scrollTop = scrollTop; } // Force the key value if there is only one action, so we can trigger it automatically - if ($shares.length === 1) { + if (shares.length === 1) { key = 1; } else { return; @@ -539,54 +494,72 @@ function auto_share(key) { } // Trigger selected share action and hide the share div key = parseInt(key); - if (key <= $shares.length) { - $shares[key - 1].click(); - $share.siblings('.dropdown-menu').find('.dropdown-close a')[0].click(); + if (key <= shares.length) { + shares[key - 1].click(); + share.parentElement.querySelector('.dropdown-menu .dropdown-close a').click(); } } -function scrollAsRead($box_to_follow) { - const minTop = 40 + (context.current_view === 'global' ? $box_to_follow.offset().top : $box_to_follow.scrollTop()); - $('.not_read:not(.keep_unread):visible').each(function () { - const $this = $(this); - if ($this.offset().top + $this.height() < minTop) { - mark_read(this, true); - } - }); +var box_to_follow; + +function onScroll() { + if (!box_to_follow) { + return; + } + if (context.auto_mark_scroll) { + const minTop = 40 + box_to_follow.scrollTop; + document.querySelectorAll('.not_read:not(.keep_unread)').forEach(function (div) { + if (div.offsetHeight > 0 && + div.offsetParent.offsetTop + div.offsetTop + div.offsetHeight < minTop) { + mark_read(div, true); + } + }); + } + if (context.auto_remove_article) { + let maxTop = box_to_follow.scrollTop, + scrollOffset = 0; + document.querySelectorAll('.flux:not(.active):not(.keep_unread)').forEach(function (div) { + if (!pending_entries[div.id] && div.offsetHeight > 0 && + div.offsetParent.offsetTop + div.offsetTop + div.offsetHeight < maxTop) { + const p = div.previousElementSibling, + n = div.nextElementSibling; + if (p && p.classList.contains('day') && n && n.classList.contains('day')) { + p.remove(); + } + maxTop -= div.offsetHeight; + scrollOffset -= div.offsetHeight; + div.remove(); + } + }); + if (scrollOffset != 0) { + box_to_follow.scrollTop += scrollOffset; + return; //onscroll will be called again + } + } + if (context.auto_load_more) { + const load_more = document.getElementById('mark-read-pagination'); + if (load_more && box_to_follow.scrollTop > 0 && + box_to_follow.scrollTop + box_to_follow.offsetHeight >= load_more.offsetTop) { + load_more_posts(); + } + } } function init_posts() { - let $box_to_follow = context.current_view === 'global' ? $('#panel') : $(window); - - if (context.auto_mark_scroll) { + if (context.auto_load_more || context.auto_mark_scroll || context.auto_remove_article) { + box_to_follow = context.current_view === 'global' ? document.getElementById('panel') : document.documentElement; let lastScroll = 0, //Throttle timerId = 0; - $box_to_follow.scroll(function () { + (box_to_follow === document.documentElement ? window : box_to_follow).onscroll = function () { clearTimeout(timerId); if (lastScroll + 500 < Date.now()) { lastScroll = Date.now(); - scrollAsRead($box_to_follow); + onScroll(); } else { - timerId = setTimeout(function () { - scrollAsRead($box_to_follow); - }, 500); - } - }); - } - - if (context.auto_load_more) { - $box_to_follow.scroll(function () { - const $load_more = $('#load_more'); - if (!$load_more.is(':visible')) { - return; + timerId = setTimeout(onScroll, 500); } - const boxBot = $box_to_follow.scrollTop() + $box_to_follow.height(), - load_more_top = $load_more.offset().top; - if (boxBot >= load_more_top) { - load_more_posts(); - } - }); - $box_to_follow.scroll(); + }; + onScroll(); } } @@ -699,10 +672,10 @@ function init_shortcuts() { } // Entry navigation shortcuts - shortcut.add(shortcuts.prev_entry, prev_entry, { + shortcut.add(shortcuts.prev_entry, function () { prev_entry(false); }, { 'disable_in_input': true }); - shortcut.add(shortcuts.skip_prev_entry, skip_prev_entry, { + shortcut.add(shortcuts.skip_prev_entry, function () { prev_entry(true); }, { 'disable_in_input': true }); shortcut.add(shortcuts.first_entry, function () { @@ -715,10 +688,10 @@ function init_shortcuts() { }, { 'disable_in_input': true }); - shortcut.add(shortcuts.next_entry, next_entry, { + shortcut.add(shortcuts.next_entry, function () { next_entry(false); }, { 'disable_in_input': true }); - shortcut.add(shortcuts.skip_next_entry, skip_next_entry, { + shortcut.add(shortcuts.skip_next_entry, function () { next_entry(true); }, { 'disable_in_input': true }); shortcut.add(shortcuts.last_entry, function () { @@ -772,15 +745,11 @@ function init_shortcuts() { 'disable_in_input': true }); - shortcut.add(shortcuts.load_more, function () { - load_more_posts(); - }, { + shortcut.add(shortcuts.load_more, load_more_posts, { 'disable_in_input': true }); - shortcut.add(shortcuts.focus_search, function () { - focus_search(); - }, { + shortcut.add(shortcuts.focus_search, focus_search, { 'disable_in_input': true }); @@ -832,22 +801,17 @@ function init_stream(divStream) { } const old_active = document.querySelector('.flux.current'), new_active = this.parentNode; - isCollapsed = true; if (e.target.tagName.toUpperCase() === 'A') { //Leave real links alone if (context.auto_mark_article) { mark_read(new_active, true); } return true; } - toggleContent($(new_active), $(old_active), false); + toggleContent(new_active, old_active, false); }); divStream.on('click', '.flux a.read', function () { - const $active = $(this).parents('.flux'); - if (context.auto_remove_article && $active.hasClass('not_read')) { - auto_remove($active); - } - mark_read($active[0], false); + mark_read(this.closest('.flux'), false); return false; }); @@ -872,7 +836,7 @@ function init_stream(divStream) { const ev = jQuery.Event('click'); ev.ctrlKey = true; $(this).trigger(ev); - } else if(e.which == 1) { + } else if (e.which == 1) { // Normal click, just toggle article. $(this).parent().click(); } @@ -900,11 +864,11 @@ function init_stream(divStream) { function init_nav_entries() { $nav_entries = $('#nav_entries'); $nav_entries.find('.previous_entry').click(function () { - prev_entry(); + prev_entry(false); return false; }); $nav_entries.find('.next_entry').click(function () { - next_entry(); + next_entry(false); return false; }); $nav_entries.find('.up').click(function () { -- cgit v1.2.3 From f9555db678679d04fdc28bb2d31eb00135209a16 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 27 Dec 2018 03:49:20 +0100 Subject: IE11 fixes --- p/scripts/main.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/p/scripts/main.js b/p/scripts/main.js index 227a4b47a..7b49ebeb2 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -49,9 +49,10 @@ function redirect(url, new_tab) { function needsScroll(elem) { const winBottom = document.documentElement.scrollTop + document.documentElement.clientHeight, - elemBottom = elem.offsetTop + elem.offsetHeight; - return (elem.offsetTop < document.documentElement.scrollTop || elemBottom > winBottom) ? - elem.offsetTop - (document.documentElement.clientHeight / 2) : 0; + elemTop = elem.offsetParent.offsetTop + elem.offsetTop, + elemBottom = elemTop + elem.offsetHeight; + return (elemTop < document.documentElement.scrollTop || elemBottom > winBottom) ? + elemTop - (document.documentElement.clientHeight / 2) : 0; } function str2int(str) { @@ -178,7 +179,8 @@ function send_mark_read_queue(queue, asRead) { div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.read; }); inc--; } else { - div.classList.add('not_read', 'keep_unread'); + div.classList.add('not_read'); + div.classList.add('keep_unread'); //Split for IE11 div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=1', '')); }); div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.unread; }); inc++; -- cgit v1.2.3 From 4872442c62f63ef97a0e12c43b4700b98ebcdc15 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 26 Jan 2019 16:23:48 +0100 Subject: Start 1.13.2-dev --- CHANGELOG.md | 3 +++ constants.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9490f25e..685be5a62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # FreshRSS changelog +## 2019-0X-XX FreshRSS 1.13.2-dev + + ## 2019-01-26 FreshRSS 1.13.1 * Features diff --git a/constants.php b/constants.php index 8a49d7c01..2072e5ea1 100644 --- a/constants.php +++ b/constants.php @@ -2,7 +2,7 @@ //NB: Do not edit; use ./constants.local.php instead. // -define('FRESHRSS_VERSION', '1.13.1'); +define('FRESHRSS_VERSION', '1.13.2-dev'); define('FRESHRSS_WEBSITE', 'https://freshrss.org'); define('FRESHRSS_WIKI', 'https://freshrss.github.io/FreshRSS/'); -- cgit v1.2.3 From 65602ab1935270f25b84108db723b1dae0868eed Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Thu, 31 Jan 2019 23:00:29 +0100 Subject: Case insensitive Authorization https://github.com/FreshRSS/FreshRSS/issues/2233 --- p/api/.htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p/api/.htaccess b/p/api/.htaccess index 937983ec9..2bd6b1d14 100644 --- a/p/api/.htaccess +++ b/p/api/.htaccess @@ -1,5 +1,5 @@ - SetEnvIf "^Authorization$" "(.*)" HTTP_AUTHORIZATION=$1 + SetEnvIfNoCase "^Authorization$" "(.*)" HTTP_AUTHORIZATION=$1 -- cgit v1.2.3 From 5bd3d92b9f1abad9f27cbe7fc138a328f8dbaa6f Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 3 Feb 2019 12:30:34 +0100 Subject: Alpine 3.9 PHP 7.2.14, Apache 2.4.38 https://alpinelinux.org/posts/Alpine-3.9.0-released.html --- CHANGELOG.md | 3 +++ Docker/Dockerfile | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 685be5a62..5a79e47dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 2019-0X-XX FreshRSS 1.13.2-dev +* Deployment + * Docker image updated to Alpine 3.9 with PHP 7.2.14 and Apache 2.4.38 [#2238](https://github.com/FreshRSS/FreshRSS/pull/2238) + ## 2019-01-26 FreshRSS 1.13.1 diff --git a/Docker/Dockerfile b/Docker/Dockerfile index a4be9fd84..cd0f521a0 100644 --- a/Docker/Dockerfile +++ b/Docker/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.8 +FROM alpine:3.9 ENV TZ UTC -- cgit v1.2.3 From 85a95aa0ddd438c4e12e56865093f00354147f69 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 3 Feb 2019 12:47:39 +0100 Subject: Changelog 2233 2234 https://github.com/FreshRSS/FreshRSS/issues/2233 https://github.com/FreshRSS/FreshRSS/pull/2235 https://github.com/FreshRSS/FreshRSS/pull/2234 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a79e47dc..9f9a10d70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## 2019-0X-XX FreshRSS 1.13.2-dev +* Bug fixing + * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) +* UI + * Batch scroll-as-read for better client-side and server-side performance [#2199](https://github.com/FreshRSS/FreshRSS/pull/2199) + * Rewrite some jQuery code as native JavaScript [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) * Deployment * Docker image updated to Alpine 3.9 with PHP 7.2.14 and Apache 2.4.38 [#2238](https://github.com/FreshRSS/FreshRSS/pull/2238) -- cgit v1.2.3 From 9cc72c0c4860c96d9d82310e4bb76a9233fd2961 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 3 Feb 2019 21:24:06 +0100 Subject: Fix EntryDAO tags warning for Fever API https://github.com/FreshRSS/FreshRSS/issues/2239 --- app/Models/EntryDAO.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 21f17c097..93d1183c9 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -1065,7 +1065,7 @@ SQL; $dao['date'], $dao['is_read'], $dao['is_favorite'], - $dao['tags'] + isset($dao['tags']) ? $dao['tags'] : '' ); if (isset($dao['id'])) { $entry->_id($dao['id']); -- cgit v1.2.3 From e4224eee2ee8ebc96db34fb70ac225880911477d Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 3 Feb 2019 21:34:44 +0100 Subject: Changelog 2239 https://github.com/FreshRSS/FreshRSS/issues/2239 https://github.com/FreshRSS/FreshRSS/pull/2240 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f9a10d70..db1873ab0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Bug fixing * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) + * Fix breaking warning in Fever API [#2239](https://github.com/FreshRSS/FreshRSS/issues/2239) * UI * Batch scroll-as-read for better client-side and server-side performance [#2199](https://github.com/FreshRSS/FreshRSS/pull/2199) * Rewrite some jQuery code as native JavaScript [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) -- cgit v1.2.3 From ce62ce0ebd562781307d137141e38338882f89ab Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 5 Feb 2019 09:30:18 +0100 Subject: Fever API encoding of special chars https://github.com/FreshRSS/FreshRSS/issues/2241 --- p/api/fever.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/p/api/fever.php b/p/api/fever.php index dd54a372b..d315523c4 100644 --- a/p/api/fever.php +++ b/p/api/fever.php @@ -324,9 +324,9 @@ class FeverAPI $feeds[] = array( 'id' => $feed->id(), 'favicon_id' => $feed->id(), - 'title' => $feed->name(), - 'url' => $feed->url(), - 'site_url' => $feed->website(), + 'title' => escapeToUnicodeAlternative($feed->name(), true), + 'url' => htmlspecialchars_decode($feed->url(), ENT_QUOTES), + 'site_url' => htmlspecialchars_decode($feed->website(), ENT_QUOTES), 'is_spark' => 0, // unsupported 'last_updated_on_time' => $feed->lastUpdate(), ); @@ -349,7 +349,7 @@ class FeverAPI foreach ($categories as $category) { $groups[] = array( 'id' => $category->id(), - 'title' => $category->name(), + 'title' => escapeToUnicodeAlternative($category->name(), false), ); } @@ -535,10 +535,10 @@ class FeverAPI $items[] = array( 'id' => $entry->id(), 'feed_id' => $entry->feed(false), - 'title' => $entry->title(), - 'author' => $entry->authors(true), + 'title' => escapeToUnicodeAlternative($entry->title(), true), + 'author' => escapeToUnicodeAlternative($entry->authors(true), true), 'html' => $entry->content(), - 'url' => $entry->link(), + 'url' => htmlspecialchars_decode($entry->link(), ENT_QUOTES), 'is_saved' => $entry->isFavorite() ? 1 : 0, 'is_read' => $entry->isRead() ? 1 : 0, 'created_on_time' => $entry->date(true), -- cgit v1.2.3 From 69eb651d56e7fa9bf742f60366cdb10f769246e3 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 5 Feb 2019 09:36:39 +0100 Subject: Minor Unicode changes --- p/api/fever.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/p/api/fever.php b/p/api/fever.php index d315523c4..30f9651a3 100644 --- a/p/api/fever.php +++ b/p/api/fever.php @@ -349,7 +349,7 @@ class FeverAPI foreach ($categories as $category) { $groups[] = array( 'id' => $category->id(), - 'title' => escapeToUnicodeAlternative($category->name(), false), + 'title' => escapeToUnicodeAlternative($category->name(), true), ); } @@ -535,8 +535,8 @@ class FeverAPI $items[] = array( 'id' => $entry->id(), 'feed_id' => $entry->feed(false), - 'title' => escapeToUnicodeAlternative($entry->title(), true), - 'author' => escapeToUnicodeAlternative($entry->authors(true), true), + 'title' => escapeToUnicodeAlternative($entry->title(), false), + 'author' => escapeToUnicodeAlternative($entry->authors(true), false), 'html' => $entry->content(), 'url' => htmlspecialchars_decode($entry->link(), ENT_QUOTES), 'is_saved' => $entry->isFavorite() ? 1 : 0, -- cgit v1.2.3 From 3b3accf6ce5d29449ee4d556b6277d92a1830680 Mon Sep 17 00:00:00 2001 From: Seokseong Jeon <6747391+gsongsong@users.noreply.github.com> Date: Tue, 5 Feb 2019 23:05:40 +0900 Subject: i18n Korean (#2242) --- app/i18n/kr/admin.php | 8 ++++---- app/i18n/kr/conf.php | 6 +++--- app/i18n/kr/feedback.php | 4 ++-- app/i18n/kr/gen.php | 12 ++++++------ app/i18n/kr/index.php | 6 +++--- app/i18n/kr/install.php | 4 ++-- app/i18n/kr/sub.php | 10 +++++----- cli/i18n/ignore/kr.php | 16 ++++++++++++++++ 8 files changed, 41 insertions(+), 25 deletions(-) diff --git a/app/i18n/kr/admin.php b/app/i18n/kr/admin.php index 532fe30a5..6312bd3fe 100644 --- a/app/i18n/kr/admin.php +++ b/app/i18n/kr/admin.php @@ -67,8 +67,8 @@ return array( 'ok' => 'JSON 확장 기능이 설치되어 있습니다.', ), 'mbstring' => array( - 'nok' => 'Cannot find the recommended library mbstring for Unicode.', //TODO - Translation - 'ok' => 'You have the recommended library mbstring for Unicode.', //TODO - Translation + 'nok' => '유니코드 지원을 위한 mbstring 라이브러리를 찾을 수 없습니다.', + 'ok' => '유니코드 지원을 위한 mbstring 라이브러리가 설치되어 있습니다.', ), 'minz' => array( 'nok' => 'Minz 프레임워크를 찾을 수 없습니다.', @@ -163,8 +163,8 @@ return array( 'max-categories' => '사용자별 카테고리 개수 제한', 'max-feeds' => '사용자별 피드 개수 제한', 'cookie-duration' => array( - 'help' => 'in seconds', // @todo translate - 'number' => 'Duration to keep logged in', // @todo translate + 'help' => '초', + 'number' => '로그인 유지 시간', ), 'registration' => array( 'help' => '0: 제한 없음', diff --git a/app/i18n/kr/conf.php b/app/i18n/kr/conf.php index 5c3d95d17..11a8494c5 100644 --- a/app/i18n/kr/conf.php +++ b/app/i18n/kr/conf.php @@ -162,7 +162,7 @@ return array( 'mark_read' => '읽음으로 표시', 'navigation' => '탐색', 'navigation_help' => '"Shift" 키를 누른 상태에선 탐색 단축키가 피드에 적용됩니다.
    "Alt" 키를 누른 상태에선 탐색 단축키가 카테고리에 적용됩니다.', - 'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.', //TODO - Translation + 'navigation_no_mod_help' => '아래 탐색 단축키에는 "Shift"와 "Alt" 키가 적용되지 않습니다.', 'next_article' => '다음 글 보기', 'normal_view' => '일반 모드로 전환', 'other_action' => '다른 동작', @@ -171,8 +171,8 @@ return array( 'rss_view' => '새 탭에서 RSS 피드 열기', 'see_on_website' => '글이 게재된 웹사이트에서 보기', 'shift_for_all_read' => '+ shift를 누른 상태에선 모두 읽음으로 표시', - 'skip_next_article' => 'Focus next without opening', //TODO - Translation - 'skip_previous_article' => 'Focus previous without opening', //TODO - Translation + 'skip_next_article' => '다음 글로 커서 이동', + 'skip_previous_article' => '이전 글로 커서 이동', 'title' => '단축키', 'user_filter' => '사용자 필터 사용하기', 'user_filter_help' => '사용자 필터가 하나만 설정되어 있다면 해당 필터를 사용하고, 그렇지 않다면 필터를 번호로 선택할 수 있습니다.', diff --git a/app/i18n/kr/feedback.php b/app/i18n/kr/feedback.php index 550904894..0e31536f8 100644 --- a/app/i18n/kr/feedback.php +++ b/app/i18n/kr/feedback.php @@ -57,8 +57,8 @@ return array( 'sub' => array( 'actualize' => '피드를 가져오는 중입니다', 'articles' => array( - 'marked_read' => 'The selected articles have been marked as read.', //TODO - Translation - 'marked_unread' => 'The articles have been marked as unread.', //TODO - Translation + 'marked_read' => '선택된 글들을 읽음으로 표시하였습니다.', + 'marked_unread' => '선택된 글들을 읽지 않음으로 표시하였습니다.', ), 'category' => array( 'created' => '%s 카테고리가 생성되었습니다.', diff --git a/app/i18n/kr/gen.php b/app/i18n/kr/gen.php index 86a50e9c4..f7855c499 100644 --- a/app/i18n/kr/gen.php +++ b/app/i18n/kr/gen.php @@ -152,13 +152,13 @@ return array( 'user_profile' => '프로필', ), 'pagination' => array( - 'first' => 'First', - 'last' => 'Last', + 'first' => '처음으로', + 'last' => '마지막으로', 'load_more' => '글 더 불러오기', 'mark_all_read' => '모두 읽음으로 표시', - 'next' => 'Next', + 'next' => '다음', 'nothing_to_load' => '더 이상 글이 없습니다', - 'previous' => 'Previous', + 'previous' => '이전', ), 'share' => array( 'blogotext' => 'Blogotext', @@ -183,13 +183,13 @@ return array( 'short' => array( 'attention' => '경고!', 'blank_to_disable' => '빈 칸으로 두면 비활성화', - 'by_author' => 'By:', + 'by_author' => '글쓴이:', 'by_default' => '기본값', 'damn' => '이런!', 'default_category' => '분류 없음', 'no' => '아니요', 'not_applicable' => '사용할 수 없음', - 'ok' => 'Ok!', + 'ok' => '좋습니다!', 'or' => '또는', 'yes' => '네', ), diff --git a/app/i18n/kr/index.php b/app/i18n/kr/index.php index 3c63fd664..bebc8bdec 100644 --- a/app/i18n/kr/index.php +++ b/app/i18n/kr/index.php @@ -40,7 +40,7 @@ return array( 'mark_all_read' => '모두 읽음으로 표시', 'mark_cat_read' => '카테고리를 읽음으로 표시', 'mark_feed_read' => '피드를 읽음으로 표시', - 'mark_selection_unread' => 'Mark selection as unread', //TODO - Translation + 'mark_selection_unread' => '선택된 글을 읽지 않음으로 표시', 'newer_first' => '최근 글 먼저', 'non-starred' => '즐겨찾기를 제외하고 표시', 'normal_view' => '일반 모드', @@ -53,11 +53,11 @@ return array( 'starred' => '즐겨찾기만 표시', 'stats' => '통계', 'subscription' => '구독 관리', - 'tags' => 'My labels', //TODO - Translation + 'tags' => '내 라벨', 'unread' => '읽지 않은 글만 표시', ), 'share' => '공유', 'tag' => array( - 'related' => '관련 태그', //TODO - Translation + 'related' => '관련 태그', ), ); diff --git a/app/i18n/kr/install.php b/app/i18n/kr/install.php index 6b60f6ffd..65e8726e1 100644 --- a/app/i18n/kr/install.php +++ b/app/i18n/kr/install.php @@ -69,8 +69,8 @@ return array( 'ok' => 'JSON 확장 기능이 설치되어 있습니다.', ), 'mbstring' => array( - 'nok' => 'Cannot find the recommended library mbstring for Unicode.', //TODO - Translation - 'ok' => 'You have the recommended library mbstring for Unicode.', //TODO - Translation + 'nok' => '유니코드 지원을 위한 mbstring 라이브러리를 찾을 수 없습니다.', + 'ok' => '유니코드 지원을 위한 mbstring 라이브러리가 설치되어 있습니다.', ), 'minz' => array( 'nok' => 'Minz 프레임워크를 찾을 수 없습니다.', diff --git a/app/i18n/kr/sub.php b/app/i18n/kr/sub.php index 9f8967053..9edd85818 100644 --- a/app/i18n/kr/sub.php +++ b/app/i18n/kr/sub.php @@ -27,7 +27,7 @@ return array( 'password' => 'HTTP 암호', 'username' => 'HTTP 사용자 이름', ), - 'clear_cache' => 'Always clear cache', //TODO - Translation + 'clear_cache' => '항상 캐시 지우기', 'css_help' => '글의 일부가 포함된 RSS 피드를 가져옵니다 (주의, 시간이 좀 더 걸립니다!)', 'css_path' => '웹사이트 상의 글 본문에 해당하는 CSS 경로', 'description' => '설명', @@ -47,11 +47,11 @@ return array( ), 'websub' => 'WebSub을 사용한 즉시 알림', 'show' => array( - 'all' => 'Show all feeds', //TODO - Translation - 'error' => 'Show only feeds with error', //TODO - Translation + 'all' => '모든 피드 보기', + 'error' => '오류가 발생한 피드만 보기', ), 'showing' => array( - 'error' => 'Showing only feeds with error', //TODO - Translation + 'error' => '오류가 발생한 피드만 보여주고 있습니다', ), 'ssl_verify' => 'SSL 유효성 검사', 'stats' => '통계', @@ -72,7 +72,7 @@ return array( 'export' => '내보내기', 'export_opml' => '피드 목록 내보내기 (OPML)', 'export_starred' => '즐겨찾기 내보내기', - 'export_labelled' => 'Export your labelled articles', //TODO + 'export_labelled' => '라벨이 표시된 글들 내보내기', 'feed_list' => '%s 개의 글 목록', 'file_to_import' => '불러올 파일
    (OPML, JSON 또는 ZIP)', 'file_to_import_no_zip' => '불러올 파일
    (OPML 또는 JSON)', diff --git a/cli/i18n/ignore/kr.php b/cli/i18n/ignore/kr.php index 24cfbc86a..bbccb2d7d 100644 --- a/cli/i18n/ignore/kr.php +++ b/cli/i18n/ignore/kr.php @@ -8,6 +8,18 @@ return array( 'conf.sharing.shaarli', 'conf.sharing.twitter', 'conf.sharing.wallabag', + 'gen.date.Apr', + 'gen.date.Aug', + 'gen.date.Dec', + 'gen.date.Feb', + 'gen.date.Jan', + 'gen.date.Jul', + 'gen.date.Jun', + 'gen.date.Mar', + 'gen.date.May', + 'gen.date.Nov', + 'gen.date.Oct', + 'gen.date.Sep', 'gen.lang.cz', 'gen.lang.de', 'gen.lang.en', @@ -17,6 +29,7 @@ return array( 'gen.lang.it', 'gen.lang.kr', 'gen.lang.nl', + 'gen.lang.oc', 'gen.lang.pt-br', 'gen.lang.ru', 'gen.lang.tr', @@ -29,8 +42,11 @@ return array( 'gen.share.g+', 'gen.share.gnusocial', 'gen.share.jdh', + 'gen.share.linkedin', 'gen.share.mastodon', 'gen.share.movim', + 'gen.share.pinboard', + 'gen.share.pocket', 'gen.share.shaarli', 'gen.share.twitter', 'gen.share.wallabag', -- cgit v1.2.3 From 086fa0d49a5e1506fda4dda42c5c69fd3a624ecf Mon Sep 17 00:00:00 2001 From: Thomas Guesnon Date: Wed, 13 Feb 2019 11:37:37 +0100 Subject: Two themes (#2245) * Two new themes * update gitignore * dirs cleaning + mobile ui improvements * name added to credits file * New line --- .gitignore | 2 + CREDITS.md | 1 + p/themes/Ansum/_components.scss | 352 ++++++++ p/themes/Ansum/_configuration.scss | 90 ++ p/themes/Ansum/_divers.scss | 12 + p/themes/Ansum/_fonts.scss | 56 ++ p/themes/Ansum/_forms.scss | 153 ++++ p/themes/Ansum/_global-view.scss | 80 ++ p/themes/Ansum/_layout.scss | 462 ++++++++++ p/themes/Ansum/_list-view.scss | 92 ++ p/themes/Ansum/_logs.scss | 34 + p/themes/Ansum/_mixins.scss | 57 ++ p/themes/Ansum/_mobile.scss | 170 ++++ p/themes/Ansum/_reader-view.scss | 13 + p/themes/Ansum/_sidebar.scss | 299 +++++++ p/themes/Ansum/_stats.scss | 27 + p/themes/Ansum/_tables.scss | 17 + p/themes/Ansum/_variables.scss | 53 ++ p/themes/Ansum/ansum.css | 1299 +++++++++++++++++++++++++++ p/themes/Ansum/ansum.css.map | 7 + p/themes/Ansum/ansum.scss | 51 ++ p/themes/Ansum/icons/cog-white.svg | 5 + p/themes/Ansum/icons/cog.svg | 59 ++ p/themes/Ansum/icons/down-white.svg | 59 ++ p/themes/Ansum/icons/down.svg | 59 ++ p/themes/Ansum/icons/icon.svg | 75 ++ p/themes/Ansum/icons/link-white.svg | 59 ++ p/themes/Ansum/icons/link.svg | 5 + p/themes/Ansum/icons/magnifier.svg | 5 + p/themes/Ansum/icons/more.svg | 59 ++ p/themes/Ansum/icons/non-starred-white.svg | 61 ++ p/themes/Ansum/icons/non-starred.svg | 60 ++ p/themes/Ansum/icons/read-grey.svg | 5 + p/themes/Ansum/icons/read-white.svg | 59 ++ p/themes/Ansum/icons/read.svg | 59 ++ p/themes/Ansum/icons/refresh.svg | 59 ++ p/themes/Ansum/icons/rss-white.svg | 60 ++ p/themes/Ansum/icons/rss.svg | 60 ++ p/themes/Ansum/icons/starred-white.svg | 59 ++ p/themes/Ansum/icons/starred.svg | 5 + p/themes/Ansum/icons/tick-color.svg | 57 ++ p/themes/Ansum/icons/tick-white.svg | 5 + p/themes/Ansum/icons/tick.svg | 5 + p/themes/Ansum/icons/unread-grey.svg | 59 ++ p/themes/Ansum/icons/unread-white.svg | 5 + p/themes/Ansum/icons/unread.svg | 59 ++ p/themes/Ansum/icons/up-white.svg | 59 ++ p/themes/Ansum/icons/up.svg | 59 ++ p/themes/Ansum/icons/view-global-white.svg | 5 + p/themes/Ansum/icons/view-global.svg | 59 ++ p/themes/Ansum/icons/view-list-white.svg | 5 + p/themes/Ansum/icons/view-list.svg | 60 ++ p/themes/Ansum/icons/view-reader-white.svg | 59 ++ p/themes/Ansum/icons/view-reader.svg | 59 ++ p/themes/Ansum/loader.gif | Bin 0 -> 4251 bytes p/themes/Ansum/metadata.json | 7 + p/themes/Ansum/sass.sh | 1 + p/themes/Ansum/thumbs/original.png | Bin 0 -> 182930 bytes p/themes/Mapco/_components.scss | 352 ++++++++ p/themes/Mapco/_configuration.scss | 90 ++ p/themes/Mapco/_divers.scss | 12 + p/themes/Mapco/_fonts.scss | 56 ++ p/themes/Mapco/_forms.scss | 153 ++++ p/themes/Mapco/_global-view.scss | 80 ++ p/themes/Mapco/_layout.scss | 462 ++++++++++ p/themes/Mapco/_list-view.scss | 92 ++ p/themes/Mapco/_logs.scss | 34 + p/themes/Mapco/_mixins.scss | 59 ++ p/themes/Mapco/_mobile.scss | 169 ++++ p/themes/Mapco/_reader-view.scss | 13 + p/themes/Mapco/_sidebar.scss | 291 +++++++ p/themes/Mapco/_stats.scss | 27 + p/themes/Mapco/_tables.scss | 17 + p/themes/Mapco/_variables.scss | 53 ++ p/themes/Mapco/icons/cog-white.svg | 5 + p/themes/Mapco/icons/cog.svg | 59 ++ p/themes/Mapco/icons/down-white.svg | 59 ++ p/themes/Mapco/icons/down.svg | 59 ++ p/themes/Mapco/icons/icon.svg | 9 + p/themes/Mapco/icons/link-white.svg | 59 ++ p/themes/Mapco/icons/link.svg | 5 + p/themes/Mapco/icons/magnifier.svg | 5 + p/themes/Mapco/icons/more.svg | 59 ++ p/themes/Mapco/icons/non-starred-white.svg | 61 ++ p/themes/Mapco/icons/non-starred.svg | 60 ++ p/themes/Mapco/icons/read-grey.svg | 5 + p/themes/Mapco/icons/read-white.svg | 59 ++ p/themes/Mapco/icons/read.svg | 59 ++ p/themes/Mapco/icons/refresh.svg | 59 ++ p/themes/Mapco/icons/rss-white.svg | 60 ++ p/themes/Mapco/icons/rss.svg | 60 ++ p/themes/Mapco/icons/starred-white.svg | 59 ++ p/themes/Mapco/icons/starred.svg | 5 + p/themes/Mapco/icons/tick-color.svg | 5 + p/themes/Mapco/icons/tick-white.svg | 5 + p/themes/Mapco/icons/tick.svg | 5 + p/themes/Mapco/icons/unread-grey.svg | 59 ++ p/themes/Mapco/icons/unread-white.svg | 5 + p/themes/Mapco/icons/unread.svg | 59 ++ p/themes/Mapco/icons/up-white.svg | 59 ++ p/themes/Mapco/icons/up.svg | 59 ++ p/themes/Mapco/icons/view-global-white.svg | 5 + p/themes/Mapco/icons/view-global.svg | 59 ++ p/themes/Mapco/icons/view-list-white.svg | 5 + p/themes/Mapco/icons/view-list.svg | 60 ++ p/themes/Mapco/icons/view-reader-white.svg | 59 ++ p/themes/Mapco/icons/view-reader.svg | 59 ++ p/themes/Mapco/loader.gif | Bin 0 -> 4251 bytes p/themes/Mapco/mapco.css | 1306 ++++++++++++++++++++++++++++ p/themes/Mapco/mapco.css.map | 7 + p/themes/Mapco/mapco.scss | 51 ++ p/themes/Mapco/metadata.json | 7 + p/themes/Mapco/sass.sh | 1 + p/themes/Mapco/thumbs/original.png | Bin 0 -> 171346 bytes p/themes/fonts/LatoLatin-Bold.woff | Bin 0 -> 72376 bytes p/themes/fonts/LatoLatin-BoldItalic.woff | Bin 0 -> 73700 bytes p/themes/fonts/LatoLatin-Italic.woff | Bin 0 -> 74708 bytes p/themes/fonts/LatoLatin-Regular.woff | Bin 0 -> 72456 bytes p/themes/fonts/Spectral-Bold.woff | Bin 0 -> 80168 bytes p/themes/fonts/Spectral-BoldItalic.woff | Bin 0 -> 81240 bytes p/themes/fonts/Spectral-Italic.woff | Bin 0 -> 77436 bytes p/themes/fonts/Spectral-Regular.woff | Bin 0 -> 76188 bytes 122 files changed, 9403 insertions(+) create mode 100644 p/themes/Ansum/_components.scss create mode 100644 p/themes/Ansum/_configuration.scss create mode 100644 p/themes/Ansum/_divers.scss create mode 100644 p/themes/Ansum/_fonts.scss create mode 100644 p/themes/Ansum/_forms.scss create mode 100644 p/themes/Ansum/_global-view.scss create mode 100644 p/themes/Ansum/_layout.scss create mode 100644 p/themes/Ansum/_list-view.scss create mode 100644 p/themes/Ansum/_logs.scss create mode 100644 p/themes/Ansum/_mixins.scss create mode 100644 p/themes/Ansum/_mobile.scss create mode 100644 p/themes/Ansum/_reader-view.scss create mode 100644 p/themes/Ansum/_sidebar.scss create mode 100644 p/themes/Ansum/_stats.scss create mode 100644 p/themes/Ansum/_tables.scss create mode 100644 p/themes/Ansum/_variables.scss create mode 100644 p/themes/Ansum/ansum.css create mode 100644 p/themes/Ansum/ansum.css.map create mode 100644 p/themes/Ansum/ansum.scss create mode 100644 p/themes/Ansum/icons/cog-white.svg create mode 100644 p/themes/Ansum/icons/cog.svg create mode 100644 p/themes/Ansum/icons/down-white.svg create mode 100644 p/themes/Ansum/icons/down.svg create mode 100644 p/themes/Ansum/icons/icon.svg create mode 100644 p/themes/Ansum/icons/link-white.svg create mode 100644 p/themes/Ansum/icons/link.svg create mode 100644 p/themes/Ansum/icons/magnifier.svg create mode 100644 p/themes/Ansum/icons/more.svg create mode 100644 p/themes/Ansum/icons/non-starred-white.svg create mode 100644 p/themes/Ansum/icons/non-starred.svg create mode 100644 p/themes/Ansum/icons/read-grey.svg create mode 100644 p/themes/Ansum/icons/read-white.svg create mode 100644 p/themes/Ansum/icons/read.svg create mode 100644 p/themes/Ansum/icons/refresh.svg create mode 100644 p/themes/Ansum/icons/rss-white.svg create mode 100644 p/themes/Ansum/icons/rss.svg create mode 100644 p/themes/Ansum/icons/starred-white.svg create mode 100644 p/themes/Ansum/icons/starred.svg create mode 100644 p/themes/Ansum/icons/tick-color.svg create mode 100644 p/themes/Ansum/icons/tick-white.svg create mode 100644 p/themes/Ansum/icons/tick.svg create mode 100644 p/themes/Ansum/icons/unread-grey.svg create mode 100644 p/themes/Ansum/icons/unread-white.svg create mode 100644 p/themes/Ansum/icons/unread.svg create mode 100644 p/themes/Ansum/icons/up-white.svg create mode 100644 p/themes/Ansum/icons/up.svg create mode 100644 p/themes/Ansum/icons/view-global-white.svg create mode 100644 p/themes/Ansum/icons/view-global.svg create mode 100644 p/themes/Ansum/icons/view-list-white.svg create mode 100644 p/themes/Ansum/icons/view-list.svg create mode 100644 p/themes/Ansum/icons/view-reader-white.svg create mode 100644 p/themes/Ansum/icons/view-reader.svg create mode 100644 p/themes/Ansum/loader.gif create mode 100644 p/themes/Ansum/metadata.json create mode 100644 p/themes/Ansum/sass.sh create mode 100644 p/themes/Ansum/thumbs/original.png create mode 100644 p/themes/Mapco/_components.scss create mode 100644 p/themes/Mapco/_configuration.scss create mode 100644 p/themes/Mapco/_divers.scss create mode 100644 p/themes/Mapco/_fonts.scss create mode 100644 p/themes/Mapco/_forms.scss create mode 100644 p/themes/Mapco/_global-view.scss create mode 100644 p/themes/Mapco/_layout.scss create mode 100644 p/themes/Mapco/_list-view.scss create mode 100644 p/themes/Mapco/_logs.scss create mode 100644 p/themes/Mapco/_mixins.scss create mode 100644 p/themes/Mapco/_mobile.scss create mode 100644 p/themes/Mapco/_reader-view.scss create mode 100644 p/themes/Mapco/_sidebar.scss create mode 100644 p/themes/Mapco/_stats.scss create mode 100644 p/themes/Mapco/_tables.scss create mode 100644 p/themes/Mapco/_variables.scss create mode 100644 p/themes/Mapco/icons/cog-white.svg create mode 100644 p/themes/Mapco/icons/cog.svg create mode 100644 p/themes/Mapco/icons/down-white.svg create mode 100644 p/themes/Mapco/icons/down.svg create mode 100644 p/themes/Mapco/icons/icon.svg create mode 100644 p/themes/Mapco/icons/link-white.svg create mode 100644 p/themes/Mapco/icons/link.svg create mode 100644 p/themes/Mapco/icons/magnifier.svg create mode 100644 p/themes/Mapco/icons/more.svg create mode 100644 p/themes/Mapco/icons/non-starred-white.svg create mode 100644 p/themes/Mapco/icons/non-starred.svg create mode 100644 p/themes/Mapco/icons/read-grey.svg create mode 100644 p/themes/Mapco/icons/read-white.svg create mode 100644 p/themes/Mapco/icons/read.svg create mode 100644 p/themes/Mapco/icons/refresh.svg create mode 100644 p/themes/Mapco/icons/rss-white.svg create mode 100644 p/themes/Mapco/icons/rss.svg create mode 100644 p/themes/Mapco/icons/starred-white.svg create mode 100644 p/themes/Mapco/icons/starred.svg create mode 100644 p/themes/Mapco/icons/tick-color.svg create mode 100644 p/themes/Mapco/icons/tick-white.svg create mode 100644 p/themes/Mapco/icons/tick.svg create mode 100644 p/themes/Mapco/icons/unread-grey.svg create mode 100644 p/themes/Mapco/icons/unread-white.svg create mode 100644 p/themes/Mapco/icons/unread.svg create mode 100644 p/themes/Mapco/icons/up-white.svg create mode 100644 p/themes/Mapco/icons/up.svg create mode 100644 p/themes/Mapco/icons/view-global-white.svg create mode 100644 p/themes/Mapco/icons/view-global.svg create mode 100644 p/themes/Mapco/icons/view-list-white.svg create mode 100644 p/themes/Mapco/icons/view-list.svg create mode 100644 p/themes/Mapco/icons/view-reader-white.svg create mode 100644 p/themes/Mapco/icons/view-reader.svg create mode 100644 p/themes/Mapco/loader.gif create mode 100644 p/themes/Mapco/mapco.css create mode 100644 p/themes/Mapco/mapco.css.map create mode 100644 p/themes/Mapco/mapco.scss create mode 100644 p/themes/Mapco/metadata.json create mode 100644 p/themes/Mapco/sass.sh create mode 100644 p/themes/Mapco/thumbs/original.png create mode 100644 p/themes/fonts/LatoLatin-Bold.woff create mode 100644 p/themes/fonts/LatoLatin-BoldItalic.woff create mode 100644 p/themes/fonts/LatoLatin-Italic.woff create mode 100644 p/themes/fonts/LatoLatin-Regular.woff create mode 100644 p/themes/fonts/Spectral-Bold.woff create mode 100644 p/themes/fonts/Spectral-BoldItalic.woff create mode 100644 p/themes/fonts/Spectral-Italic.woff create mode 100644 p/themes/fonts/Spectral-Regular.woff diff --git a/.gitignore b/.gitignore index 8230b746c..62b1bcbdf 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ constants.local.php *.save *.autosav *.autosave +*.sass-cache +sass.sh diff --git a/CREDITS.md b/CREDITS.md index 83bb97a25..ff3f64127 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -64,6 +64,7 @@ People are sorted by name so please keep this order. * [Thomas Citharel](https://github.com/tcitworld): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:tomgue), [Web](https://www.tcit.fr/) * [thomas-gt](https://github.com/thomas-gt): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:thomas-gt) * [tomgue](https://github.com/tomgue): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=tomgue) +* [Thomas Guesnon](https://github.com/patjennings): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:patjennings), [Web](http://www.thomasguesnon.fr/) * [Twilek-de](https://github.com/Twilek-de): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:Twilek-de) * [Uncovery](https://github.com/uncovery): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:uncovery) * [Wanabo](https://github.com/Wanabo): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=Wanabo) diff --git a/p/themes/Ansum/_components.scss b/p/themes/Ansum/_components.scss new file mode 100644 index 000000000..cf8cb5e91 --- /dev/null +++ b/p/themes/Ansum/_components.scss @@ -0,0 +1,352 @@ +/*=== COMPONENTS */ +/*===============*/ +/*=== Forms */ +// parti dans _forms.scss + +/*=== Horizontal-list */ +.horizontal-list { + margin: 0; + padding: 0.1rem 0; + + .item{ + vertical-align: middle; + + &:first-child{ + padding-left: 0.5rem; + } + + } +} + +/*=== Dropdown */ +.dropdown-menu { + background: $grey-lighter; + margin: 0; + font-size: 1rem; + text-align: left; + padding: 0.5rem 0 1rem 0; + border: none; + border-radius: 3px; + + -webkit-box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + -moz-box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + + &::after { + content: ""; + position: absolute; + top: -4px; + right: 13px; + width: 10px; + height: 10px; + z-index: -10; + transform: rotate(45deg); + -moz-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + background: white; + // border-top: 1px solid #95a5a6; + // border-left: 1px solid #95a5a6; + } + + .dropdown-header { + // padding: 0 5px 5px; + margin: 1.75rem 0 0.5rem 2rem; + font-weight: bold; + text-align: left; + color: $grey-dark; + text-transform: uppercase; + letter-spacing: 1px; + + + } + + .item{ + @include transition(all, 0.075s, ease-in-out); + a, span, .as-link{ + padding: 0 2rem; + line-height: 2.5em; + font-size: 1rem; + color: $main-font-color; + } + &:hover{ + background: $main-first; + color: $white; + + a, button{ + text-decoration: none; + color: $white; + } + } + &[aria-checked="true"]{ + a::before{ + font-weight: bold; + margin: 0 0 0 -14px; + } + } + } + .input{ + select, input{ + margin: 0 auto 5px; + padding: 2px 5px; + border-radius: 3px; + } + } + .separator { + margin: 0.75rem 0; + border-bottom: 1px solid $grey-light; + // display: none; + } + +} +.tree .tree-folder .tree-folder-items .dropdown-menu, +.tree .tree-folder .tree-folder-items .dropdown-menu{ + // tout ça sert à restaurer l'apparence du dropdown dans un contexte de sidebar sombre + + .item{ + padding: 0; + + a, + button{ + color: $main-font-color; + + &:hover{ + color: $white; + } + } + &:hover{ + background: $main-first; + } + } +} + + + + +/*=== Alerts */ +.alert { + margin: 1rem 0; + // width: 100%; + padding: 1rem; + font-size: 1rem; + background: $grey-lighter; + border: 1px solid $grey-medium; + border-radius: 3px; + color: $grey-dark; + text-shadow: 0 0 1px $grey-light; +} +.alert-head { + font-size: 1.15em; +} +.alert > a { + text-decoration: underline; + color: inherit; +} +.alert-warn { + background: $warning-light; + border: 1px solid unquote($warning-text+'33'); // on ajoute l'opacité à la fin + color: $warning-text; +} +.alert-success { + background: $success-light; + border: 1px solid unquote($success-text+'33'); + color: $success-text; +} +.alert-error { + background: $alert-light; + border: 1px solid unquote($alert-text+'33'); + color: $alert-text; +} + +/*=== Pagination */ +.pagination { + text-align: center; + font-size: 0.8em; + background: $grey-light; + color: $main-font-color; + + .item{ + &.pager-current { + font-weight: bold; + font-size: 1.5em; + background: $sid-bg; + color: $grey-light; + } + a { + display: block; + font-style: italic; + line-height: 3em; + text-decoration: none; + color: $main-font-color; + + &:hover{ + background: $main-font-color; + color: $grey-light; + } + } + } + + .loading, + a:hover.loading { + font-size: 0; + background: url("loader.gif") center center no-repeat #34495e; + } +} +.content .pagination { + margin: 0; + padding: 0; +} + + +/*=== Boxes */ +.box { + // border: 1px solid #ddd; + border: none; + border-radius: 3px; + background: $white; + + -webkit-box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.25); + -moz-box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.25); + box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.25); + + .box-title { + margin: 0; + padding: 5px 10px; + background: $grey-light; + color: $main-font-color; + // border-bottom: 1px solid #ddd; + border-radius: 2px 2px 0 0; + + form{ + input{ + width: 85%; + } + .dropdown{ + float: right; + a.dropdown-toggle{ + padding: 0; + background-image: url(icons/more.svg); + background-repeat: no-repeat; + background-position: right 8px; + // float: right; + border-radius: 0; + img{ + display: none; + } + } + } + } + } + .box-content { + // max-height: 260px; + + .item { + padding: 0.5rem 0.75rem; + font-size: 1rem; + color: $main-font-color; + line-height: 1.7em; + border-bottom: 1px solid $grey-light; + + img{ + margin-right: 0.75rem; + } + + .configure { + visibility: hidden; + width: 1.75rem; + height: 1.75rem; + display: block; + border-radius: 2px; + float: left; + margin-right: 0.5rem; + background: url("icons/cog.svg") no-repeat 4px 4px; + + .icon { + vertical-align: middle; + border-radius: 3px; + display: none; + } + &:hover{ + // background: $main-first; + background: url("icons/cog-white.svg") no-repeat 4px 4px $main-first; + } + } + &:hover .configure { + visibility: visible; + } + } + .item:last-child{ + border-bottom: none; + } + } +} + +/*=== "Load more" part */ +#bigMarkAsRead { + text-align: center; + text-decoration: none; + background: $main-first-light; + color: $main-first; + + @include transition(all, 0.15s, ease-in-out); + + &:hover { + background: $main-first; + color: #fff; + + .bigTick{ + background: url(icons/tick-white.svg) center no-repeat; + } + } + .bigTick{ + margin: 0.5rem 0; + display: inline-block; + text-indent: -9999px; + background: url(icons/tick-color.svg) center no-repeat; + height: 64px; + width: 64px; + white-space: nowrap; + } +} + +// page de login +.formLogin{ + background: $sid-bg; + + .header{ + .configure{ + padding-right: 1rem; + img{ + margin-right: 0.5rem; + } + + a.signin{ + color: $white; + } + } + } + + h1{ + color: $white; + } + form#crypto-form{ + div{ + margin-bottom: 1rem; + + label{ + font-size: 1rem; + color: $grey-medium; + + + } + input{ + background: $main-first-darker; + + &:focus{ + background: $grey-lighter; + color: $main-font-color; + } + } + } + } +} diff --git a/p/themes/Ansum/_configuration.scss b/p/themes/Ansum/_configuration.scss new file mode 100644 index 000000000..c3c6fd417 --- /dev/null +++ b/p/themes/Ansum/_configuration.scss @@ -0,0 +1,90 @@ +/*=== Configuration pages */ +.post { + padding: 1rem 2rem; + font-size: 1rem; + + form { + margin: 1rem 0; + + // Gestion des extensions + .horizontal-list{ + margin-bottom: 0.5rem; + + .item{ + .stick{ + // width: 65%; + // margin-right: 1rem; + // display:flex; + + } + .btn{ + // width: 8rem; + // flex-grow: 1; + } + } + + } + } + &.content { + max-width: 550px; + } + + h1, h2{ // pages titles + font-size: 3rem; + margin-top: 1.75rem; + font-weight: 300; + line-height: 1.2em; + // font-family: "spectral"; + color: $main-font-color; + } + + a[href="./"]{ // C'est le bouton "Retour à vos flux" + display: inline-block; + // min-height: 38px; + min-width: 15px; + line-height: 25px; + margin: 0; + padding: 0.75rem 1.5rem; + font-size: 1rem; + vertical-align: middle; + cursor: pointer; + overflow: hidden; + background: $grey-lighter; + border: 1px solid $grey-medium-light; + border-radius: 5px; + // border: none; + color: $grey-dark; + + &:hover{ + text-decoration: none; + background: $main-first; + color: white; + border: 1px solid $main-first; + } + } + +} + + + +#slider{ + border-left: none; + + -webkit-box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + -moz-box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); +} + +.slide-container{ + .properties{ + background: rgba(0, 0, 0, 0.75); + border: 0; + padding: 1rem; + color: white; + + .page-number{ + right: 1rem; + top: 1rem; + } + } +} diff --git a/p/themes/Ansum/_divers.scss b/p/themes/Ansum/_divers.scss new file mode 100644 index 000000000..7d122f1b4 --- /dev/null +++ b/p/themes/Ansum/_divers.scss @@ -0,0 +1,12 @@ +/*=== DIVERS */ +/*===========*/ +.aside.aside_feed .nav-form input, +.aside.aside_feed .nav-form select { + width: 140px; +} +.aside.aside_feed .nav-form .dropdown .dropdown-menu { + right: -20px; +} +.aside.aside_feed .nav-form .dropdown .dropdown-menu::after { + right: 33px; +} diff --git a/p/themes/Ansum/_fonts.scss b/p/themes/Ansum/_fonts.scss new file mode 100644 index 000000000..5891be834 --- /dev/null +++ b/p/themes/Ansum/_fonts.scss @@ -0,0 +1,56 @@ +@font-face { + font-family: "lato"; + font-style: normal; + font-stretch: normal; + font-weight: 400; + src: local("Lato"), url("../fonts/LatoLatin-Regular.woff") format("woff"); +} +@font-face { + font-family: "lato"; + font-style: italic; + font-stretch: normal; + font-weight: 400; + src: local("Lato"), url("../fonts/LatoLatin-Italic.woff") format("woff"); +} +@font-face { + font-family: "lato"; + font-style: normal; + font-stretch: normal; + font-weight: 700; + src: local("Lato"), url("../fonts/LatoLatin-Bold.woff") format("woff"); +} +@font-face { + font-family: "lato"; + font-style: italic; + font-stretch: normal; + font-weight: 700; + src: local("Lato"), url("../fonts/LatoLatin-BoldItalic.woff") format("woff"); +} +@font-face { + font-family: "spectral"; + font-style: normal; + font-stretch: normal; + font-weight: 400; + src: local("Spectral"), url("../fonts/Spectral-Regular.woff") format("woff"); +} +@font-face { + font-family: "spectral"; + font-style: italic; + font-stretch: normal; + font-weight: 400; + src: local("Spectral"), url("../fonts/Spectral-Italic.woff") format("woff"); +} +@font-face { + font-family: "spectral"; + font-style: normal; + font-stretch: normal; + font-weight: 700; + src: local("Spectral"), url("../fonts/Spectral-Bold.woff") format("woff"); +} +@font-face { + font-family: "spectral"; + font-style: italic; + font-stretch: normal; + font-weight: 700; + src: local("Spectral"), url("../fonts/Spectral-BoldItalic.woff") format("woff"); +} diff --git a/p/themes/Ansum/_forms.scss b/p/themes/Ansum/_forms.scss new file mode 100644 index 000000000..8a388aa8a --- /dev/null +++ b/p/themes/Ansum/_forms.scss @@ -0,0 +1,153 @@ +/* btns */ + +.btn { + display: inline-block; + min-height: 38px; + min-width: 15px; + line-height: 25px; + margin: 0; + padding: 0.5rem 1.5rem; + font-size: 1rem; + vertical-align: middle; + cursor: pointer; + overflow: hidden; + background: $grey-lighter; + border-radius: 5px; + border: none; + color: $grey-dark; + + @include transition(all, 0.15s, ease-in-out); + + &.btn-important { + background: $main-first; + color: $white; + + // @include transition(all, 0.15s, ease-in-out); + + &:hover, + &:active { + background: $main-first-alt; + } + } + + + &.btn-attention { + background: $alert-bg; + color: #fff; + + &:hover, + &:active { + background: $alert-text; + } + } + + &:hover { + text-decoration: none; + } +} + +a.btn { + min-height: 25px; + line-height: 25px; +} + +/*=== Forms */ +legend { + display: inline-block; + width: auto; + margin: 2rem 0 1rem 0; + padding: 0; + font-size: 1rem; + clear: both; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 700; +} +label { + min-height: 25px; + padding: 5px 0; + cursor: pointer; + color: $grey-dark; +} +textarea { + width: 360px; + height: 100px; +} +input, select, textarea, button { + font-family: "lato", "Helvetica", "Arial", sans-serif; + min-height: 25px; + padding: 5px 10px; + line-height: 25px; + vertical-align: middle; + background: $white; + border: 1px solid $grey-light; + font-size: 1rem; + color: $grey-dark; + border-radius: 2px; +} +option { + padding: 0 .5em; +} +input:focus, select:focus, textarea:focus { + color: $main-font-color; + border-color: $main-first; +} +input:invalid, select:invalid { + color: $alert-bg; + border-color: $alert-bg; + box-shadow: none; +} +input:disabled, select:disabled { + background: $grey-light; +} +input.extend { + transition: width 200ms linear; + -moz-transition: width 200ms linear; + -webkit-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; +} + + +.form-group { + padding: 5px; + border-radius: 3px; + + &::after { + content: ""; + display: block; + clear: both; + } + &:hover { + // background: #fff; + // border: 1px solid #eee; + // border-radius: 3px; + // border: 1px solid #eee; + } + .group-name { + padding: 10px 0; + text-align: right; + } + .group-controls { + min-height: 25px; + padding: 5px 0; + } + .group-controls .control { + line-height: 2.0em; + } + table { + margin: 10px 0 0 220px; + } + + &.form-actions { + margin: 15px 0 25px; + padding: 5px 0; + // background: #333; + } + &.form-actions .btn { + margin: 0 0.5rem 0 0; + } +} + + + diff --git a/p/themes/Ansum/_global-view.scss b/p/themes/Ansum/_global-view.scss new file mode 100644 index 000000000..30979bd6c --- /dev/null +++ b/p/themes/Ansum/_global-view.scss @@ -0,0 +1,80 @@ +/*=== GLOBAL VIEW */ +/*================*/ + +#stream{ + .box.category{ + + &:not([data-unread="0"]) .box-title { + // background: #3498db; + } + &:not([data-unread="0"]) .box-title:active { + // background: #2980b9; + } + &:not([data-unread="0"]) .box-title .title { + font-weight: bold; + // color: #fff; + } + + .box-title{ + background: none; + padding: 1.5rem; + + a.title{ + font-weight: normal; + text-decoration: none; + text-align: left; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; + color: $grey-dark; + + &:not([data-unread="0"])::after { + position: absolute; + top: 1.75rem; + right: 0; + line-height: 1.5rem; + background: $grey-light; + border-radius: 12px; + padding: 0 0.75rem; + margin: -0.5rem 1rem 0 0; + text-align: center; + } + &:hover{ + color: $main-first; + } + } + } + + .box-content{ + padding-bottom: 0.5rem; + .item.feed { + // padding: 2px 10px; + font-size: 1rem; + padding: 0.5rem 1.5rem; + + a{ + color: $main-font-color; + font-weight: 400; + + &:hover{ + color: $main-first; + text-decoration: none; + } + } + } + } + } +} + + +// le panel qui apparait en overlay pour afficher les flux +#overlay{ + background: rgba(0, 0, 0, 0.65); +} +#panel{ + top: 3rem; + right: 3rem; + bottom: 3rem; + left: 3rem; + border-radius: 3px; +} diff --git a/p/themes/Ansum/_layout.scss b/p/themes/Ansum/_layout.scss new file mode 100644 index 000000000..de684504a --- /dev/null +++ b/p/themes/Ansum/_layout.scss @@ -0,0 +1,462 @@ +/*=== STRUCTURE */ +/*===============*/ +/*=== Header */ +.header { + background: $sid-bg; + padding: 0.5rem 1.35rem; + display: block; + table-layout: none; + width: auto; + + .item{ + vertical-align: middle; + // text-align: center; + // display: flex; + // justify-content: space-between; + // flex-direction: row; + + &.title{ + + font-weight: 400; + width: 280px; + + h1{ + a{ + text-decoration: none; + color: $sid-font-color; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; + + img{ + margin-right: 0.5rem; + + } + } + } + } + &.search{ + // text-align: center; + // width: 50%; + + input{ + width: 230px; + border-radius: 2px 0 0 2px; + background-color: $sid-bg-alt; + color: $sid-font-color; + border: none; + + @include transition(all, 0.15s, ease-in-out); + + &:hover{ + background-color: $sid-bg-dark; + } + + &:focus{ + width: 350px; + + background-color: $white; + color: $grey-dark; + } + } + .btn{ + img{display: none;} + border-radius: 0 2px 2px 0; + + background-color: $main-first; + background-position: center; + background-repeat: no-repeat; + background-image: url(icons/magnifier.svg); + + border-left-width: 0; + + width: 3rem; + min-height: 35px; + + &:hover{ + background-color: $main-first-alt; + } + } + } + &.configure{ + width: 2rem; + position: absolute; + right: 1rem; + top: 1.25rem; + text-align: center; + // float: right; + + .btn{ + img{display: none;} + // border-radius: 0 2px 2px 0; + + background-color: transparent; + background-position: center; + background-repeat: no-repeat; + background-image: url(icons/cog.svg); + + padding: 0 0.5rem; + + // border-left-width: 0; + + // width: 3rem; + + &:hover{ + // background-color: $main-first-alt; + } + } + } + } + + +} + +/*=== Body */ +#global { + height: calc(100% - 85px); +} + + + + +/*=== Prompt (centered) */ +.prompt { + text-align: center; +} +.prompt label { + text-align: left; +} +.prompt form { + margin: 10px auto 20px auto; + width: 200px; +} +.prompt input { + margin: 5px auto; + width: 100%; +} +.prompt p { + margin: 20px 0; +} + +/*=== New article notification */ +#new-article { + text-align: center; + font-size: 1rem; + background: $main-first; +} +#new-article:hover { + background: $main-first-alt; +} +#new-article > a { + line-height: 3em; + font-weight: bold; + color: $white; +} +#new-article > a:hover { + text-decoration: none; +} + +/*=== Day indication */ +.day { + padding: 1rem 0 0 1.25rem; + font-weight: 700; + line-height: 3em; + letter-spacing: 1px; + text-transform: uppercase; + font-size: 0.875rem; + color: $light-font-color; + // border-left: 2px solid #ecf0f1; + + .name{ + padding: 0 1rem 0 1rem; + font-size: 0.875rem; + // font-weight: 700; + color: $main-font-color; + position: relative; + left: 0; + + // letter-spacing: 1px; + text-transform: uppercase; + } +} + +/*=== Index menu */ +.nav_menu { + text-align: center; + padding: 5px 0; + + .btn{ + border-left-width: 0; + padding: 0.5rem 1rem; + background-color: $grey-lighter; + background-position: center; + background-repeat: no-repeat; + + &:hover{ + background-color: $grey-light; + } + } + + .stick{ + background: $grey-lighter; + + .btn{ + border-left-width: 0; + padding: 0.5rem 1rem; + background-color: $grey-lighter; + background-position: center; + background-repeat: no-repeat; + @include transition(all, 0.15s, ease-in-out); + + &:hover{ + background-color: $grey-medium-light; + } + + &.active{ + background-color: $main-first; + } + + img.icon{display: none;} // on efface pour afficher nos icones, mouhahaha !! + + + // actions + &#toggle-read{ + background-image: url(icons/read.svg); + } + &#toggle-read.active{ + background-image: url(icons/read-white.svg); + } + + &#toggle-unread{ + background-image: url(icons/unread.svg); + } + &#toggle-unread.active{ + background-image: url(icons/unread-white.svg); + } + + &#toggle-starred{ + background-image: url(icons/starred.svg); + } + &#toggle-starred.active{ + background-image: url(icons/starred-white.svg); + } + + &#toggle-non-starred{ + background-image: url(icons/non-starred.svg); + } + &#toggle-non-starred.active{ + background-image: url(icons/non-starred-white.svg); + } + + // read all + &.read_all{ + background-color: $grey-lighter; + // min-height: 0; + color:$main-font-color; + padding: 5px 16px; + @include transition(all, 0.15s, ease-in-out); + + &:hover{ + background-color: $grey-medium-light; + } + } + + // views + &.view-normal{ + background-image: url(icons/view-list.svg); + } + &.view-normal.active{ + background-image: url(icons/view-list-white.svg); + } + + &.view-global{ + background-image: url(icons/view-global.svg); + } + &.view-global.active{ + background-image: url(icons/view-global-white.svg); + } + + &.view-reader{ + background-image: url(icons/view-reader.svg); + } + &.view-reader.active{ + background-image: url(icons/view-reader-white.svg); + } + + &.view-rss{ + background-image: url(icons/rss.svg); + } + + } + .dropdown { + a.dropdown-toggle{ + border-left-width: 0; + background-image: url(icons/more.svg); + } + } + + &#nav_menu_action{ + + } + &#nav_menu_read_all{ + + } + &#nav_menu_views{ + + } + } +} + + +#dropdown-query ~ .dropdown-menu .dropdown-header .icon { + vertical-align: middle; + background-color: $grey-medium-dark; + border-radius: 3px; +} + + +/*=== Content of feed articles */ +.content, .content.thin { + padding: 20px 10px; + + font-size: 1.125rem; + line-height: 1.8rem; + + h1.title, h1{ + + a{ + color: $main-font-color; + font-family: "spectral"; + font-size: 2rem; + + &:hover{ + color: $main-first; + text-decoration: none; + } + } + } + .author{ + font-size: 1.125rem; + color: $light-font-color; + } + p, ul{ + font-size: 1.125rem; + line-height: 1.8rem; + } + hr{ + } + .content hr { + margin: 30px 10px; + height: 1px; + background: $grey-medium-light; + border: 0; + box-shadow: 0 2px 5px #ccc; + } + + pre { + margin: 10px auto; + padding: 10px 20px; + overflow: auto; + background: $main-first-darker; + color: $white; + font-size: 0.9rem; + border-radius: 3px; + + code { + background: transparent; + color: $white; + border: none; + } + } + code { + padding: 2px 5px; + color: $grey-light; + background: $grey-lighter; + border: 1px solid $grey-light; + border-radius: 3px; + } + + + blockquote { + display: block; + margin: 0; + padding: 5px 20px; + border-top: 1px solid $grey-medium-light; + border-bottom: 1px solid $grey-medium-light; + background: $grey-lighter; + color: $main-font-color; + + p { + margin: 0; + } + } + +} + + +/*=== Notification and actualize notification */ +.notification { + position: fixed; + top: auto; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 3rem; + + padding: 1rem 0; + text-align: center; + // font-weight: bold; + font-size: 1em; + line-height: 3em; + z-index: 10; + vertical-align: middle; + background: $grey-medium-light; + color: $grey-dark; + // border-radius: 3px; + border: none; + + .msg{ + font-size: 1rem; + display: inline-block; + } + + &.good { + background: $success-bg; + color: $white; + } + &.bad { + background: $alert-bg; + color: $white; + } + a.close { + padding: 0 15px; + line-height: 3em; + border-radius: 0 3px 3px 0; + } + + &.good a.close:hover { + background: $success-text; + } + &.bad a.close:hover { + background: $alert-text; + } + + &#actualizeProgress { + line-height: 2em; + + br{ + display: none; + } + } +} + + +/*=== Navigation menu (for articles) */ +#nav_entries { + margin: 0; + text-align: center; + line-height: 3em; + table-layout: fixed; + background: $sid-bg; +} diff --git a/p/themes/Ansum/_list-view.scss b/p/themes/Ansum/_list-view.scss new file mode 100644 index 000000000..78f100203 --- /dev/null +++ b/p/themes/Ansum/_list-view.scss @@ -0,0 +1,92 @@ +/*=== Feed articles */ +.flux { + // border-left: 2px solid #ecf0f1; + background: $white; + + @include transition(all, 0.15s, ease-in-out); + + &:hover{ + background: $grey-lighter; + + &:not(.current):hover .item.title { + background: $grey-lighter; + + + } + } + &.current{ + border-left-color: $main-first; + background: $white; + } + &.not_read{ + background: $unread-bg; //-------------------- + // border-left-color: #FF5300; + + &:hover{ + background: $unread-bg-light; //-------------------- + } + + &:not(.current):hover .item.title { + background: $unread-bg-light; + + + } + .item.title{ + a{ + color: $unread-font-color; //-------------------- + } + + } + .item.website{ + a{ + color: $unread-font-color; //-------------------- + } + } + .item.date{ + color: unquote($unread-font-color+"99"); //-------------------- + } +} + + &.favorite { + background: $fav-light; + border-left-color: $fav-bg; + + @include transition(all, 0.15s, ease-in-out); + + &:not(.current):hover .item.title { + background: $fav-light; + } + } + + .website{ + a{ + color: $main-font-color; + opacity: 0.75; + } + + .favicon { + padding: 5px; + } + } + .date { + font-size: 0.85rem; + color: $main-font-color; + opacity: 0.75; + } + + .bottom { + font-size: 1rem; + text-align: center; + } +} + +.flux_header { + font-size: 1rem; + cursor: pointer; + border-top: 1px solid $grey-light; + + .title { + font-size: 1rem; + } +} + diff --git a/p/themes/Ansum/_logs.scss b/p/themes/Ansum/_logs.scss new file mode 100644 index 000000000..ae1e24c6c --- /dev/null +++ b/p/themes/Ansum/_logs.scss @@ -0,0 +1,34 @@ +/*=== LOGS */ +/*=========*/ +.loglist { + overflow: hidden; + border: 1px solid $grey-medium-dark; +} +.log { + margin: 10px 0; + padding: 5px 2%; + overflow: auto; + font-size: 0.8rem; + background: $grey-lighter; + color: $grey-dark; +} + +.log > .date { + margin: 0 10px 0 0; + padding: 5px 10px; + border-radius: 20px; +} +.log.error > .date { + background: $alert-bg; + color: #fff; +} +.log.warning > .date { + background: $warning-bg; +} +.log.notice > .date { + background: $grey-light; +} +.log.debug > .date { + background: $main-first-darker; + color: $white; +} diff --git a/p/themes/Ansum/_mixins.scss b/p/themes/Ansum/_mixins.scss new file mode 100644 index 000000000..4c82c438a --- /dev/null +++ b/p/themes/Ansum/_mixins.scss @@ -0,0 +1,57 @@ +/* FUNCTIONS */ + +//animation +@mixin transition($target, $duration, $ease) { + -webkit-transition: $target $duration $ease; + -moz-transition: $target $duration $ease; + -o-transition: $target $duration $ease; + transition: $target $duration $ease; +} + +//animation +@mixin animation-delay($delay) { + -webkit-animation-delay: $delay; + /* Safari 4.0 - 8.0 */ + animation-delay: $delay; +} + +//animation +@mixin animation($animate...) { + $max: length($animate); + $animations: ''; + @for $i from 1 through $max { + $animations: #{$animations + nth($animate, $i)}; + @if $i < $max { + $animations: #{$animations + ", "}; + } + } + -webkit-animation: $animations; + -moz-animation: $animations; + -o-animation: $animations; + animation: $animations; +} + +//keyframes +@mixin keyframes($animationName) { + @-webkit-keyframes #{$animationName} { + @content; + } + @-moz-keyframes #{$animationName} { + @content; + } + @-o-keyframes #{$animationName} { + @content; + } + @keyframes #{$animationName} { + @content; + } +} + +@mixin border-radius($radius: 4px){ + -moz-border-radius: $radius; + -webkit-border-radius: $radius; + -ms-border-radius: $radius; + -o-border-radius: $radius; + -khtml-border-radius: $radius; + border-radius: $radius; +} diff --git a/p/themes/Ansum/_mobile.scss b/p/themes/Ansum/_mobile.scss new file mode 100644 index 000000000..10b432241 --- /dev/null +++ b/p/themes/Ansum/_mobile.scss @@ -0,0 +1,170 @@ +/*=== MOBILE */ +/*===========*/ +@media(max-width: 840px) { + html, body{ + // font-size: 1rem; + } + ul.nav{ + .item{ + width: 100%; + + img{ + display: none; + } + a{ + display: inline-block; + padding: 1rem 1rem 1rem 2.5rem; + color: $sid-font-color; + width: 100%; + + background: url("../../themes/icons/logout.svg") no-repeat $sid-bg-dark 3% center; + + @include transition(all, 0.2s, ease-in-out); + + &:hover, + &:active{ + background: url("../../themes/icons/logout.svg") no-repeat $alert-bg 3% center; + text-decoration: none; + color: $white; + } + } + + } + + } + .aside { + @include transition(all, 0.2s, ease-in-out); + + &.aside_feed { + padding: 0; + } + + .tree .tree-folder .tree-folder-items .item a{ + padding: 0.5rem 1rem; + } + } + .aside .toggle_aside, + #panel .close { + display: block; + width: 100%; + height: 50px; + line-height: 50px; + text-align: center; + background: $main-first-alt; + } + + .header{ + padding: 0.5rem; + .item{ + &.title{ + display: none; + } + + &.search{ + input{ + width: 90%; + height: 3.5rem; + + &:focus{ + width: 100%; + + } + } + .btn{ + min-height: 49px; + padding: 0.5rem 2rem; + } + } + &.configure{ + width: 2.75rem; + top: 3.125rem; + .dropdown{ + .btn{ + padding: 1.125rem; + } + } + } + } + } + + .nav_menu{ + .btn { + margin: 0; + padding: 0.85rem 1.25rem; + } + .stick { + margin: 0.5rem 0.5rem; + + .btn{ + margin: 0; + padding: 0.85rem 1.25rem; + + &.read_all{ + padding: 0.85rem 1.25rem; + } + } + } + .search { + display: none; + max-width: 97%; + + .input{ + + max-width: 97%; + width: 90px; + + &::focus{ + width: 400px; + } + } + } + } + #stream{ + .flux{ + .flux_header{ + padding: 0.5rem 0; + } + } + } + + + + .day{ + text-align: center; + padding: 1rem 0; + .name { + // font-size: 1.1rem; + display: block; + padding: 0; + width: 100%; + line-height: 1.5rem; + margin-bottom: 1rem; + } + + } + + .pagination { + margin: 0 0 3.5em; + } + + #nav_entries{ + line-height: 4.5rem; + } + + .notification { + border-radius: 0; + + a.close { + display: block; + left: 0; + background: transparent; + } + a.close:hover { + opacity: 0.5; + } + a.close .icon { + display: none; + + } + } +} diff --git a/p/themes/Ansum/_reader-view.scss b/p/themes/Ansum/_reader-view.scss new file mode 100644 index 000000000..4368908d6 --- /dev/null +++ b/p/themes/Ansum/_reader-view.scss @@ -0,0 +1,13 @@ +/*=== READER VIEW */ +/*================*/ +#stream.reader .flux { + padding: 0 0 50px; + background: $grey-light; + color: $main-font-color; + border: none; +} +#stream.reader .flux .author { + margin: 0 0 10px; + font-size: 90%; + color: $grey-medium-dark; +} diff --git a/p/themes/Ansum/_sidebar.scss b/p/themes/Ansum/_sidebar.scss new file mode 100644 index 000000000..87d5bd1a9 --- /dev/null +++ b/p/themes/Ansum/_sidebar.scss @@ -0,0 +1,299 @@ +/*=== Tree */ +.tree { + margin: 10px 0; + + &#sidebar{ + scrollbar-color: rgba(255,255, 0, 0.1) rgba(0, 0, 0, 0.05); + scrollbar-color: unquote($sid-font-color+"33") unquote($sid-font-color+"22"); + + + } + + + .tree-folder{ + border-bottom: 1px solid $sid-sep; + + -moz-box-shadow: inset -1px -11px 8px #00000033; + -webkit-box-shadow: inset -1px -11px 8px #00000033; + box-shadow: inset -1px -11px 8px #00000033; + + .tree-folder-title { + position: relative; + background: $sid-bg; + font-size: 0.85rem; + letter-spacing: 1px; + padding: 12px 16px; + font-weight: 700; + text-transform: uppercase; + + .title { + background: inherit; + color: $sid-font-color; + &:hover{ + text-decoration: none; + } + } + } + &.active { + .tree-folder-title { + background: $sid-bg; + font-weight: bold; + } + } + .tree-folder-items { + background: $sid-bg-alt; + + .item{ + padding: 0 1rem; + line-height: 2.5rem; + font-size: 1rem; + font-weight: 400; + @include transition(all, 0.15s, ease-in-out); + + &.active{ + background: $sid-active; + + .dropdown li a{ + color: $main-font-color; + + &:hover{ + color: $sid-font-color; + } + } + + a{ + color: $sid-active-font; + } + } + + &:hover{ + background: $sid-bg-dark; + } + + a{ + text-decoration: none; + color: $sid-font-color; + } + } + + .feed .item-title:not([data-unread="0"])::before { + content: attr(data-unread); + background: $sid-pills; + font-size: 0.75rem; + display: block; + float: left; + padding: 3px 4px; + text-align:center; + border-radius: 12px; + margin: 11px 6px 0 4px; + line-height: 0.75rem; + } + .feed .item-title:not([data-unread="0"]) { + + } + } + } +} + +/*=== Buttons */ +.stick { + vertical-align: middle; + font-size: 0; + + input, .btn { + border-radius: 0; + } + .btn:first-child, + input:first-child { + border-radius: 5px 0 0 5px; + } + .btn:last-child, input:last-child, .btn + .dropdown > .btn { + border-radius: 0 5px 5px 0; + } + .btn + .btn, + .btn + input, + .btn + .dropdown > .btn, + input + .btn, + input + input, + input + .dropdown > .btn, + .dropdown + .btn, + .dropdown + input, + .dropdown + .dropdown > .btn { + border-left: 1px solid $grey-medium-light; + } + +} + +.aside { + background: $sid-bg; + + + &.aside_feed { + padding: 10px 0; + text-align: center; + background: $sid-bg; + border-right: 1px solid $sid-sep; + } + &.aside_feed .tree { + margin: 10px 0 50px; + } + +} + + +/* Sidebar des pages de configuration */ + + + +/*=== Navigation */ + +.nav-list{ + .nav-header, + .item{ + height: 2.5em; + line-height: 2.5em; + font-size: 1rem; + } + .item{ + background: $sid-bg; + @include transition(all, 0.15s, ease-in-out); + a{ + padding: 0 1rem; + color: $sid-font-color; + } + .error{ + a{ + color: $alert-bg; + } + } + &:hover{ + background: $sid-bg-dark; + color: $sid-font-color; + + .error{ + a{ + color: $sid-font-color; + background: $main-first; + } + } + .empty{ + a{ + color: $sid-font-color; + background: $warning-bg; + } + } + + a{ + color: $sid-font-color; + text-decoration: none; + } + } + &.active{ + background: $main-first; + color: $white; + + .error{ + a{ + color: $white; + background: $main-first; + } + } + + .empty{ + a{ + color: $white; + background: $warning-bg; + } + } + + a{ + color: $white; + text-decoration: none; + } + } + + } + &.empty{ + a{ + color: $warning-bg; + } + } + .disable{ + text-align: center; + background: $grey-lighter; + color: $grey-medium-dark; + } + + .nav-header { + padding: 0 10px; + font-weight: bold; + color: $grey-dark; + text-transform: uppercase; + letter-spacing: 1px; + margin-top: 1rem; + } + + .nav-form { + padding: 3px; + text-align: center; + } + + .nav-head { + margin: 0; + text-align: right; + // background: #34495e; + color: $white; + a { + color: $white; + } + .item { + padding: 5px 10px; + font-size: 0.9rem; + line-height: 1.5rem; + } + } +} + +/*=== Aside main page (categories) */ +.aside_feed .tree-folder-title > .title:not([data-unread="0"])::after { + position: absolute; + right: 0; + line-height: 1.5rem; + background: $sid-pills; + border-radius: 12px; + padding: 0 0.75rem; + margin: -0.5rem 1rem 0 0; + text-align: center; +} + +.feed.item.empty.active { + background: $grey-dark; +} +.feed.item.error.active { + background: $grey-dark; +} +.feed.item.empty, +.feed.item.empty > a { + color: $grey-dark; +} +.feed.item.error, +.feed.item.error > a { + color: $grey-dark; +} +.feed.item.empty.active, +.feed.item.error.active, +.feed.item.empty.active > a, +.feed.item.error.active > a { + color: $white; +} +.aside_feed .tree-folder-items .dropdown-menu::after { + left: 2px; +} +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { + border-radius: 3px; +} +.aside_feed .stick #btn-importExport{ + border-left-color: $sid-bg; +} diff --git a/p/themes/Ansum/_stats.scss b/p/themes/Ansum/_stats.scss new file mode 100644 index 000000000..f287efa08 --- /dev/null +++ b/p/themes/Ansum/_stats.scss @@ -0,0 +1,27 @@ +/*=== STATISTICS */ +/*===============*/ +.stat { + margin: 10px 0 20px; +} + +.stat th, +.stat td, +.stat tr { + border: none; +} +.stat > table td, +.stat > table th { + border-bottom: 1px solid $grey-medium-light; +} + +.stat > .horizontal-list { + margin: 0 0 5px; +} +.stat > .horizontal-list .item { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.stat > .horizontal-list .item:first-child { + width: 270px; +} diff --git a/p/themes/Ansum/_tables.scss b/p/themes/Ansum/_tables.scss new file mode 100644 index 000000000..608e19aca --- /dev/null +++ b/p/themes/Ansum/_tables.scss @@ -0,0 +1,17 @@ +/*=== Tables */ +table { + border-collapse: collapse; +} + +tr, th, td { + padding: 0.5em; + border: 1px solid $grey-medium-light; +} +th { + background: $grey-lighter; +} +form td, +form th { + font-weight: normal; + text-align: center; +} diff --git a/p/themes/Ansum/_variables.scss b/p/themes/Ansum/_variables.scss new file mode 100644 index 000000000..9fc4238ab --- /dev/null +++ b/p/themes/Ansum/_variables.scss @@ -0,0 +1,53 @@ +// La couleur principale du thème +$main-first: #ca7227; // couleur principale +$main-first-alt: #b7641d; // var pour les hovers +$main-first-light: #fdf6ef; // var light 1 +$main-first-lighter: #fefaf7; // var light 2 +$main-first-dark: #3c3835; // var pour les hovers +$main-first-darker: #221f1d; // var pour les hovers + +// les couleurs de polices liées +$main-font-color: #363330; +$light-font-color: #6d655f; +$white: #fff; // le blanc (des fois qu'on aurait envie de le teinter un peu) + +// toute la palette des gris, très utile +// on essaiera de teinter ces gris suivant la couleur principale +$grey-darker: #524236; +$grey-dark: #766556; +$grey-medium-dark: #bbaa99; +$grey-medium: #d9ccbf; +$grey-medium-light: #e4d8cc; +$grey-light: #f5f0ec; +$grey-lighter: #fcfaf8; + +$unread-font-color: #161a38; +$unread-bg: #f2f6f8; +$unread-bg-light: #fdfdfe; + +// les couleurs d'alertes (rouge, jaune, vert) +$alert-bg: #f5633e; // la base +$alert-light: #fde0d8; // +light +$alert-text: #73341f; // +foncé + +$warning-bg: #f4f762; +$warning-light: #fdfde0; +$warning-text: #73762f; + +$success-bg: #10f5b2; +$success-light: #cffdef; +$success-text: #0c7556; + +// les favoris +$fav-bg: #FFC300; +$fav-light: #FFF6DA; + +// la couleur de sidebar, utile si on a envie d'un thème qui aurait une sidebar foncé, e.g. +$sid-font-color: #363330; // la couleur de fond de la barre de gauche et du header +$sid-bg: #fbf9f6; // le background général de la barre de gauche, et du header +$sid-bg-alt: #f7f2ea; // le background de l'intérieur des groupes +$sid-bg-dark: #efe3d3; // les hovers +$sid-sep: #f0e7da; // les séparateurs +$sid-active: $main-first; // la couleur active +$sid-active-font: #FFFFFF; // la couleur active +$sid-pills: rgba(35,35,0, 0.15); // les gélules diff --git a/p/themes/Ansum/ansum.css b/p/themes/Ansum/ansum.css new file mode 100644 index 000000000..bc4ae36b4 --- /dev/null +++ b/p/themes/Ansum/ansum.css @@ -0,0 +1,1299 @@ +@font-face { + font-family: "lato"; + font-style: normal; + font-stretch: normal; + font-weight: 400; + src: local("Lato"), url("../fonts/LatoLatin-Regular.woff") format("woff"); } +@font-face { + font-family: "lato"; + font-style: italic; + font-stretch: normal; + font-weight: 400; + src: local("Lato"), url("../fonts/LatoLatin-Italic.woff") format("woff"); } +@font-face { + font-family: "lato"; + font-style: normal; + font-stretch: normal; + font-weight: 700; + src: local("Lato"), url("../fonts/LatoLatin-Bold.woff") format("woff"); } +@font-face { + font-family: "lato"; + font-style: italic; + font-stretch: normal; + font-weight: 700; + src: local("Lato"), url("../fonts/LatoLatin-BoldItalic.woff") format("woff"); } +@font-face { + font-family: "spectral"; + font-style: normal; + font-stretch: normal; + font-weight: 400; + src: local("Spectral"), url("../fonts/Spectral-Regular.woff") format("woff"); } +@font-face { + font-family: "spectral"; + font-style: italic; + font-stretch: normal; + font-weight: 400; + src: local("Spectral"), url("../fonts/Spectral-Italic.woff") format("woff"); } +@font-face { + font-family: "spectral"; + font-style: normal; + font-stretch: normal; + font-weight: 700; + src: local("Spectral"), url("../fonts/Spectral-Bold.woff") format("woff"); } +@font-face { + font-family: "spectral"; + font-style: italic; + font-stretch: normal; + font-weight: 700; + src: local("Spectral"), url("../fonts/Spectral-BoldItalic.woff") format("woff"); } +/* FUNCTIONS */ +/* btns */ +.btn { + display: inline-block; + min-height: 38px; + min-width: 15px; + line-height: 25px; + margin: 0; + padding: 0.5rem 1.5rem; + font-size: 1rem; + vertical-align: middle; + cursor: pointer; + overflow: hidden; + background: #fcfaf8; + border-radius: 5px; + border: none; + color: #766556; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .btn.btn-important { + background: #ca7227; + color: #fff; } + .btn.btn-important:hover, .btn.btn-important:active { + background: #b7641d; } + .btn.btn-attention { + background: #f5633e; + color: #fff; } + .btn.btn-attention:hover, .btn.btn-attention:active { + background: #73341f; } + .btn:hover { + text-decoration: none; } + +a.btn { + min-height: 25px; + line-height: 25px; } + +/*=== Forms */ +legend { + display: inline-block; + width: auto; + margin: 2rem 0 1rem 0; + padding: 0; + font-size: 1rem; + clear: both; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 700; } + +label { + min-height: 25px; + padding: 5px 0; + cursor: pointer; + color: #766556; } + +textarea { + width: 360px; + height: 100px; } + +input, select, textarea, button { + font-family: "lato", "Helvetica", "Arial", sans-serif; + min-height: 25px; + padding: 5px 10px; + line-height: 25px; + vertical-align: middle; + background: #fff; + border: 1px solid #f5f0ec; + font-size: 1rem; + color: #766556; + border-radius: 2px; } + +option { + padding: 0 .5em; } + +input:focus, select:focus, textarea:focus { + color: #363330; + border-color: #ca7227; } + +input:invalid, select:invalid { + color: #f5633e; + border-color: #f5633e; + box-shadow: none; } + +input:disabled, select:disabled { + background: #f5f0ec; } + +input.extend { + transition: width 200ms linear; + -moz-transition: width 200ms linear; + -webkit-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; } + +.form-group { + padding: 5px; + border-radius: 3px; } + .form-group::after { + content: ""; + display: block; + clear: both; } + .form-group .group-name { + padding: 10px 0; + text-align: right; } + .form-group .group-controls { + min-height: 25px; + padding: 5px 0; } + .form-group .group-controls .control { + line-height: 2.0em; } + .form-group table { + margin: 10px 0 0 220px; } + .form-group.form-actions { + margin: 15px 0 25px; + padding: 5px 0; } + .form-group.form-actions .btn { + margin: 0 0.5rem 0 0; } + +/*=== Tables */ +table { + border-collapse: collapse; } + +tr, th, td { + padding: 0.5em; + border: 1px solid #e4d8cc; } + +th { + background: #fcfaf8; } + +form td, +form th { + font-weight: normal; + text-align: center; } + +/*=== COMPONENTS */ +/*===============*/ +/*=== Forms */ +/*=== Horizontal-list */ +.horizontal-list { + margin: 0; + padding: 0.1rem 0; } + .horizontal-list .item { + vertical-align: middle; } + .horizontal-list .item:first-child { + padding-left: 0.5rem; } + +/*=== Dropdown */ +.dropdown-menu { + background: #fcfaf8; + margin: 0; + font-size: 1rem; + text-align: left; + padding: 0.5rem 0 1rem 0; + border: none; + border-radius: 3px; + -webkit-box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); + -moz-box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); + box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); } + .dropdown-menu::after { + content: ""; + position: absolute; + top: -4px; + right: 13px; + width: 10px; + height: 10px; + z-index: -10; + transform: rotate(45deg); + -moz-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + background: white; } + .dropdown-menu .dropdown-header { + margin: 1.75rem 0 0.5rem 2rem; + font-weight: bold; + text-align: left; + color: #766556; + text-transform: uppercase; + letter-spacing: 1px; } + .dropdown-menu .item { + -webkit-transition: all 0.075s ease-in-out; + -moz-transition: all 0.075s ease-in-out; + -o-transition: all 0.075s ease-in-out; + transition: all 0.075s ease-in-out; } + .dropdown-menu .item a, .dropdown-menu .item span, .dropdown-menu .item .as-link { + padding: 0 2rem; + line-height: 2.5em; + font-size: 1rem; + color: #363330; } + .dropdown-menu .item:hover { + background: #ca7227; + color: #fff; } + .dropdown-menu .item:hover a, .dropdown-menu .item:hover button { + text-decoration: none; + color: #fff; } + .dropdown-menu .item[aria-checked="true"] a::before { + font-weight: bold; + margin: 0 0 0 -14px; } + .dropdown-menu .input select, .dropdown-menu .input input { + margin: 0 auto 5px; + padding: 2px 5px; + border-radius: 3px; } + .dropdown-menu .separator { + margin: 0.75rem 0; + border-bottom: 1px solid #f5f0ec; } + +.tree .tree-folder .tree-folder-items .dropdown-menu .item, +.tree .tree-folder .tree-folder-items .dropdown-menu .item { + padding: 0; } + .tree .tree-folder .tree-folder-items .dropdown-menu .item a, + .tree .tree-folder .tree-folder-items .dropdown-menu .item button, + .tree .tree-folder .tree-folder-items .dropdown-menu .item a, + .tree .tree-folder .tree-folder-items .dropdown-menu .item button { + color: #363330; } + .tree .tree-folder .tree-folder-items .dropdown-menu .item a:hover, + .tree .tree-folder .tree-folder-items .dropdown-menu .item button:hover, + .tree .tree-folder .tree-folder-items .dropdown-menu .item a:hover, + .tree .tree-folder .tree-folder-items .dropdown-menu .item button:hover { + color: #fff; } + .tree .tree-folder .tree-folder-items .dropdown-menu .item:hover, + .tree .tree-folder .tree-folder-items .dropdown-menu .item:hover { + background: #ca7227; } + +/*=== Alerts */ +.alert { + margin: 1rem 0; + padding: 1rem; + font-size: 1rem; + background: #fcfaf8; + border: 1px solid #d9ccbf; + border-radius: 3px; + color: #766556; + text-shadow: 0 0 1px #f5f0ec; } + +.alert-head { + font-size: 1.15em; } + +.alert > a { + text-decoration: underline; + color: inherit; } + +.alert-warn { + background: #fdfde0; + border: 1px solid #73762f33; + color: #73762f; } + +.alert-success { + background: #cffdef; + border: 1px solid #0c755633; + color: #0c7556; } + +.alert-error { + background: #fde0d8; + border: 1px solid #73341f33; + color: #73341f; } + +/*=== Pagination */ +.pagination { + text-align: center; + font-size: 0.8em; + background: #f5f0ec; + color: #363330; } + .pagination .item.pager-current { + font-weight: bold; + font-size: 1.5em; + background: #fbf9f6; + color: #f5f0ec; } + .pagination .item a { + display: block; + font-style: italic; + line-height: 3em; + text-decoration: none; + color: #363330; } + .pagination .item a:hover { + background: #363330; + color: #f5f0ec; } + .pagination .loading, + .pagination a:hover.loading { + font-size: 0; + background: url("loader.gif") center center no-repeat #34495e; } + +.content .pagination { + margin: 0; + padding: 0; } + +/*=== Boxes */ +.box { + border: none; + border-radius: 3px; + background: #fff; + -webkit-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.25); + box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.25); } + .box .box-title { + margin: 0; + padding: 5px 10px; + background: #f5f0ec; + color: #363330; + border-radius: 2px 2px 0 0; } + .box .box-title form input { + width: 85%; } + .box .box-title form .dropdown { + float: right; } + .box .box-title form .dropdown a.dropdown-toggle { + padding: 0; + background-image: url(icons/more.svg); + background-repeat: no-repeat; + background-position: right 8px; + border-radius: 0; } + .box .box-title form .dropdown a.dropdown-toggle img { + display: none; } + .box .box-content .item { + padding: 0.5rem 0.75rem; + font-size: 1rem; + color: #363330; + line-height: 1.7em; + border-bottom: 1px solid #f5f0ec; } + .box .box-content .item img { + margin-right: 0.75rem; } + .box .box-content .item .configure { + visibility: hidden; + width: 1.75rem; + height: 1.75rem; + display: block; + border-radius: 2px; + float: left; + margin-right: 0.5rem; + background: url("icons/cog.svg") no-repeat 4px 4px; } + .box .box-content .item .configure .icon { + vertical-align: middle; + border-radius: 3px; + display: none; } + .box .box-content .item .configure:hover { + background: url("icons/cog-white.svg") no-repeat 4px 4px #ca7227; } + .box .box-content .item:hover .configure { + visibility: visible; } + .box .box-content .item:last-child { + border-bottom: none; } + +/*=== "Load more" part */ +#bigMarkAsRead { + text-align: center; + text-decoration: none; + background: #fdf6ef; + color: #ca7227; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + #bigMarkAsRead:hover { + background: #ca7227; + color: #fff; } + #bigMarkAsRead:hover .bigTick { + background: url(icons/tick-white.svg) center no-repeat; } + #bigMarkAsRead .bigTick { + margin: 0.5rem 0; + display: inline-block; + text-indent: -9999px; + background: url(icons/tick-color.svg) center no-repeat; + height: 64px; + width: 64px; + white-space: nowrap; } + +.formLogin { + background: #fbf9f6; } + .formLogin .header .configure { + padding-right: 1rem; } + .formLogin .header .configure img { + margin-right: 0.5rem; } + .formLogin .header .configure a.signin { + color: #fff; } + .formLogin h1 { + color: #fff; } + .formLogin form#crypto-form div { + margin-bottom: 1rem; } + .formLogin form#crypto-form div label { + font-size: 1rem; + color: #d9ccbf; } + .formLogin form#crypto-form div input { + background: #221f1d; } + .formLogin form#crypto-form div input:focus { + background: #fcfaf8; + color: #363330; } + +/*=== DIVERS */ +/*===========*/ +.aside.aside_feed .nav-form input, +.aside.aside_feed .nav-form select { + width: 140px; } + +.aside.aside_feed .nav-form .dropdown .dropdown-menu { + right: -20px; } + +.aside.aside_feed .nav-form .dropdown .dropdown-menu::after { + right: 33px; } + +/*=== Tree */ +.tree { + margin: 10px 0; } + .tree#sidebar { + scrollbar-color: rgba(255, 255, 0, 0.1) rgba(0, 0, 0, 0.05); + scrollbar-color: #36333033 #36333022; } + .tree .tree-folder { + border-bottom: 1px solid #f0e7da; + -moz-box-shadow: inset -1px -11px 8px #00000033; + -webkit-box-shadow: inset -1px -11px 8px #00000033; + box-shadow: inset -1px -11px 8px #00000033; } + .tree .tree-folder .tree-folder-title { + position: relative; + background: #fbf9f6; + font-size: 0.85rem; + letter-spacing: 1px; + padding: 12px 16px; + font-weight: 700; + text-transform: uppercase; } + .tree .tree-folder .tree-folder-title .title { + background: inherit; + color: #363330; } + .tree .tree-folder .tree-folder-title .title:hover { + text-decoration: none; } + .tree .tree-folder.active .tree-folder-title { + background: #fbf9f6; + font-weight: bold; } + .tree .tree-folder .tree-folder-items { + background: #f7f2ea; } + .tree .tree-folder .tree-folder-items .item { + padding: 0 1rem; + line-height: 2.5rem; + font-size: 1rem; + font-weight: 400; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .tree .tree-folder .tree-folder-items .item.active { + background: #ca7227; } + .tree .tree-folder .tree-folder-items .item.active .dropdown li a { + color: #363330; } + .tree .tree-folder .tree-folder-items .item.active .dropdown li a:hover { + color: #363330; } + .tree .tree-folder .tree-folder-items .item.active a { + color: #FFFFFF; } + .tree .tree-folder .tree-folder-items .item:hover { + background: #efe3d3; } + .tree .tree-folder .tree-folder-items .item a { + text-decoration: none; + color: #363330; } + .tree .tree-folder .tree-folder-items .feed .item-title:not([data-unread="0"])::before { + content: attr(data-unread); + background: rgba(35, 35, 0, 0.15); + font-size: 0.75rem; + display: block; + float: left; + padding: 3px 4px; + text-align: center; + border-radius: 12px; + margin: 11px 6px 0 4px; + line-height: 0.75rem; } + +/*=== Buttons */ +.stick { + vertical-align: middle; + font-size: 0; } + .stick input, .stick .btn { + border-radius: 0; } + .stick .btn:first-child, + .stick input:first-child { + border-radius: 5px 0 0 5px; } + .stick .btn:last-child, .stick input:last-child, .stick .btn + .dropdown > .btn { + border-radius: 0 5px 5px 0; } + .stick .btn + .btn, + .stick .btn + input, + .stick .btn + .dropdown > .btn, + .stick input + .btn, + .stick input + input, + .stick input + .dropdown > .btn, + .stick .dropdown + .btn, + .stick .dropdown + input, + .stick .dropdown + .dropdown > .btn { + border-left: 1px solid #e4d8cc; } + +.aside { + background: #fbf9f6; } + .aside.aside_feed { + padding: 10px 0; + text-align: center; + background: #fbf9f6; + border-right: 1px solid #f0e7da; } + .aside.aside_feed .tree { + margin: 10px 0 50px; } + +/* Sidebar des pages de configuration */ +/*=== Navigation */ +.nav-list .nav-header, +.nav-list .item { + height: 2.5em; + line-height: 2.5em; + font-size: 1rem; } +.nav-list .item { + background: #fbf9f6; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .nav-list .item a { + padding: 0 1rem; + color: #363330; } + .nav-list .item .error a { + color: #f5633e; } + .nav-list .item:hover { + background: #efe3d3; + color: #363330; } + .nav-list .item:hover .error a { + color: #363330; + background: #ca7227; } + .nav-list .item:hover .empty a { + color: #363330; + background: #f4f762; } + .nav-list .item:hover a { + color: #363330; + text-decoration: none; } + .nav-list .item.active { + background: #ca7227; + color: #fff; } + .nav-list .item.active .error a { + color: #fff; + background: #ca7227; } + .nav-list .item.active .empty a { + color: #fff; + background: #f4f762; } + .nav-list .item.active a { + color: #fff; + text-decoration: none; } +.nav-list.empty a { + color: #f4f762; } +.nav-list .disable { + text-align: center; + background: #fcfaf8; + color: #bbaa99; } +.nav-list .nav-header { + padding: 0 10px; + font-weight: bold; + color: #766556; + text-transform: uppercase; + letter-spacing: 1px; + margin-top: 1rem; } +.nav-list .nav-form { + padding: 3px; + text-align: center; } +.nav-list .nav-head { + margin: 0; + text-align: right; + color: #fff; } + .nav-list .nav-head a { + color: #fff; } + .nav-list .nav-head .item { + padding: 5px 10px; + font-size: 0.9rem; + line-height: 1.5rem; } + +/*=== Aside main page (categories) */ +.aside_feed .tree-folder-title > .title:not([data-unread="0"])::after { + position: absolute; + right: 0; + line-height: 1.5rem; + background: rgba(35, 35, 0, 0.15); + border-radius: 12px; + padding: 0 0.75rem; + margin: -0.5rem 1rem 0 0; + text-align: center; } + +.feed.item.empty.active { + background: #766556; } + +.feed.item.error.active { + background: #766556; } + +.feed.item.empty, +.feed.item.empty > a { + color: #766556; } + +.feed.item.error, +.feed.item.error > a { + color: #766556; } + +.feed.item.empty.active, +.feed.item.error.active, +.feed.item.empty.active > a, +.feed.item.error.active > a { + color: #fff; } + +.aside_feed .tree-folder-items .dropdown-menu::after { + left: 2px; } + +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { + border-radius: 3px; } + +.aside_feed .stick #btn-importExport { + border-left-color: #fbf9f6; } + +/*=== STRUCTURE */ +/*===============*/ +/*=== Header */ +.header { + background: #fbf9f6; + padding: 0.5rem 1.35rem; + display: block; + table-layout: none; + width: auto; } + .header .item { + vertical-align: middle; } + .header .item.title { + font-weight: 400; + width: 280px; } + .header .item.title h1 a { + text-decoration: none; + color: #363330; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; } + .header .item.title h1 a img { + margin-right: 0.5rem; } + .header .item.search input { + width: 230px; + border-radius: 2px 0 0 2px; + background-color: #f7f2ea; + color: #363330; + border: none; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .header .item.search input:hover { + background-color: #efe3d3; } + .header .item.search input:focus { + width: 350px; + background-color: #fff; + color: #766556; } + .header .item.search .btn { + border-radius: 0 2px 2px 0; + background-color: #ca7227; + background-position: center; + background-repeat: no-repeat; + background-image: url(icons/magnifier.svg); + border-left-width: 0; + width: 3rem; + min-height: 35px; } + .header .item.search .btn img { + display: none; } + .header .item.search .btn:hover { + background-color: #b7641d; } + .header .item.configure { + width: 2rem; + position: absolute; + right: 1rem; + top: 1.25rem; + text-align: center; } + .header .item.configure .btn { + background-color: transparent; + background-position: center; + background-repeat: no-repeat; + background-image: url(icons/cog.svg); + padding: 0 0.5rem; } + .header .item.configure .btn img { + display: none; } + +/*=== Body */ +#global { + height: calc(100% - 85px); } + +/*=== Prompt (centered) */ +.prompt { + text-align: center; } + +.prompt label { + text-align: left; } + +.prompt form { + margin: 10px auto 20px auto; + width: 200px; } + +.prompt input { + margin: 5px auto; + width: 100%; } + +.prompt p { + margin: 20px 0; } + +/*=== New article notification */ +#new-article { + text-align: center; + font-size: 1rem; + background: #ca7227; } + +#new-article:hover { + background: #b7641d; } + +#new-article > a { + line-height: 3em; + font-weight: bold; + color: #fff; } + +#new-article > a:hover { + text-decoration: none; } + +/*=== Day indication */ +.day { + padding: 1rem 0 0 1.25rem; + font-weight: 700; + line-height: 3em; + letter-spacing: 1px; + text-transform: uppercase; + font-size: 0.875rem; + color: #6d655f; } + .day .name { + padding: 0 1rem 0 1rem; + font-size: 0.875rem; + color: #363330; + position: relative; + left: 0; + text-transform: uppercase; } + +/*=== Index menu */ +.nav_menu { + text-align: center; + padding: 5px 0; } + .nav_menu .btn { + border-left-width: 0; + padding: 0.5rem 1rem; + background-color: #fcfaf8; + background-position: center; + background-repeat: no-repeat; } + .nav_menu .btn:hover { + background-color: #f5f0ec; } + .nav_menu .stick { + background: #fcfaf8; } + .nav_menu .stick .btn { + border-left-width: 0; + padding: 0.5rem 1rem; + background-color: #fcfaf8; + background-position: center; + background-repeat: no-repeat; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .nav_menu .stick .btn:hover { + background-color: #e4d8cc; } + .nav_menu .stick .btn.active { + background-color: #ca7227; } + .nav_menu .stick .btn img.icon { + display: none; } + .nav_menu .stick .btn#toggle-read { + background-image: url(icons/read.svg); } + .nav_menu .stick .btn#toggle-read.active { + background-image: url(icons/read-white.svg); } + .nav_menu .stick .btn#toggle-unread { + background-image: url(icons/unread.svg); } + .nav_menu .stick .btn#toggle-unread.active { + background-image: url(icons/unread-white.svg); } + .nav_menu .stick .btn#toggle-starred { + background-image: url(icons/starred.svg); } + .nav_menu .stick .btn#toggle-starred.active { + background-image: url(icons/starred-white.svg); } + .nav_menu .stick .btn#toggle-non-starred { + background-image: url(icons/non-starred.svg); } + .nav_menu .stick .btn#toggle-non-starred.active { + background-image: url(icons/non-starred-white.svg); } + .nav_menu .stick .btn.read_all { + background-color: #fcfaf8; + color: #363330; + padding: 5px 16px; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .nav_menu .stick .btn.read_all:hover { + background-color: #e4d8cc; } + .nav_menu .stick .btn.view-normal { + background-image: url(icons/view-list.svg); } + .nav_menu .stick .btn.view-normal.active { + background-image: url(icons/view-list-white.svg); } + .nav_menu .stick .btn.view-global { + background-image: url(icons/view-global.svg); } + .nav_menu .stick .btn.view-global.active { + background-image: url(icons/view-global-white.svg); } + .nav_menu .stick .btn.view-reader { + background-image: url(icons/view-reader.svg); } + .nav_menu .stick .btn.view-reader.active { + background-image: url(icons/view-reader-white.svg); } + .nav_menu .stick .btn.view-rss { + background-image: url(icons/rss.svg); } + .nav_menu .stick .dropdown a.dropdown-toggle { + border-left-width: 0; + background-image: url(icons/more.svg); } + +#dropdown-query ~ .dropdown-menu .dropdown-header .icon { + vertical-align: middle; + background-color: #bbaa99; + border-radius: 3px; } + +/*=== Content of feed articles */ +.content, .content.thin { + padding: 20px 10px; + font-size: 1.125rem; + line-height: 1.8rem; } + .content h1.title a, .content h1 a, .content.thin h1.title a, .content.thin h1 a { + color: #363330; + font-family: "spectral"; + font-size: 2rem; } + .content h1.title a:hover, .content h1 a:hover, .content.thin h1.title a:hover, .content.thin h1 a:hover { + color: #ca7227; + text-decoration: none; } + .content .author, .content.thin .author { + font-size: 1.125rem; + color: #6d655f; } + .content p, .content ul, .content.thin p, .content.thin ul { + font-size: 1.125rem; + line-height: 1.8rem; } + .content .content hr, .content.thin .content hr { + margin: 30px 10px; + height: 1px; + background: #e4d8cc; + border: 0; + box-shadow: 0 2px 5px #ccc; } + .content pre, .content.thin pre { + margin: 10px auto; + padding: 10px 20px; + overflow: auto; + background: #221f1d; + color: #fff; + font-size: 0.9rem; + border-radius: 3px; } + .content pre code, .content.thin pre code { + background: transparent; + color: #fff; + border: none; } + .content code, .content.thin code { + padding: 2px 5px; + color: #f5f0ec; + background: #fcfaf8; + border: 1px solid #f5f0ec; + border-radius: 3px; } + .content blockquote, .content.thin blockquote { + display: block; + margin: 0; + padding: 5px 20px; + border-top: 1px solid #e4d8cc; + border-bottom: 1px solid #e4d8cc; + background: #fcfaf8; + color: #363330; } + .content blockquote p, .content.thin blockquote p { + margin: 0; } + +/*=== Notification and actualize notification */ +.notification { + position: fixed; + top: auto; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 3rem; + padding: 1rem 0; + text-align: center; + font-size: 1em; + line-height: 3em; + z-index: 10; + vertical-align: middle; + background: #e4d8cc; + color: #766556; + border: none; } + .notification .msg { + font-size: 1rem; + display: inline-block; } + .notification.good { + background: #10f5b2; + color: #fff; } + .notification.bad { + background: #f5633e; + color: #fff; } + .notification a.close { + padding: 0 15px; + line-height: 3em; + border-radius: 0 3px 3px 0; } + .notification.good a.close:hover { + background: #0c7556; } + .notification.bad a.close:hover { + background: #73341f; } + .notification#actualizeProgress { + line-height: 2em; } + .notification#actualizeProgress br { + display: none; } + +/*=== Navigation menu (for articles) */ +#nav_entries { + margin: 0; + text-align: center; + line-height: 3em; + table-layout: fixed; + background: #fbf9f6; } + +/*=== Feed articles */ +.flux { + background: #fff; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .flux:hover { + background: #fcfaf8; } + .flux:hover:not(.current):hover .item.title { + background: #fcfaf8; } + .flux.current { + border-left-color: #ca7227; + background: #fff; } + .flux.not_read { + background: #f2f6f8; } + .flux.not_read:hover { + background: #fdfdfe; } + .flux.not_read:not(.current):hover .item.title { + background: #fdfdfe; } + .flux.not_read .item.title a { + color: #161a38; } + .flux.not_read .item.website a { + color: #161a38; } + .flux.not_read .item.date { + color: #161a3899; } + .flux.favorite { + background: #FFF6DA; + border-left-color: #FFC300; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .flux.favorite:not(.current):hover .item.title { + background: #FFF6DA; } + .flux .website a { + color: #363330; + opacity: 0.75; } + .flux .website .favicon { + padding: 5px; } + .flux .date { + font-size: 0.85rem; + color: #363330; + opacity: 0.75; } + .flux .bottom { + font-size: 1rem; + text-align: center; } + +.flux_header { + font-size: 1rem; + cursor: pointer; + border-top: 1px solid #f5f0ec; } + .flux_header .title { + font-size: 1rem; } + +/*=== GLOBAL VIEW */ +/*================*/ +#stream .box.category:not([data-unread="0"]) .box-title .title { + font-weight: bold; } +#stream .box.category .box-title { + background: none; + padding: 1.5rem; } + #stream .box.category .box-title a.title { + font-weight: normal; + text-decoration: none; + text-align: left; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; + color: #766556; } + #stream .box.category .box-title a.title:not([data-unread="0"])::after { + position: absolute; + top: 1.75rem; + right: 0; + line-height: 1.5rem; + background: #f5f0ec; + border-radius: 12px; + padding: 0 0.75rem; + margin: -0.5rem 1rem 0 0; + text-align: center; } + #stream .box.category .box-title a.title:hover { + color: #ca7227; } +#stream .box.category .box-content { + padding-bottom: 0.5rem; } + #stream .box.category .box-content .item.feed { + font-size: 1rem; + padding: 0.5rem 1.5rem; } + #stream .box.category .box-content .item.feed a { + color: #363330; + font-weight: 400; } + #stream .box.category .box-content .item.feed a:hover { + color: #ca7227; + text-decoration: none; } + +#overlay { + background: rgba(0, 0, 0, 0.65); } + +#panel { + top: 3rem; + right: 3rem; + bottom: 3rem; + left: 3rem; + border-radius: 3px; } + +/*=== READER VIEW */ +/*================*/ +#stream.reader .flux { + padding: 0 0 50px; + background: #f5f0ec; + color: #363330; + border: none; } + +#stream.reader .flux .author { + margin: 0 0 10px; + font-size: 90%; + color: #bbaa99; } + +/*=== Configuration pages */ +.post { + padding: 1rem 2rem; + font-size: 1rem; } + .post form { + margin: 1rem 0; } + .post form .horizontal-list { + margin-bottom: 0.5rem; } + .post.content { + max-width: 550px; } + .post h1, .post h2 { + font-size: 3rem; + margin-top: 1.75rem; + font-weight: 300; + line-height: 1.2em; + color: #363330; } + .post a[href="./"] { + display: inline-block; + min-width: 15px; + line-height: 25px; + margin: 0; + padding: 0.75rem 1.5rem; + font-size: 1rem; + vertical-align: middle; + cursor: pointer; + overflow: hidden; + background: #fcfaf8; + border: 1px solid #e4d8cc; + border-radius: 5px; + color: #766556; } + .post a[href="./"]:hover { + text-decoration: none; + background: #ca7227; + color: white; + border: 1px solid #ca7227; } + +#slider { + border-left: none; + -webkit-box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); + -moz-box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); + box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); } + +.slide-container .properties { + background: rgba(0, 0, 0, 0.75); + border: 0; + padding: 1rem; + color: white; } + .slide-container .properties .page-number { + right: 1rem; + top: 1rem; } + +/*=== LOGS */ +/*=========*/ +.loglist { + overflow: hidden; + border: 1px solid #bbaa99; } + +.log { + margin: 10px 0; + padding: 5px 2%; + overflow: auto; + font-size: 0.8rem; + background: #fcfaf8; + color: #766556; } + +.log > .date { + margin: 0 10px 0 0; + padding: 5px 10px; + border-radius: 20px; } + +.log.error > .date { + background: #f5633e; + color: #fff; } + +.log.warning > .date { + background: #f4f762; } + +.log.notice > .date { + background: #f5f0ec; } + +.log.debug > .date { + background: #221f1d; + color: #fff; } + +/*=== STATISTICS */ +/*===============*/ +.stat { + margin: 10px 0 20px; } + +.stat th, +.stat td, +.stat tr { + border: none; } + +.stat > table td, +.stat > table th { + border-bottom: 1px solid #e4d8cc; } + +.stat > .horizontal-list { + margin: 0 0 5px; } + +.stat > .horizontal-list .item { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } + +.stat > .horizontal-list .item:first-child { + width: 270px; } + +/*=== MOBILE */ +/*===========*/ +@media (max-width: 840px) { + ul.nav .item { + width: 100%; } + ul.nav .item img { + display: none; } + ul.nav .item a { + display: inline-block; + padding: 1rem 1rem 1rem 2.5rem; + color: #363330; + width: 100%; + background: url("../../themes/icons/logout.svg") no-repeat #efe3d3 3% center; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + ul.nav .item a:hover, ul.nav .item a:active { + background: url("../../themes/icons/logout.svg") no-repeat #f5633e 3% center; + text-decoration: none; + color: #fff; } + + .aside { + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + .aside.aside_feed { + padding: 0; } + .aside .tree .tree-folder .tree-folder-items .item a { + padding: 0.5rem 1rem; } + + .aside .toggle_aside, + #panel .close { + display: block; + width: 100%; + height: 50px; + line-height: 50px; + text-align: center; + background: #b7641d; } + + .header { + padding: 0.5rem; } + .header .item.title { + display: none; } + .header .item.search input { + width: 90%; + height: 3.5rem; } + .header .item.search input:focus { + width: 100%; } + .header .item.search .btn { + min-height: 49px; + padding: 0.5rem 2rem; } + .header .item.configure { + width: 2.75rem; + top: 3.125rem; } + .header .item.configure .dropdown .btn { + padding: 1.125rem; } + + .nav_menu .btn { + margin: 0; + padding: 0.85rem 1.25rem; } + .nav_menu .stick { + margin: 0.5rem 0.5rem; } + .nav_menu .stick .btn { + margin: 0; + padding: 0.85rem 1.25rem; } + .nav_menu .stick .btn.read_all { + padding: 0.85rem 1.25rem; } + .nav_menu .search { + display: none; + max-width: 97%; } + .nav_menu .search .input { + max-width: 97%; + width: 90px; } + .nav_menu .search .input::focus { + width: 400px; } + + #stream .flux .flux_header { + padding: 0.5rem 0; } + + .day { + text-align: center; + padding: 1rem 0; } + .day .name { + display: block; + padding: 0; + width: 100%; + line-height: 1.5rem; + margin-bottom: 1rem; } + + .pagination { + margin: 0 0 3.5em; } + + #nav_entries { + line-height: 4.5rem; } + + .notification { + border-radius: 0; } + .notification a.close { + display: block; + left: 0; + background: transparent; } + .notification a.close:hover { + opacity: 0.5; } + .notification a.close .icon { + display: none; } } +html, body { + font-family: "lato", "Helvetica", "Arial", sans-serif; + font-size: 0.875rem; } + +/*=== GENERAL */ +/*============*/ +html, body { + height: 100%; + background: #f5f0ec; } + +/*=== Links */ +a, button.as-link { + outline: none; + color: #ca7227; } + +/*# sourceMappingURL=ansum.css.map */ diff --git a/p/themes/Ansum/ansum.css.map b/p/themes/Ansum/ansum.css.map new file mode 100644 index 000000000..7b1c15ade --- /dev/null +++ b/p/themes/Ansum/ansum.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["_fonts.scss","_mixins.scss","_forms.scss","_variables.scss","_tables.scss","_components.scss","_divers.scss","_sidebar.scss","_layout.scss","_list-view.scss","_global-view.scss","_reader-view.scss","_configuration.scss","_logs.scss","_stats.scss","_mobile.scss","ansum.scss"], +"names": [], +"file": "ansum.css" +} \ No newline at end of file diff --git a/p/themes/Ansum/ansum.scss b/p/themes/Ansum/ansum.scss new file mode 100644 index 000000000..1a538b50a --- /dev/null +++ b/p/themes/Ansum/ansum.scss @@ -0,0 +1,51 @@ +@import "fonts"; +@import "mixins"; +@import "variables"; + +@import "forms"; +@import "tables"; +@import "components"; + +@import "divers"; + +@import "sidebar"; +@import "layout"; +@import "list-view"; +@import "global-view"; +@import "reader-view"; + +@import "configuration"; + +@import "logs"; +@import "stats"; + +@import "mobile"; + +html, body{ + font-family: "lato", "Helvetica", "Arial", sans-serif; + font-size: 0.875rem; +} + +@charset "UTF-8"; + +/*=== GENERAL */ +/*============*/ +html, body { + height: 100%; + background: $grey-light; +} + +/*=== Links */ +a, button.as-link { + outline: none; + color: $main-first; +} + + + + + + + + + diff --git a/p/themes/Ansum/icons/cog-white.svg b/p/themes/Ansum/icons/cog-white.svg new file mode 100644 index 000000000..3df8c2d70 --- /dev/null +++ b/p/themes/Ansum/icons/cog-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/cog.svg b/p/themes/Ansum/icons/cog.svg new file mode 100644 index 000000000..aa56d862b --- /dev/null +++ b/p/themes/Ansum/icons/cog.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/down-white.svg b/p/themes/Ansum/icons/down-white.svg new file mode 100644 index 000000000..df05a4704 --- /dev/null +++ b/p/themes/Ansum/icons/down-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/down.svg b/p/themes/Ansum/icons/down.svg new file mode 100644 index 000000000..5c732e199 --- /dev/null +++ b/p/themes/Ansum/icons/down.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/icon.svg b/p/themes/Ansum/icons/icon.svg new file mode 100644 index 000000000..7900c0a79 --- /dev/null +++ b/p/themes/Ansum/icons/icon.svg @@ -0,0 +1,75 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/link-white.svg b/p/themes/Ansum/icons/link-white.svg new file mode 100644 index 000000000..c6baadc85 --- /dev/null +++ b/p/themes/Ansum/icons/link-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/p/themes/Ansum/icons/link.svg b/p/themes/Ansum/icons/link.svg new file mode 100644 index 000000000..44ee847b0 --- /dev/null +++ b/p/themes/Ansum/icons/link.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/magnifier.svg b/p/themes/Ansum/icons/magnifier.svg new file mode 100644 index 000000000..ae3732c69 --- /dev/null +++ b/p/themes/Ansum/icons/magnifier.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/more.svg b/p/themes/Ansum/icons/more.svg new file mode 100644 index 000000000..6e505e71b --- /dev/null +++ b/p/themes/Ansum/icons/more.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/non-starred-white.svg b/p/themes/Ansum/icons/non-starred-white.svg new file mode 100644 index 000000000..9bd48c801 --- /dev/null +++ b/p/themes/Ansum/icons/non-starred-white.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/non-starred.svg b/p/themes/Ansum/icons/non-starred.svg new file mode 100644 index 000000000..9d49930c0 --- /dev/null +++ b/p/themes/Ansum/icons/non-starred.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/read-grey.svg b/p/themes/Ansum/icons/read-grey.svg new file mode 100644 index 000000000..4857aca02 --- /dev/null +++ b/p/themes/Ansum/icons/read-grey.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/read-white.svg b/p/themes/Ansum/icons/read-white.svg new file mode 100644 index 000000000..578facdc7 --- /dev/null +++ b/p/themes/Ansum/icons/read-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/read.svg b/p/themes/Ansum/icons/read.svg new file mode 100644 index 000000000..d583cce03 --- /dev/null +++ b/p/themes/Ansum/icons/read.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/refresh.svg b/p/themes/Ansum/icons/refresh.svg new file mode 100644 index 000000000..f23fbf4a2 --- /dev/null +++ b/p/themes/Ansum/icons/refresh.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/rss-white.svg b/p/themes/Ansum/icons/rss-white.svg new file mode 100644 index 000000000..b7fbf9987 --- /dev/null +++ b/p/themes/Ansum/icons/rss-white.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/rss.svg b/p/themes/Ansum/icons/rss.svg new file mode 100644 index 000000000..7044bbaa4 --- /dev/null +++ b/p/themes/Ansum/icons/rss.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/starred-white.svg b/p/themes/Ansum/icons/starred-white.svg new file mode 100644 index 000000000..896dd1eeb --- /dev/null +++ b/p/themes/Ansum/icons/starred-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/starred.svg b/p/themes/Ansum/icons/starred.svg new file mode 100644 index 000000000..3b0bf8cb8 --- /dev/null +++ b/p/themes/Ansum/icons/starred.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/tick-color.svg b/p/themes/Ansum/icons/tick-color.svg new file mode 100644 index 000000000..fe0c28a84 --- /dev/null +++ b/p/themes/Ansum/icons/tick-color.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/p/themes/Ansum/icons/tick-white.svg b/p/themes/Ansum/icons/tick-white.svg new file mode 100644 index 000000000..0bcc26f47 --- /dev/null +++ b/p/themes/Ansum/icons/tick-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/tick.svg b/p/themes/Ansum/icons/tick.svg new file mode 100644 index 000000000..9c436e7a0 --- /dev/null +++ b/p/themes/Ansum/icons/tick.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/unread-grey.svg b/p/themes/Ansum/icons/unread-grey.svg new file mode 100644 index 000000000..1981cf92c --- /dev/null +++ b/p/themes/Ansum/icons/unread-grey.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/unread-white.svg b/p/themes/Ansum/icons/unread-white.svg new file mode 100644 index 000000000..6623924ab --- /dev/null +++ b/p/themes/Ansum/icons/unread-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/unread.svg b/p/themes/Ansum/icons/unread.svg new file mode 100644 index 000000000..5c6c3ac8e --- /dev/null +++ b/p/themes/Ansum/icons/unread.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/up-white.svg b/p/themes/Ansum/icons/up-white.svg new file mode 100644 index 000000000..e19d1e1d9 --- /dev/null +++ b/p/themes/Ansum/icons/up-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/up.svg b/p/themes/Ansum/icons/up.svg new file mode 100644 index 000000000..306b076e9 --- /dev/null +++ b/p/themes/Ansum/icons/up.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/view-global-white.svg b/p/themes/Ansum/icons/view-global-white.svg new file mode 100644 index 000000000..950267f6a --- /dev/null +++ b/p/themes/Ansum/icons/view-global-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/view-global.svg b/p/themes/Ansum/icons/view-global.svg new file mode 100644 index 000000000..08632a190 --- /dev/null +++ b/p/themes/Ansum/icons/view-global.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/view-list-white.svg b/p/themes/Ansum/icons/view-list-white.svg new file mode 100644 index 000000000..c76fc298b --- /dev/null +++ b/p/themes/Ansum/icons/view-list-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Ansum/icons/view-list.svg b/p/themes/Ansum/icons/view-list.svg new file mode 100644 index 000000000..bcea01055 --- /dev/null +++ b/p/themes/Ansum/icons/view-list.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/view-reader-white.svg b/p/themes/Ansum/icons/view-reader-white.svg new file mode 100644 index 000000000..70175c623 --- /dev/null +++ b/p/themes/Ansum/icons/view-reader-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/icons/view-reader.svg b/p/themes/Ansum/icons/view-reader.svg new file mode 100644 index 000000000..7471037d9 --- /dev/null +++ b/p/themes/Ansum/icons/view-reader.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Ansum/loader.gif b/p/themes/Ansum/loader.gif new file mode 100644 index 000000000..ce36565b3 Binary files /dev/null and b/p/themes/Ansum/loader.gif differ diff --git a/p/themes/Ansum/metadata.json b/p/themes/Ansum/metadata.json new file mode 100644 index 000000000..c76c3fa9c --- /dev/null +++ b/p/themes/Ansum/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Ansum", + "author": "Thomas Guesnon", + "description": "Thème sablonneux", + "version": 0.1, + "files": ["_template.css", "ansum.css"] +} diff --git a/p/themes/Ansum/sass.sh b/p/themes/Ansum/sass.sh new file mode 100644 index 000000000..a653acace --- /dev/null +++ b/p/themes/Ansum/sass.sh @@ -0,0 +1 @@ +sass --watch ansum.scss:ansum.css diff --git a/p/themes/Ansum/thumbs/original.png b/p/themes/Ansum/thumbs/original.png new file mode 100644 index 000000000..6351ee51e Binary files /dev/null and b/p/themes/Ansum/thumbs/original.png differ diff --git a/p/themes/Mapco/_components.scss b/p/themes/Mapco/_components.scss new file mode 100644 index 000000000..cf8cb5e91 --- /dev/null +++ b/p/themes/Mapco/_components.scss @@ -0,0 +1,352 @@ +/*=== COMPONENTS */ +/*===============*/ +/*=== Forms */ +// parti dans _forms.scss + +/*=== Horizontal-list */ +.horizontal-list { + margin: 0; + padding: 0.1rem 0; + + .item{ + vertical-align: middle; + + &:first-child{ + padding-left: 0.5rem; + } + + } +} + +/*=== Dropdown */ +.dropdown-menu { + background: $grey-lighter; + margin: 0; + font-size: 1rem; + text-align: left; + padding: 0.5rem 0 1rem 0; + border: none; + border-radius: 3px; + + -webkit-box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + -moz-box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + + &::after { + content: ""; + position: absolute; + top: -4px; + right: 13px; + width: 10px; + height: 10px; + z-index: -10; + transform: rotate(45deg); + -moz-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + background: white; + // border-top: 1px solid #95a5a6; + // border-left: 1px solid #95a5a6; + } + + .dropdown-header { + // padding: 0 5px 5px; + margin: 1.75rem 0 0.5rem 2rem; + font-weight: bold; + text-align: left; + color: $grey-dark; + text-transform: uppercase; + letter-spacing: 1px; + + + } + + .item{ + @include transition(all, 0.075s, ease-in-out); + a, span, .as-link{ + padding: 0 2rem; + line-height: 2.5em; + font-size: 1rem; + color: $main-font-color; + } + &:hover{ + background: $main-first; + color: $white; + + a, button{ + text-decoration: none; + color: $white; + } + } + &[aria-checked="true"]{ + a::before{ + font-weight: bold; + margin: 0 0 0 -14px; + } + } + } + .input{ + select, input{ + margin: 0 auto 5px; + padding: 2px 5px; + border-radius: 3px; + } + } + .separator { + margin: 0.75rem 0; + border-bottom: 1px solid $grey-light; + // display: none; + } + +} +.tree .tree-folder .tree-folder-items .dropdown-menu, +.tree .tree-folder .tree-folder-items .dropdown-menu{ + // tout ça sert à restaurer l'apparence du dropdown dans un contexte de sidebar sombre + + .item{ + padding: 0; + + a, + button{ + color: $main-font-color; + + &:hover{ + color: $white; + } + } + &:hover{ + background: $main-first; + } + } +} + + + + +/*=== Alerts */ +.alert { + margin: 1rem 0; + // width: 100%; + padding: 1rem; + font-size: 1rem; + background: $grey-lighter; + border: 1px solid $grey-medium; + border-radius: 3px; + color: $grey-dark; + text-shadow: 0 0 1px $grey-light; +} +.alert-head { + font-size: 1.15em; +} +.alert > a { + text-decoration: underline; + color: inherit; +} +.alert-warn { + background: $warning-light; + border: 1px solid unquote($warning-text+'33'); // on ajoute l'opacité à la fin + color: $warning-text; +} +.alert-success { + background: $success-light; + border: 1px solid unquote($success-text+'33'); + color: $success-text; +} +.alert-error { + background: $alert-light; + border: 1px solid unquote($alert-text+'33'); + color: $alert-text; +} + +/*=== Pagination */ +.pagination { + text-align: center; + font-size: 0.8em; + background: $grey-light; + color: $main-font-color; + + .item{ + &.pager-current { + font-weight: bold; + font-size: 1.5em; + background: $sid-bg; + color: $grey-light; + } + a { + display: block; + font-style: italic; + line-height: 3em; + text-decoration: none; + color: $main-font-color; + + &:hover{ + background: $main-font-color; + color: $grey-light; + } + } + } + + .loading, + a:hover.loading { + font-size: 0; + background: url("loader.gif") center center no-repeat #34495e; + } +} +.content .pagination { + margin: 0; + padding: 0; +} + + +/*=== Boxes */ +.box { + // border: 1px solid #ddd; + border: none; + border-radius: 3px; + background: $white; + + -webkit-box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.25); + -moz-box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.25); + box-shadow: 0px 2px 2px 0px rgba(0,0,0,0.25); + + .box-title { + margin: 0; + padding: 5px 10px; + background: $grey-light; + color: $main-font-color; + // border-bottom: 1px solid #ddd; + border-radius: 2px 2px 0 0; + + form{ + input{ + width: 85%; + } + .dropdown{ + float: right; + a.dropdown-toggle{ + padding: 0; + background-image: url(icons/more.svg); + background-repeat: no-repeat; + background-position: right 8px; + // float: right; + border-radius: 0; + img{ + display: none; + } + } + } + } + } + .box-content { + // max-height: 260px; + + .item { + padding: 0.5rem 0.75rem; + font-size: 1rem; + color: $main-font-color; + line-height: 1.7em; + border-bottom: 1px solid $grey-light; + + img{ + margin-right: 0.75rem; + } + + .configure { + visibility: hidden; + width: 1.75rem; + height: 1.75rem; + display: block; + border-radius: 2px; + float: left; + margin-right: 0.5rem; + background: url("icons/cog.svg") no-repeat 4px 4px; + + .icon { + vertical-align: middle; + border-radius: 3px; + display: none; + } + &:hover{ + // background: $main-first; + background: url("icons/cog-white.svg") no-repeat 4px 4px $main-first; + } + } + &:hover .configure { + visibility: visible; + } + } + .item:last-child{ + border-bottom: none; + } + } +} + +/*=== "Load more" part */ +#bigMarkAsRead { + text-align: center; + text-decoration: none; + background: $main-first-light; + color: $main-first; + + @include transition(all, 0.15s, ease-in-out); + + &:hover { + background: $main-first; + color: #fff; + + .bigTick{ + background: url(icons/tick-white.svg) center no-repeat; + } + } + .bigTick{ + margin: 0.5rem 0; + display: inline-block; + text-indent: -9999px; + background: url(icons/tick-color.svg) center no-repeat; + height: 64px; + width: 64px; + white-space: nowrap; + } +} + +// page de login +.formLogin{ + background: $sid-bg; + + .header{ + .configure{ + padding-right: 1rem; + img{ + margin-right: 0.5rem; + } + + a.signin{ + color: $white; + } + } + } + + h1{ + color: $white; + } + form#crypto-form{ + div{ + margin-bottom: 1rem; + + label{ + font-size: 1rem; + color: $grey-medium; + + + } + input{ + background: $main-first-darker; + + &:focus{ + background: $grey-lighter; + color: $main-font-color; + } + } + } + } +} diff --git a/p/themes/Mapco/_configuration.scss b/p/themes/Mapco/_configuration.scss new file mode 100644 index 000000000..c3c6fd417 --- /dev/null +++ b/p/themes/Mapco/_configuration.scss @@ -0,0 +1,90 @@ +/*=== Configuration pages */ +.post { + padding: 1rem 2rem; + font-size: 1rem; + + form { + margin: 1rem 0; + + // Gestion des extensions + .horizontal-list{ + margin-bottom: 0.5rem; + + .item{ + .stick{ + // width: 65%; + // margin-right: 1rem; + // display:flex; + + } + .btn{ + // width: 8rem; + // flex-grow: 1; + } + } + + } + } + &.content { + max-width: 550px; + } + + h1, h2{ // pages titles + font-size: 3rem; + margin-top: 1.75rem; + font-weight: 300; + line-height: 1.2em; + // font-family: "spectral"; + color: $main-font-color; + } + + a[href="./"]{ // C'est le bouton "Retour à vos flux" + display: inline-block; + // min-height: 38px; + min-width: 15px; + line-height: 25px; + margin: 0; + padding: 0.75rem 1.5rem; + font-size: 1rem; + vertical-align: middle; + cursor: pointer; + overflow: hidden; + background: $grey-lighter; + border: 1px solid $grey-medium-light; + border-radius: 5px; + // border: none; + color: $grey-dark; + + &:hover{ + text-decoration: none; + background: $main-first; + color: white; + border: 1px solid $main-first; + } + } + +} + + + +#slider{ + border-left: none; + + -webkit-box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + -moz-box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); + box-shadow: 0px 6px 8px 0px rgba(0,0,0,0.35); +} + +.slide-container{ + .properties{ + background: rgba(0, 0, 0, 0.75); + border: 0; + padding: 1rem; + color: white; + + .page-number{ + right: 1rem; + top: 1rem; + } + } +} diff --git a/p/themes/Mapco/_divers.scss b/p/themes/Mapco/_divers.scss new file mode 100644 index 000000000..7d122f1b4 --- /dev/null +++ b/p/themes/Mapco/_divers.scss @@ -0,0 +1,12 @@ +/*=== DIVERS */ +/*===========*/ +.aside.aside_feed .nav-form input, +.aside.aside_feed .nav-form select { + width: 140px; +} +.aside.aside_feed .nav-form .dropdown .dropdown-menu { + right: -20px; +} +.aside.aside_feed .nav-form .dropdown .dropdown-menu::after { + right: 33px; +} diff --git a/p/themes/Mapco/_fonts.scss b/p/themes/Mapco/_fonts.scss new file mode 100644 index 000000000..5891be834 --- /dev/null +++ b/p/themes/Mapco/_fonts.scss @@ -0,0 +1,56 @@ +@font-face { + font-family: "lato"; + font-style: normal; + font-stretch: normal; + font-weight: 400; + src: local("Lato"), url("../fonts/LatoLatin-Regular.woff") format("woff"); +} +@font-face { + font-family: "lato"; + font-style: italic; + font-stretch: normal; + font-weight: 400; + src: local("Lato"), url("../fonts/LatoLatin-Italic.woff") format("woff"); +} +@font-face { + font-family: "lato"; + font-style: normal; + font-stretch: normal; + font-weight: 700; + src: local("Lato"), url("../fonts/LatoLatin-Bold.woff") format("woff"); +} +@font-face { + font-family: "lato"; + font-style: italic; + font-stretch: normal; + font-weight: 700; + src: local("Lato"), url("../fonts/LatoLatin-BoldItalic.woff") format("woff"); +} +@font-face { + font-family: "spectral"; + font-style: normal; + font-stretch: normal; + font-weight: 400; + src: local("Spectral"), url("../fonts/Spectral-Regular.woff") format("woff"); +} +@font-face { + font-family: "spectral"; + font-style: italic; + font-stretch: normal; + font-weight: 400; + src: local("Spectral"), url("../fonts/Spectral-Italic.woff") format("woff"); +} +@font-face { + font-family: "spectral"; + font-style: normal; + font-stretch: normal; + font-weight: 700; + src: local("Spectral"), url("../fonts/Spectral-Bold.woff") format("woff"); +} +@font-face { + font-family: "spectral"; + font-style: italic; + font-stretch: normal; + font-weight: 700; + src: local("Spectral"), url("../fonts/Spectral-BoldItalic.woff") format("woff"); +} diff --git a/p/themes/Mapco/_forms.scss b/p/themes/Mapco/_forms.scss new file mode 100644 index 000000000..8a388aa8a --- /dev/null +++ b/p/themes/Mapco/_forms.scss @@ -0,0 +1,153 @@ +/* btns */ + +.btn { + display: inline-block; + min-height: 38px; + min-width: 15px; + line-height: 25px; + margin: 0; + padding: 0.5rem 1.5rem; + font-size: 1rem; + vertical-align: middle; + cursor: pointer; + overflow: hidden; + background: $grey-lighter; + border-radius: 5px; + border: none; + color: $grey-dark; + + @include transition(all, 0.15s, ease-in-out); + + &.btn-important { + background: $main-first; + color: $white; + + // @include transition(all, 0.15s, ease-in-out); + + &:hover, + &:active { + background: $main-first-alt; + } + } + + + &.btn-attention { + background: $alert-bg; + color: #fff; + + &:hover, + &:active { + background: $alert-text; + } + } + + &:hover { + text-decoration: none; + } +} + +a.btn { + min-height: 25px; + line-height: 25px; +} + +/*=== Forms */ +legend { + display: inline-block; + width: auto; + margin: 2rem 0 1rem 0; + padding: 0; + font-size: 1rem; + clear: both; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 700; +} +label { + min-height: 25px; + padding: 5px 0; + cursor: pointer; + color: $grey-dark; +} +textarea { + width: 360px; + height: 100px; +} +input, select, textarea, button { + font-family: "lato", "Helvetica", "Arial", sans-serif; + min-height: 25px; + padding: 5px 10px; + line-height: 25px; + vertical-align: middle; + background: $white; + border: 1px solid $grey-light; + font-size: 1rem; + color: $grey-dark; + border-radius: 2px; +} +option { + padding: 0 .5em; +} +input:focus, select:focus, textarea:focus { + color: $main-font-color; + border-color: $main-first; +} +input:invalid, select:invalid { + color: $alert-bg; + border-color: $alert-bg; + box-shadow: none; +} +input:disabled, select:disabled { + background: $grey-light; +} +input.extend { + transition: width 200ms linear; + -moz-transition: width 200ms linear; + -webkit-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; +} + + +.form-group { + padding: 5px; + border-radius: 3px; + + &::after { + content: ""; + display: block; + clear: both; + } + &:hover { + // background: #fff; + // border: 1px solid #eee; + // border-radius: 3px; + // border: 1px solid #eee; + } + .group-name { + padding: 10px 0; + text-align: right; + } + .group-controls { + min-height: 25px; + padding: 5px 0; + } + .group-controls .control { + line-height: 2.0em; + } + table { + margin: 10px 0 0 220px; + } + + &.form-actions { + margin: 15px 0 25px; + padding: 5px 0; + // background: #333; + } + &.form-actions .btn { + margin: 0 0.5rem 0 0; + } +} + + + diff --git a/p/themes/Mapco/_global-view.scss b/p/themes/Mapco/_global-view.scss new file mode 100644 index 000000000..30979bd6c --- /dev/null +++ b/p/themes/Mapco/_global-view.scss @@ -0,0 +1,80 @@ +/*=== GLOBAL VIEW */ +/*================*/ + +#stream{ + .box.category{ + + &:not([data-unread="0"]) .box-title { + // background: #3498db; + } + &:not([data-unread="0"]) .box-title:active { + // background: #2980b9; + } + &:not([data-unread="0"]) .box-title .title { + font-weight: bold; + // color: #fff; + } + + .box-title{ + background: none; + padding: 1.5rem; + + a.title{ + font-weight: normal; + text-decoration: none; + text-align: left; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; + color: $grey-dark; + + &:not([data-unread="0"])::after { + position: absolute; + top: 1.75rem; + right: 0; + line-height: 1.5rem; + background: $grey-light; + border-radius: 12px; + padding: 0 0.75rem; + margin: -0.5rem 1rem 0 0; + text-align: center; + } + &:hover{ + color: $main-first; + } + } + } + + .box-content{ + padding-bottom: 0.5rem; + .item.feed { + // padding: 2px 10px; + font-size: 1rem; + padding: 0.5rem 1.5rem; + + a{ + color: $main-font-color; + font-weight: 400; + + &:hover{ + color: $main-first; + text-decoration: none; + } + } + } + } + } +} + + +// le panel qui apparait en overlay pour afficher les flux +#overlay{ + background: rgba(0, 0, 0, 0.65); +} +#panel{ + top: 3rem; + right: 3rem; + bottom: 3rem; + left: 3rem; + border-radius: 3px; +} diff --git a/p/themes/Mapco/_layout.scss b/p/themes/Mapco/_layout.scss new file mode 100644 index 000000000..b62618d81 --- /dev/null +++ b/p/themes/Mapco/_layout.scss @@ -0,0 +1,462 @@ +/*=== STRUCTURE */ +/*===============*/ +/*=== Header */ +.header { + background: $sid-bg; + padding: 0.5rem 1.35rem; + display: block; + table-layout: none; + width: auto; + + .item{ + vertical-align: middle; + // text-align: center; + // display: flex; + // justify-content: space-between; + // flex-direction: row; + + &.title{ + + font-weight: 400; + width: 280px; + + h1{ + a{ + text-decoration: none; + color: $sid-font-color; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; + + img{ + margin-right: 0.5rem; + + } + } + } + } + &.search{ + // text-align: center; + // width: 50%; + + input{ + width: 230px; + border-radius: 2px 0 0 2px; + background-color: $sid-bg-alt; + color: $sid-font-color; + border: none; + + @include transition(all, 0.15s, ease-in-out); + + &:hover{ + background-color: $sid-bg-dark; + } + + &:focus{ + width: 350px; + + background-color: $white; + color: $grey-dark; + } + } + .btn{ + img{display: none;} + border-radius: 0 2px 2px 0; + + background-color: $main-first; + background-position: center; + background-repeat: no-repeat; + background-image: url(icons/magnifier.svg); + + border-left-width: 0; + + width: 3rem; + min-height: 35px; + + &:hover{ + background-color: $main-first-alt; + } + } + } + &.configure{ + width: 2rem; + position: absolute; + right: 1rem; + top: 1.25rem; + text-align: center; + // float: right; + + .btn{ + img{display: none;} + // border-radius: 0 2px 2px 0; + + background-color: transparent; + background-position: center; + background-repeat: no-repeat; + background-image: url(icons/cog-white.svg); + + padding: 0 0.5rem; + + // border-left-width: 0; + + // width: 3rem; + + &:hover{ + // background-color: $main-first-alt; + } + } + } + } + + +} + +/*=== Body */ +#global { + height: calc(100% - 85px); +} + + + + +/*=== Prompt (centered) */ +.prompt { + text-align: center; +} +.prompt label { + text-align: left; +} +.prompt form { + margin: 10px auto 20px auto; + width: 200px; +} +.prompt input { + margin: 5px auto; + width: 100%; +} +.prompt p { + margin: 20px 0; +} + +/*=== New article notification */ +#new-article { + text-align: center; + font-size: 1rem; + background: $main-first; +} +#new-article:hover { + background: $main-first-alt; +} +#new-article > a { + line-height: 3em; + font-weight: bold; + color: $white; +} +#new-article > a:hover { + text-decoration: none; +} + +/*=== Day indication */ +.day { + padding: 1rem 0 0 1.25rem; + font-weight: 700; + line-height: 3em; + letter-spacing: 1px; + text-transform: uppercase; + font-size: 0.875rem; + color: $light-font-color; + // border-left: 2px solid #ecf0f1; + + .name{ + padding: 0 1rem 0 1rem; + font-size: 0.875rem; + // font-weight: 700; + color: $main-font-color; + position: relative; + left: 0; + + // letter-spacing: 1px; + text-transform: uppercase; + } +} + +/*=== Index menu */ +.nav_menu { + text-align: center; + padding: 5px 0; + + .btn{ + border-left-width: 0; + padding: 0.5rem 1rem; + background-color: $grey-lighter; + background-position: center; + background-repeat: no-repeat; + + &:hover{ + background-color: $grey-light; + } + } + + .stick{ + background: $grey-lighter; + + .btn{ + border-left-width: 0; + padding: 0.5rem 1rem; + background-color: $grey-lighter; + background-position: center; + background-repeat: no-repeat; + @include transition(all, 0.15s, ease-in-out); + + &:hover{ + background-color: $grey-medium-light; + } + + &.active{ + background-color: $main-first; + } + + img.icon{display: none;} // on efface pour afficher nos icones, mouhahaha !! + + + // actions + &#toggle-read{ + background-image: url(icons/read.svg); + } + &#toggle-read.active{ + background-image: url(icons/read-white.svg); + } + + &#toggle-unread{ + background-image: url(icons/unread.svg); + } + &#toggle-unread.active{ + background-image: url(icons/unread-white.svg); + } + + &#toggle-starred{ + background-image: url(icons/starred.svg); + } + &#toggle-starred.active{ + background-image: url(icons/starred-white.svg); + } + + &#toggle-non-starred{ + background-image: url(icons/non-starred.svg); + } + &#toggle-non-starred.active{ + background-image: url(icons/non-starred-white.svg); + } + + // read all + &.read_all{ + background-color: $grey-lighter; + // min-height: 0; + color:$main-font-color; + padding: 5px 16px; + @include transition(all, 0.15s, ease-in-out); + + &:hover{ + background-color: $grey-medium-light; + } + } + + // views + &.view-normal{ + background-image: url(icons/view-list.svg); + } + &.view-normal.active{ + background-image: url(icons/view-list-white.svg); + } + + &.view-global{ + background-image: url(icons/view-global.svg); + } + &.view-global.active{ + background-image: url(icons/view-global-white.svg); + } + + &.view-reader{ + background-image: url(icons/view-reader.svg); + } + &.view-reader.active{ + background-image: url(icons/view-reader-white.svg); + } + + &.view-rss{ + background-image: url(icons/rss.svg); + } + + } + .dropdown { + a.dropdown-toggle{ + border-left-width: 0; + background-image: url(icons/more.svg); + } + } + + &#nav_menu_action{ + + } + &#nav_menu_read_all{ + + } + &#nav_menu_views{ + + } + } +} + + +#dropdown-query ~ .dropdown-menu .dropdown-header .icon { + vertical-align: middle; + background-color: $grey-medium-dark; + border-radius: 3px; +} + + +/*=== Content of feed articles */ +.content, .content.thin { + padding: 20px 10px; + + font-size: 1.125rem; + line-height: 1.8rem; + + h1.title, h1{ + + a{ + color: $main-font-color; + font-family: "spectral"; + font-size: 2rem; + + &:hover{ + color: $main-first; + text-decoration: none; + } + } + } + .author{ + font-size: 1.125rem; + color: $light-font-color; + } + p, ul{ + font-size: 1.125rem; + line-height: 1.8rem; + } + hr{ + } + .content hr { + margin: 30px 10px; + height: 1px; + background: $grey-medium-light; + border: 0; + box-shadow: 0 2px 5px #ccc; + } + + pre { + margin: 10px auto; + padding: 10px 20px; + overflow: auto; + background: $main-first-darker; + color: $white; + font-size: 0.9rem; + border-radius: 3px; + + code { + background: transparent; + color: $white; + border: none; + } + } + code { + padding: 2px 5px; + color: $grey-light; + background: $grey-lighter; + border: 1px solid $grey-light; + border-radius: 3px; + } + + + blockquote { + display: block; + margin: 0; + padding: 5px 20px; + border-top: 1px solid $grey-medium-light; + border-bottom: 1px solid $grey-medium-light; + background: $grey-lighter; + color: $main-font-color; + + p { + margin: 0; + } + } + +} + + +/*=== Notification and actualize notification */ +.notification { + position: fixed; + top: auto; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 3rem; + + padding: 1rem 0; + text-align: center; + // font-weight: bold; + font-size: 1em; + line-height: 3em; + z-index: 10; + vertical-align: middle; + background: $grey-medium-light; + color: $grey-dark; + // border-radius: 3px; + border: none; + + .msg{ + font-size: 1rem; + display: inline-block; + } + + &.good { + background: $success-bg; + color: $white; + } + &.bad { + background: $alert-bg; + color: $white; + } + a.close { + padding: 0 15px; + line-height: 3em; + border-radius: 0 3px 3px 0; + } + + &.good a.close:hover { + background: $success-text; + } + &.bad a.close:hover { + background: $alert-text; + } + + &#actualizeProgress { + line-height: 2em; + + br{ + display: none; + } + } +} + + +/*=== Navigation menu (for articles) */ +#nav_entries { + margin: 0; + text-align: center; + line-height: 3em; + table-layout: fixed; + background: $sid-bg; +} diff --git a/p/themes/Mapco/_list-view.scss b/p/themes/Mapco/_list-view.scss new file mode 100644 index 000000000..69cd8a81d --- /dev/null +++ b/p/themes/Mapco/_list-view.scss @@ -0,0 +1,92 @@ +/*=== Feed articles */ +.flux { + // border-left: 2px solid #ecf0f1; + background: $white; + + @include transition(all, 0.15s, ease-in-out); + + &:hover{ + background: $grey-lighter; + + &:not(.current):hover .item.title { + background: $grey-lighter; + + + } + } + &.current{ + border-left-color: $main-first; + background: $grey-lighter; + } + &.not_read{ + background: $unread-bg; //-------------------- + // border-left-color: #FF5300; + + &:hover{ + background: $unread-bg-light; //-------------------- + } + + &:not(.current):hover .item.title { + background: $unread-bg-light; + + + } + .item.title{ + a{ + color: $unread-font-color; //-------------------- + } + + } + .item.website{ + a{ + color: $unread-font-color; //-------------------- + } + } + .item.date{ + color: unquote($unread-font-color+"99"); //-------------------- + } +} + + &.favorite { + background: $fav-light; + border-left-color: $fav-bg; + + @include transition(all, 0.15s, ease-in-out); + + &:not(.current):hover .item.title { + background: $fav-light; + } + } + + .website{ + a{ + color: $main-font-color; + opacity: 0.75; + } + + .favicon { + padding: 5px; + } + } + .date { + font-size: 0.85rem; + color: $main-font-color; + opacity: 0.75; + } + + .bottom { + font-size: 1rem; + text-align: center; + } +} + +.flux_header { + font-size: 1rem; + cursor: pointer; + border-top: 1px solid $grey-light; + + .title { + font-size: 1rem; + } +} + diff --git a/p/themes/Mapco/_logs.scss b/p/themes/Mapco/_logs.scss new file mode 100644 index 000000000..ae1e24c6c --- /dev/null +++ b/p/themes/Mapco/_logs.scss @@ -0,0 +1,34 @@ +/*=== LOGS */ +/*=========*/ +.loglist { + overflow: hidden; + border: 1px solid $grey-medium-dark; +} +.log { + margin: 10px 0; + padding: 5px 2%; + overflow: auto; + font-size: 0.8rem; + background: $grey-lighter; + color: $grey-dark; +} + +.log > .date { + margin: 0 10px 0 0; + padding: 5px 10px; + border-radius: 20px; +} +.log.error > .date { + background: $alert-bg; + color: #fff; +} +.log.warning > .date { + background: $warning-bg; +} +.log.notice > .date { + background: $grey-light; +} +.log.debug > .date { + background: $main-first-darker; + color: $white; +} diff --git a/p/themes/Mapco/_mixins.scss b/p/themes/Mapco/_mixins.scss new file mode 100644 index 000000000..3542ade6b --- /dev/null +++ b/p/themes/Mapco/_mixins.scss @@ -0,0 +1,59 @@ +/* FUNCTIONS */ + +//animation +@mixin transition($target, $duration, $ease) { + -webkit-transition: $target $duration $ease; + -moz-transition: $target $duration $ease; + -o-transition: $target $duration $ease; + -ms-transition: $target $duration $ease; + transition: $target $duration $ease; +} + +//animation +@mixin animation-delay($delay) { + -webkit-animation-delay: $delay; + /* Safari 4.0 - 8.0 */ + animation-delay: $delay; +} + +//animation +@mixin animation($animate...) { + $max: length($animate); + $animations: ''; + @for $i from 1 through $max { + $animations: #{$animations + nth($animate, $i)}; + @if $i < $max { + $animations: #{$animations + ", "}; + } + } + -webkit-animation: $animations; + -moz-animation: $animations; + -o-animation: $animations; + -ms-transition: $animations; + animation: $animations; +} + +//keyframes +@mixin keyframes($animationName) { + @-webkit-keyframes #{$animationName} { + @content; + } + @-moz-keyframes #{$animationName} { + @content; + } + @-o-keyframes #{$animationName} { + @content; + } + @keyframes #{$animationName} { + @content; + } +} + +@mixin border-radius($radius: 4px){ + -moz-border-radius: $radius; + -webkit-border-radius: $radius; + -ms-border-radius: $radius; + -o-border-radius: $radius; + -khtml-border-radius: $radius; + border-radius: $radius; +} diff --git a/p/themes/Mapco/_mobile.scss b/p/themes/Mapco/_mobile.scss new file mode 100644 index 000000000..dcf4e74f2 --- /dev/null +++ b/p/themes/Mapco/_mobile.scss @@ -0,0 +1,169 @@ +/*=== MOBILE */ +/*===========*/ +@media(max-width: 840px) { + html, body{ + // font-size: 1rem; + } + ul.nav{ + .item{ + width: 100%; + + img{ + display: none; + } + a{ + display: inline-block; + padding: 1rem 1rem 1rem 2.5rem; + color: $sid-font-color; + width: 100%; + + background: url("../../themes/icons/logout.svg") no-repeat $sid-bg-dark 3% center; + + @include transition(all, 0.2s, ease-in-out); + + &:hover, + &:active{ + background: url("../../themes/icons/logout.svg") no-repeat $alert-bg 3% center; + text-decoration: none; + } + } + + } + + } + .aside { + @include transition(all, 0.2s, ease-in-out); + + &.aside_feed { + padding: 0; + } + + .tree .tree-folder .tree-folder-items .item a{ + padding: 0.5rem 1rem; + } + } + .aside .toggle_aside, + #panel .close { + display: block; + width: 100%; + height: 50px; + line-height: 50px; + text-align: center; + background: $main-first-alt; + } + + .header{ + padding: 0.5rem; + .item{ + &.title{ + display: none; + } + + &.search{ + input{ + width: 90%; + height: 3.5rem; + + &:focus{ + width: 100%; + + } + } + .btn{ + min-height: 49px; + padding: 0.5rem 2rem; + } + } + &.configure{ + width: 2.75rem; + top: 3.125rem; + .dropdown{ + .btn{ + padding: 1.125rem; + } + } + } + } + } + + .nav_menu{ + .btn { + margin: 0; + padding: 0.85rem 1.25rem; + } + .stick { + margin: 0.5rem 0.5rem; + + .btn{ + margin: 0; + padding: 0.85rem 1.25rem; + + &.read_all{ + padding: 0.85rem 1.25rem; + } + } + } + .search { + display: none; + max-width: 97%; + + .input{ + + max-width: 97%; + width: 90px; + + &::focus{ + width: 400px; + } + } + } + } + #stream{ + .flux{ + .flux_header{ + padding: 0.5rem 0; + } + } + } + + + + .day{ + text-align: center; + padding: 1rem 0; + .name { + // font-size: 1.1rem; + display: block; + padding: 0; + width: 100%; + line-height: 1.5rem; + margin-bottom: 1rem; + } + + } + + .pagination { + margin: 0 0 3.5em; + } + + #nav_entries{ + line-height: 4.5rem; + } + + .notification { + border-radius: 0; + + a.close { + display: block; + left: 0; + background: transparent; + } + a.close:hover { + opacity: 0.5; + } + a.close .icon { + display: none; + + } + } +} diff --git a/p/themes/Mapco/_reader-view.scss b/p/themes/Mapco/_reader-view.scss new file mode 100644 index 000000000..4368908d6 --- /dev/null +++ b/p/themes/Mapco/_reader-view.scss @@ -0,0 +1,13 @@ +/*=== READER VIEW */ +/*================*/ +#stream.reader .flux { + padding: 0 0 50px; + background: $grey-light; + color: $main-font-color; + border: none; +} +#stream.reader .flux .author { + margin: 0 0 10px; + font-size: 90%; + color: $grey-medium-dark; +} diff --git a/p/themes/Mapco/_sidebar.scss b/p/themes/Mapco/_sidebar.scss new file mode 100644 index 000000000..62ec1c1cf --- /dev/null +++ b/p/themes/Mapco/_sidebar.scss @@ -0,0 +1,291 @@ +/*=== Tree */ +.tree { + margin: 10px 0; + + &#sidebar{ + scrollbar-color: rgba(255,255, 0, 0.1) rgba(0, 0, 0, 0.05); + scrollbar-color: unquote($sid-font-color+"33") unquote($sid-font-color+"22"); + } + + + .tree-folder{ + border-bottom: 1px solid $sid-sep; + + .tree-folder-title { + position: relative; + background: $sid-bg; + font-size: 0.85rem; + letter-spacing: 1px; + padding: 12px 16px; + font-weight: 700; + text-transform: uppercase; + + .title { + background: inherit; + color: $sid-font-color; + &:hover{ + text-decoration: none; + } + } + } + &.active { + .tree-folder-title { + background: $sid-bg; + font-weight: bold; + } + } + .tree-folder-items { + background: $sid-bg-alt; + + .item{ + padding: 0 1rem; + line-height: 2.5rem; + font-size: 1rem; + font-weight: 400; + @include transition(all, 0.15s, ease-in-out); + + &.active{ + background: $sid-active; + + .dropdown li a{ + color: $main-font-color; + + &:hover{ + color: $sid-font-color; + } + } + + a{ + color: $sid-active-font; + } + } + + &:hover{ + background: $sid-bg-dark; + } + + a{ + text-decoration: none; + color: $sid-font-color; + } + } + + .feed .item-title:not([data-unread="0"])::before { + content: attr(data-unread); + background: $sid-pills; + font-size: 0.75rem; + display: block; + float: left; + padding: 3px 4px; + text-align:center; + border-radius: 12px; + margin: 11px 6px 0 4px; + line-height: 0.75rem; + } + .feed .item-title:not([data-unread="0"]) { + + } + } + } +} + +/*=== Buttons */ +.stick { + vertical-align: middle; + font-size: 0; + + input, .btn { + border-radius: 0; + } + .btn:first-child, + input:first-child { + border-radius: 5px 0 0 5px; + } + .btn:last-child, input:last-child, .btn + .dropdown > .btn { + border-radius: 0 5px 5px 0; + } + .btn + .btn, + .btn + input, + .btn + .dropdown > .btn, + input + .btn, + input + input, + input + .dropdown > .btn, + .dropdown + .btn, + .dropdown + input, + .dropdown + .dropdown > .btn { + border-left: 1px solid $grey-medium-light; + } + +} + +.aside { + background: $sid-bg; + + &.aside_feed { + padding: 10px 0; + text-align: center; + background: $sid-bg; + } + &.aside_feed .tree { + margin: 10px 0 50px; + } + +} + + +/* Sidebar des pages de configuration */ + + + +/*=== Navigation */ + +.nav-list{ + .nav-header, + .item{ + height: 2.5em; + line-height: 2.5em; + font-size: 1rem; + } + .item{ + background: $sid-bg; + @include transition(all, 0.15s, ease-in-out); + a{ + padding: 0 1rem; + color: $sid-font-color; + } + .error{ + a{ + color: $alert-bg; + } + } + &:hover{ + background: $sid-bg-dark; + color: $sid-font-color; + + .error{ + a{ + color: $sid-font-color; + background: $main-first; + } + } + .empty{ + a{ + color: $sid-font-color; + background: $warning-bg; + } + } + + a{ + color: $sid-font-color; + text-decoration: none; + } + } + &.active{ + background: $main-first; + color: $white; + + .error{ + a{ + color: $white; + background: $main-first; + } + } + + .empty{ + a{ + color: $white; + background: $warning-bg; + } + } + + a{ + color: $white; + text-decoration: none; + } + } + + } + &.empty{ + a{ + color: $warning-bg; + } + } + .disable{ + text-align: center; + background: $grey-lighter; + color: $grey-medium-dark; + } + + .nav-header { + padding: 0 10px; + font-weight: bold; + color: $grey-dark; + text-transform: uppercase; + letter-spacing: 1px; + margin-top: 1rem; + } + + .nav-form { + padding: 3px; + text-align: center; + } + + .nav-head { + margin: 0; + text-align: right; + // background: #34495e; + color: $white; + a { + color: $white; + } + .item { + padding: 5px 10px; + font-size: 0.9rem; + line-height: 1.5rem; + } + } +} + +/*=== Aside main page (categories) */ +.aside_feed .tree-folder-title > .title:not([data-unread="0"])::after { + position: absolute; + right: 0; + line-height: 1.5rem; + background: $sid-pills; + border-radius: 12px; + padding: 0 0.75rem; + margin: -0.5rem 1rem 0 0; + text-align: center; +} + +.feed.item.empty.active { + background: $grey-dark; +} +.feed.item.error.active { + background: $grey-dark; +} +.feed.item.empty, +.feed.item.empty > a { + color: $grey-dark; +} +.feed.item.error, +.feed.item.error > a { + color: $grey-dark; +} +.feed.item.empty.active, +.feed.item.error.active, +.feed.item.empty.active > a, +.feed.item.error.active > a { + color: $white; +} +.aside_feed .tree-folder-items .dropdown-menu::after { + left: 2px; +} +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { + border-radius: 3px; +} +.aside_feed .stick #btn-importExport{ + border-left-color: $sid-bg; +} diff --git a/p/themes/Mapco/_stats.scss b/p/themes/Mapco/_stats.scss new file mode 100644 index 000000000..f287efa08 --- /dev/null +++ b/p/themes/Mapco/_stats.scss @@ -0,0 +1,27 @@ +/*=== STATISTICS */ +/*===============*/ +.stat { + margin: 10px 0 20px; +} + +.stat th, +.stat td, +.stat tr { + border: none; +} +.stat > table td, +.stat > table th { + border-bottom: 1px solid $grey-medium-light; +} + +.stat > .horizontal-list { + margin: 0 0 5px; +} +.stat > .horizontal-list .item { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.stat > .horizontal-list .item:first-child { + width: 270px; +} diff --git a/p/themes/Mapco/_tables.scss b/p/themes/Mapco/_tables.scss new file mode 100644 index 000000000..608e19aca --- /dev/null +++ b/p/themes/Mapco/_tables.scss @@ -0,0 +1,17 @@ +/*=== Tables */ +table { + border-collapse: collapse; +} + +tr, th, td { + padding: 0.5em; + border: 1px solid $grey-medium-light; +} +th { + background: $grey-lighter; +} +form td, +form th { + font-weight: normal; + text-align: center; +} diff --git a/p/themes/Mapco/_variables.scss b/p/themes/Mapco/_variables.scss new file mode 100644 index 000000000..b01d9bd67 --- /dev/null +++ b/p/themes/Mapco/_variables.scss @@ -0,0 +1,53 @@ +// La couleur principale du thème +$main-first: #3366cc; // couleur principale +$main-first-alt: #2255cc; // var pour les hovers +$main-first-light: #effcfd; // var light 1 +$main-first-lighter: #f7fdfe; // var light 2 +$main-first-dark: #35363c; // var pour les hovers +$main-first-darker: #1d1e22; // var pour les hovers + +// les couleurs de polices liées +$main-font-color: #303136; +$light-font-color: #5b6871; +$white: #fff; // le blanc (des fois qu'on aurait envie de le teinter un peu) + +// toute la palette des gris, très utile +// on essaiera de teinter ces gris suivant la couleur principale +$grey-darker: #3b3f4d; +$grey-dark: #5b6871; +$grey-medium-dark: #a6a7ae; +$grey-medium: #c5ced3; +$grey-medium-light: #d5d8db; +$grey-light: #eff0f2; +$grey-lighter: #f9fafb; + +$unread-font-color: $main-first; +$unread-bg: #f2f6f8; +$unread-bg-light: #fdfdfe; + +// les couleurs d'alertes (rouge, jaune, vert) +$alert-bg: #f5633e; // la base +$alert-light: #fde0d8; // +light +$alert-text: #73341f; // +foncé + +$warning-bg: #f4f762; +$warning-light: #fdfde0; +$warning-text: #73762f; + +$success-bg: #10f587; +$success-light: #cffde7; +$success-text: #0c7540; + +// les favoris +$fav-bg: #FFC300; +$fav-light: #FFF6DA; + +// la couleur de sidebar, utile si on a envie d'un thème qui aurait une sidebar foncé, e.g. +$sid-font-color: #FFFFFF; // la couleur de fond de la barre de gauche et du header +$sid-bg: #303136; // le background général de la barre de gauche, et du header +$sid-bg-alt: #26272a; // le background de l'intérieur des groupes +$sid-bg-dark: #17181a; // les hovers +$sid-sep: #3f3f3f; // les séparateurs +$sid-active: $main-first; // la couleur active +$sid-active-font: #FFFFFF; // la couleur active +$sid-pills: rgba(0,0,0, 0.25); // les gélules diff --git a/p/themes/Mapco/icons/cog-white.svg b/p/themes/Mapco/icons/cog-white.svg new file mode 100644 index 000000000..3df8c2d70 --- /dev/null +++ b/p/themes/Mapco/icons/cog-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/cog.svg b/p/themes/Mapco/icons/cog.svg new file mode 100644 index 000000000..aa56d862b --- /dev/null +++ b/p/themes/Mapco/icons/cog.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/down-white.svg b/p/themes/Mapco/icons/down-white.svg new file mode 100644 index 000000000..df05a4704 --- /dev/null +++ b/p/themes/Mapco/icons/down-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/down.svg b/p/themes/Mapco/icons/down.svg new file mode 100644 index 000000000..5c732e199 --- /dev/null +++ b/p/themes/Mapco/icons/down.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/icon.svg b/p/themes/Mapco/icons/icon.svg new file mode 100644 index 000000000..594abba59 --- /dev/null +++ b/p/themes/Mapco/icons/icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/link-white.svg b/p/themes/Mapco/icons/link-white.svg new file mode 100644 index 000000000..c6baadc85 --- /dev/null +++ b/p/themes/Mapco/icons/link-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/p/themes/Mapco/icons/link.svg b/p/themes/Mapco/icons/link.svg new file mode 100644 index 000000000..44ee847b0 --- /dev/null +++ b/p/themes/Mapco/icons/link.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/magnifier.svg b/p/themes/Mapco/icons/magnifier.svg new file mode 100644 index 000000000..ae3732c69 --- /dev/null +++ b/p/themes/Mapco/icons/magnifier.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/more.svg b/p/themes/Mapco/icons/more.svg new file mode 100644 index 000000000..6e505e71b --- /dev/null +++ b/p/themes/Mapco/icons/more.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/non-starred-white.svg b/p/themes/Mapco/icons/non-starred-white.svg new file mode 100644 index 000000000..9bd48c801 --- /dev/null +++ b/p/themes/Mapco/icons/non-starred-white.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/non-starred.svg b/p/themes/Mapco/icons/non-starred.svg new file mode 100644 index 000000000..9d49930c0 --- /dev/null +++ b/p/themes/Mapco/icons/non-starred.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/read-grey.svg b/p/themes/Mapco/icons/read-grey.svg new file mode 100644 index 000000000..4857aca02 --- /dev/null +++ b/p/themes/Mapco/icons/read-grey.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/read-white.svg b/p/themes/Mapco/icons/read-white.svg new file mode 100644 index 000000000..578facdc7 --- /dev/null +++ b/p/themes/Mapco/icons/read-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/read.svg b/p/themes/Mapco/icons/read.svg new file mode 100644 index 000000000..d583cce03 --- /dev/null +++ b/p/themes/Mapco/icons/read.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/refresh.svg b/p/themes/Mapco/icons/refresh.svg new file mode 100644 index 000000000..f23fbf4a2 --- /dev/null +++ b/p/themes/Mapco/icons/refresh.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/rss-white.svg b/p/themes/Mapco/icons/rss-white.svg new file mode 100644 index 000000000..b7fbf9987 --- /dev/null +++ b/p/themes/Mapco/icons/rss-white.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/rss.svg b/p/themes/Mapco/icons/rss.svg new file mode 100644 index 000000000..7044bbaa4 --- /dev/null +++ b/p/themes/Mapco/icons/rss.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/starred-white.svg b/p/themes/Mapco/icons/starred-white.svg new file mode 100644 index 000000000..896dd1eeb --- /dev/null +++ b/p/themes/Mapco/icons/starred-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/starred.svg b/p/themes/Mapco/icons/starred.svg new file mode 100644 index 000000000..3b0bf8cb8 --- /dev/null +++ b/p/themes/Mapco/icons/starred.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/tick-color.svg b/p/themes/Mapco/icons/tick-color.svg new file mode 100644 index 000000000..302541e80 --- /dev/null +++ b/p/themes/Mapco/icons/tick-color.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/tick-white.svg b/p/themes/Mapco/icons/tick-white.svg new file mode 100644 index 000000000..0bcc26f47 --- /dev/null +++ b/p/themes/Mapco/icons/tick-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/tick.svg b/p/themes/Mapco/icons/tick.svg new file mode 100644 index 000000000..9c436e7a0 --- /dev/null +++ b/p/themes/Mapco/icons/tick.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/unread-grey.svg b/p/themes/Mapco/icons/unread-grey.svg new file mode 100644 index 000000000..1981cf92c --- /dev/null +++ b/p/themes/Mapco/icons/unread-grey.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/unread-white.svg b/p/themes/Mapco/icons/unread-white.svg new file mode 100644 index 000000000..6623924ab --- /dev/null +++ b/p/themes/Mapco/icons/unread-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/unread.svg b/p/themes/Mapco/icons/unread.svg new file mode 100644 index 000000000..5c6c3ac8e --- /dev/null +++ b/p/themes/Mapco/icons/unread.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/up-white.svg b/p/themes/Mapco/icons/up-white.svg new file mode 100644 index 000000000..e19d1e1d9 --- /dev/null +++ b/p/themes/Mapco/icons/up-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/up.svg b/p/themes/Mapco/icons/up.svg new file mode 100644 index 000000000..306b076e9 --- /dev/null +++ b/p/themes/Mapco/icons/up.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/view-global-white.svg b/p/themes/Mapco/icons/view-global-white.svg new file mode 100644 index 000000000..950267f6a --- /dev/null +++ b/p/themes/Mapco/icons/view-global-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/view-global.svg b/p/themes/Mapco/icons/view-global.svg new file mode 100644 index 000000000..08632a190 --- /dev/null +++ b/p/themes/Mapco/icons/view-global.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/view-list-white.svg b/p/themes/Mapco/icons/view-list-white.svg new file mode 100644 index 000000000..c76fc298b --- /dev/null +++ b/p/themes/Mapco/icons/view-list-white.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/p/themes/Mapco/icons/view-list.svg b/p/themes/Mapco/icons/view-list.svg new file mode 100644 index 000000000..bcea01055 --- /dev/null +++ b/p/themes/Mapco/icons/view-list.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/view-reader-white.svg b/p/themes/Mapco/icons/view-reader-white.svg new file mode 100644 index 000000000..70175c623 --- /dev/null +++ b/p/themes/Mapco/icons/view-reader-white.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/icons/view-reader.svg b/p/themes/Mapco/icons/view-reader.svg new file mode 100644 index 000000000..7471037d9 --- /dev/null +++ b/p/themes/Mapco/icons/view-reader.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/p/themes/Mapco/loader.gif b/p/themes/Mapco/loader.gif new file mode 100644 index 000000000..ce36565b3 Binary files /dev/null and b/p/themes/Mapco/loader.gif differ diff --git a/p/themes/Mapco/mapco.css b/p/themes/Mapco/mapco.css new file mode 100644 index 000000000..90994163e --- /dev/null +++ b/p/themes/Mapco/mapco.css @@ -0,0 +1,1306 @@ +@font-face { + font-family: "lato"; + font-style: normal; + font-stretch: normal; + font-weight: 400; + src: local("Lato"), url("../fonts/LatoLatin-Regular.woff") format("woff"); } +@font-face { + font-family: "lato"; + font-style: italic; + font-stretch: normal; + font-weight: 400; + src: local("Lato"), url("../fonts/LatoLatin-Italic.woff") format("woff"); } +@font-face { + font-family: "lato"; + font-style: normal; + font-stretch: normal; + font-weight: 700; + src: local("Lato"), url("../fonts/LatoLatin-Bold.woff") format("woff"); } +@font-face { + font-family: "lato"; + font-style: italic; + font-stretch: normal; + font-weight: 700; + src: local("Lato"), url("../fonts/LatoLatin-BoldItalic.woff") format("woff"); } +@font-face { + font-family: "spectral"; + font-style: normal; + font-stretch: normal; + font-weight: 400; + src: local("Spectral"), url("../fonts/Spectral-Regular.woff") format("woff"); } +@font-face { + font-family: "spectral"; + font-style: italic; + font-stretch: normal; + font-weight: 400; + src: local("Spectral"), url("../fonts/Spectral-Italic.woff") format("woff"); } +@font-face { + font-family: "spectral"; + font-style: normal; + font-stretch: normal; + font-weight: 700; + src: local("Spectral"), url("../fonts/Spectral-Bold.woff") format("woff"); } +@font-face { + font-family: "spectral"; + font-style: italic; + font-stretch: normal; + font-weight: 700; + src: local("Spectral"), url("../fonts/Spectral-BoldItalic.woff") format("woff"); } +/* FUNCTIONS */ +/* btns */ +.btn { + display: inline-block; + min-height: 38px; + min-width: 15px; + line-height: 25px; + margin: 0; + padding: 0.5rem 1.5rem; + font-size: 1rem; + vertical-align: middle; + cursor: pointer; + overflow: hidden; + background: #f9fafb; + border-radius: 5px; + border: none; + color: #5b6871; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .btn.btn-important { + background: #3366cc; + color: #fff; } + .btn.btn-important:hover, .btn.btn-important:active { + background: #2255cc; } + .btn.btn-attention { + background: #f5633e; + color: #fff; } + .btn.btn-attention:hover, .btn.btn-attention:active { + background: #73341f; } + .btn:hover { + text-decoration: none; } + +a.btn { + min-height: 25px; + line-height: 25px; } + +/*=== Forms */ +legend { + display: inline-block; + width: auto; + margin: 2rem 0 1rem 0; + padding: 0; + font-size: 1rem; + clear: both; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 700; } + +label { + min-height: 25px; + padding: 5px 0; + cursor: pointer; + color: #5b6871; } + +textarea { + width: 360px; + height: 100px; } + +input, select, textarea, button { + font-family: "lato", "Helvetica", "Arial", sans-serif; + min-height: 25px; + padding: 5px 10px; + line-height: 25px; + vertical-align: middle; + background: #fff; + border: 1px solid #eff0f2; + font-size: 1rem; + color: #5b6871; + border-radius: 2px; } + +option { + padding: 0 .5em; } + +input:focus, select:focus, textarea:focus { + color: #303136; + border-color: #3366cc; } + +input:invalid, select:invalid { + color: #f5633e; + border-color: #f5633e; + box-shadow: none; } + +input:disabled, select:disabled { + background: #eff0f2; } + +input.extend { + transition: width 200ms linear; + -moz-transition: width 200ms linear; + -webkit-transition: width 200ms linear; + -o-transition: width 200ms linear; + -ms-transition: width 200ms linear; } + +.form-group { + padding: 5px; + border-radius: 3px; } + .form-group::after { + content: ""; + display: block; + clear: both; } + .form-group .group-name { + padding: 10px 0; + text-align: right; } + .form-group .group-controls { + min-height: 25px; + padding: 5px 0; } + .form-group .group-controls .control { + line-height: 2.0em; } + .form-group table { + margin: 10px 0 0 220px; } + .form-group.form-actions { + margin: 15px 0 25px; + padding: 5px 0; } + .form-group.form-actions .btn { + margin: 0 0.5rem 0 0; } + +/*=== Tables */ +table { + border-collapse: collapse; } + +tr, th, td { + padding: 0.5em; + border: 1px solid #d5d8db; } + +th { + background: #f9fafb; } + +form td, +form th { + font-weight: normal; + text-align: center; } + +/*=== COMPONENTS */ +/*===============*/ +/*=== Forms */ +/*=== Horizontal-list */ +.horizontal-list { + margin: 0; + padding: 0.1rem 0; } + .horizontal-list .item { + vertical-align: middle; } + .horizontal-list .item:first-child { + padding-left: 0.5rem; } + +/*=== Dropdown */ +.dropdown-menu { + background: #f9fafb; + margin: 0; + font-size: 1rem; + text-align: left; + padding: 0.5rem 0 1rem 0; + border: none; + border-radius: 3px; + -webkit-box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); + -moz-box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); + box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); } + .dropdown-menu::after { + content: ""; + position: absolute; + top: -4px; + right: 13px; + width: 10px; + height: 10px; + z-index: -10; + transform: rotate(45deg); + -moz-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + background: white; } + .dropdown-menu .dropdown-header { + margin: 1.75rem 0 0.5rem 2rem; + font-weight: bold; + text-align: left; + color: #5b6871; + text-transform: uppercase; + letter-spacing: 1px; } + .dropdown-menu .item { + -webkit-transition: all 0.075s ease-in-out; + -moz-transition: all 0.075s ease-in-out; + -o-transition: all 0.075s ease-in-out; + -ms-transition: all 0.075s ease-in-out; + transition: all 0.075s ease-in-out; } + .dropdown-menu .item a, .dropdown-menu .item span, .dropdown-menu .item .as-link { + padding: 0 2rem; + line-height: 2.5em; + font-size: 1rem; + color: #303136; } + .dropdown-menu .item:hover { + background: #3366cc; + color: #fff; } + .dropdown-menu .item:hover a, .dropdown-menu .item:hover button { + text-decoration: none; + color: #fff; } + .dropdown-menu .item[aria-checked="true"] a::before { + font-weight: bold; + margin: 0 0 0 -14px; } + .dropdown-menu .input select, .dropdown-menu .input input { + margin: 0 auto 5px; + padding: 2px 5px; + border-radius: 3px; } + .dropdown-menu .separator { + margin: 0.75rem 0; + border-bottom: 1px solid #eff0f2; } + +.tree .tree-folder .tree-folder-items .dropdown-menu .item, +.tree .tree-folder .tree-folder-items .dropdown-menu .item { + padding: 0; } + .tree .tree-folder .tree-folder-items .dropdown-menu .item a, + .tree .tree-folder .tree-folder-items .dropdown-menu .item button, + .tree .tree-folder .tree-folder-items .dropdown-menu .item a, + .tree .tree-folder .tree-folder-items .dropdown-menu .item button { + color: #303136; } + .tree .tree-folder .tree-folder-items .dropdown-menu .item a:hover, + .tree .tree-folder .tree-folder-items .dropdown-menu .item button:hover, + .tree .tree-folder .tree-folder-items .dropdown-menu .item a:hover, + .tree .tree-folder .tree-folder-items .dropdown-menu .item button:hover { + color: #fff; } + .tree .tree-folder .tree-folder-items .dropdown-menu .item:hover, + .tree .tree-folder .tree-folder-items .dropdown-menu .item:hover { + background: #3366cc; } + +/*=== Alerts */ +.alert { + margin: 1rem 0; + padding: 1rem; + font-size: 1rem; + background: #f9fafb; + border: 1px solid #c5ced3; + border-radius: 3px; + color: #5b6871; + text-shadow: 0 0 1px #eff0f2; } + +.alert-head { + font-size: 1.15em; } + +.alert > a { + text-decoration: underline; + color: inherit; } + +.alert-warn { + background: #fdfde0; + border: 1px solid #73762f33; + color: #73762f; } + +.alert-success { + background: #cffde7; + border: 1px solid #0c754033; + color: #0c7540; } + +.alert-error { + background: #fde0d8; + border: 1px solid #73341f33; + color: #73341f; } + +/*=== Pagination */ +.pagination { + text-align: center; + font-size: 0.8em; + background: #eff0f2; + color: #303136; } + .pagination .item.pager-current { + font-weight: bold; + font-size: 1.5em; + background: #303136; + color: #eff0f2; } + .pagination .item a { + display: block; + font-style: italic; + line-height: 3em; + text-decoration: none; + color: #303136; } + .pagination .item a:hover { + background: #303136; + color: #eff0f2; } + .pagination .loading, + .pagination a:hover.loading { + font-size: 0; + background: url("loader.gif") center center no-repeat #34495e; } + +.content .pagination { + margin: 0; + padding: 0; } + +/*=== Boxes */ +.box { + border: none; + border-radius: 3px; + background: #fff; + -webkit-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.25); + box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.25); } + .box .box-title { + margin: 0; + padding: 5px 10px; + background: #eff0f2; + color: #303136; + border-radius: 2px 2px 0 0; } + .box .box-title form input { + width: 85%; } + .box .box-title form .dropdown { + float: right; } + .box .box-title form .dropdown a.dropdown-toggle { + padding: 0; + background-image: url(icons/more.svg); + background-repeat: no-repeat; + background-position: right 8px; + border-radius: 0; } + .box .box-title form .dropdown a.dropdown-toggle img { + display: none; } + .box .box-content .item { + padding: 0.5rem 0.75rem; + font-size: 1rem; + color: #303136; + line-height: 1.7em; + border-bottom: 1px solid #eff0f2; } + .box .box-content .item img { + margin-right: 0.75rem; } + .box .box-content .item .configure { + visibility: hidden; + width: 1.75rem; + height: 1.75rem; + display: block; + border-radius: 2px; + float: left; + margin-right: 0.5rem; + background: url("icons/cog.svg") no-repeat 4px 4px; } + .box .box-content .item .configure .icon { + vertical-align: middle; + border-radius: 3px; + display: none; } + .box .box-content .item .configure:hover { + background: url("icons/cog-white.svg") no-repeat 4px 4px #3366cc; } + .box .box-content .item:hover .configure { + visibility: visible; } + .box .box-content .item:last-child { + border-bottom: none; } + +/*=== "Load more" part */ +#bigMarkAsRead { + text-align: center; + text-decoration: none; + background: #effcfd; + color: #3366cc; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + #bigMarkAsRead:hover { + background: #3366cc; + color: #fff; } + #bigMarkAsRead:hover .bigTick { + background: url(icons/tick-white.svg) center no-repeat; } + #bigMarkAsRead .bigTick { + margin: 0.5rem 0; + display: inline-block; + text-indent: -9999px; + background: url(icons/tick-color.svg) center no-repeat; + height: 64px; + width: 64px; + white-space: nowrap; } + +.formLogin { + background: #303136; } + .formLogin .header .configure { + padding-right: 1rem; } + .formLogin .header .configure img { + margin-right: 0.5rem; } + .formLogin .header .configure a.signin { + color: #fff; } + .formLogin h1 { + color: #fff; } + .formLogin form#crypto-form div { + margin-bottom: 1rem; } + .formLogin form#crypto-form div label { + font-size: 1rem; + color: #c5ced3; } + .formLogin form#crypto-form div input { + background: #1d1e22; } + .formLogin form#crypto-form div input:focus { + background: #f9fafb; + color: #303136; } + +/*=== DIVERS */ +/*===========*/ +.aside.aside_feed .nav-form input, +.aside.aside_feed .nav-form select { + width: 140px; } + +.aside.aside_feed .nav-form .dropdown .dropdown-menu { + right: -20px; } + +.aside.aside_feed .nav-form .dropdown .dropdown-menu::after { + right: 33px; } + +/*=== Tree */ +.tree { + margin: 10px 0; } + .tree#sidebar { + scrollbar-color: rgba(255, 255, 0, 0.1) rgba(0, 0, 0, 0.05); + scrollbar-color: #FFFFFF33 #FFFFFF22; } + .tree .tree-folder { + border-bottom: 1px solid #3f3f3f; } + .tree .tree-folder .tree-folder-title { + position: relative; + background: #303136; + font-size: 0.85rem; + letter-spacing: 1px; + padding: 12px 16px; + font-weight: 700; + text-transform: uppercase; } + .tree .tree-folder .tree-folder-title .title { + background: inherit; + color: #FFFFFF; } + .tree .tree-folder .tree-folder-title .title:hover { + text-decoration: none; } + .tree .tree-folder.active .tree-folder-title { + background: #303136; + font-weight: bold; } + .tree .tree-folder .tree-folder-items { + background: #26272a; } + .tree .tree-folder .tree-folder-items .item { + padding: 0 1rem; + line-height: 2.5rem; + font-size: 1rem; + font-weight: 400; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .tree .tree-folder .tree-folder-items .item.active { + background: #3366cc; } + .tree .tree-folder .tree-folder-items .item.active .dropdown li a { + color: #303136; } + .tree .tree-folder .tree-folder-items .item.active .dropdown li a:hover { + color: #FFFFFF; } + .tree .tree-folder .tree-folder-items .item.active a { + color: #FFFFFF; } + .tree .tree-folder .tree-folder-items .item:hover { + background: #17181a; } + .tree .tree-folder .tree-folder-items .item a { + text-decoration: none; + color: #FFFFFF; } + .tree .tree-folder .tree-folder-items .feed .item-title:not([data-unread="0"])::before { + content: attr(data-unread); + background: rgba(0, 0, 0, 0.25); + font-size: 0.75rem; + display: block; + float: left; + padding: 3px 4px; + text-align: center; + border-radius: 12px; + margin: 11px 6px 0 4px; + line-height: 0.75rem; } + +/*=== Buttons */ +.stick { + vertical-align: middle; + font-size: 0; } + .stick input, .stick .btn { + border-radius: 0; } + .stick .btn:first-child, + .stick input:first-child { + border-radius: 5px 0 0 5px; } + .stick .btn:last-child, .stick input:last-child, .stick .btn + .dropdown > .btn { + border-radius: 0 5px 5px 0; } + .stick .btn + .btn, + .stick .btn + input, + .stick .btn + .dropdown > .btn, + .stick input + .btn, + .stick input + input, + .stick input + .dropdown > .btn, + .stick .dropdown + .btn, + .stick .dropdown + input, + .stick .dropdown + .dropdown > .btn { + border-left: 1px solid #d5d8db; } + +.aside { + background: #303136; } + .aside.aside_feed { + padding: 10px 0; + text-align: center; + background: #303136; } + .aside.aside_feed .tree { + margin: 10px 0 50px; } + +/* Sidebar des pages de configuration */ +/*=== Navigation */ +.nav-list .nav-header, +.nav-list .item { + height: 2.5em; + line-height: 2.5em; + font-size: 1rem; } +.nav-list .item { + background: #303136; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .nav-list .item a { + padding: 0 1rem; + color: #FFFFFF; } + .nav-list .item .error a { + color: #f5633e; } + .nav-list .item:hover { + background: #17181a; + color: #FFFFFF; } + .nav-list .item:hover .error a { + color: #FFFFFF; + background: #3366cc; } + .nav-list .item:hover .empty a { + color: #FFFFFF; + background: #f4f762; } + .nav-list .item:hover a { + color: #FFFFFF; + text-decoration: none; } + .nav-list .item.active { + background: #3366cc; + color: #fff; } + .nav-list .item.active .error a { + color: #fff; + background: #3366cc; } + .nav-list .item.active .empty a { + color: #fff; + background: #f4f762; } + .nav-list .item.active a { + color: #fff; + text-decoration: none; } +.nav-list.empty a { + color: #f4f762; } +.nav-list .disable { + text-align: center; + background: #f9fafb; + color: #a6a7ae; } +.nav-list .nav-header { + padding: 0 10px; + font-weight: bold; + color: #5b6871; + text-transform: uppercase; + letter-spacing: 1px; + margin-top: 1rem; } +.nav-list .nav-form { + padding: 3px; + text-align: center; } +.nav-list .nav-head { + margin: 0; + text-align: right; + color: #fff; } + .nav-list .nav-head a { + color: #fff; } + .nav-list .nav-head .item { + padding: 5px 10px; + font-size: 0.9rem; + line-height: 1.5rem; } + +/*=== Aside main page (categories) */ +.aside_feed .tree-folder-title > .title:not([data-unread="0"])::after { + position: absolute; + right: 0; + line-height: 1.5rem; + background: rgba(0, 0, 0, 0.25); + border-radius: 12px; + padding: 0 0.75rem; + margin: -0.5rem 1rem 0 0; + text-align: center; } + +.feed.item.empty.active { + background: #5b6871; } + +.feed.item.error.active { + background: #5b6871; } + +.feed.item.empty, +.feed.item.empty > a { + color: #5b6871; } + +.feed.item.error, +.feed.item.error > a { + color: #5b6871; } + +.feed.item.empty.active, +.feed.item.error.active, +.feed.item.empty.active > a, +.feed.item.error.active > a { + color: #fff; } + +.aside_feed .tree-folder-items .dropdown-menu::after { + left: 2px; } + +.aside_feed .tree-folder-items .item .dropdown-target:target ~ .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item:hover .dropdown-toggle > .icon, +.aside_feed .tree-folder-items .item.active .dropdown-toggle > .icon { + border-radius: 3px; } + +.aside_feed .stick #btn-importExport { + border-left-color: #303136; } + +/*=== STRUCTURE */ +/*===============*/ +/*=== Header */ +.header { + background: #303136; + padding: 0.5rem 1.35rem; + display: block; + table-layout: none; + width: auto; } + .header .item { + vertical-align: middle; } + .header .item.title { + font-weight: 400; + width: 280px; } + .header .item.title h1 a { + text-decoration: none; + color: #FFFFFF; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; } + .header .item.title h1 a img { + margin-right: 0.5rem; } + .header .item.search input { + width: 230px; + border-radius: 2px 0 0 2px; + background-color: #26272a; + color: #FFFFFF; + border: none; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .header .item.search input:hover { + background-color: #17181a; } + .header .item.search input:focus { + width: 350px; + background-color: #fff; + color: #5b6871; } + .header .item.search .btn { + border-radius: 0 2px 2px 0; + background-color: #3366cc; + background-position: center; + background-repeat: no-repeat; + background-image: url(icons/magnifier.svg); + border-left-width: 0; + width: 3rem; + min-height: 35px; } + .header .item.search .btn img { + display: none; } + .header .item.search .btn:hover { + background-color: #2255cc; } + .header .item.configure { + width: 2rem; + position: absolute; + right: 1rem; + top: 1.25rem; + text-align: center; } + .header .item.configure .btn { + background-color: transparent; + background-position: center; + background-repeat: no-repeat; + background-image: url(icons/cog-white.svg); + padding: 0 0.5rem; } + .header .item.configure .btn img { + display: none; } + +/*=== Body */ +#global { + height: calc(100% - 85px); } + +/*=== Prompt (centered) */ +.prompt { + text-align: center; } + +.prompt label { + text-align: left; } + +.prompt form { + margin: 10px auto 20px auto; + width: 200px; } + +.prompt input { + margin: 5px auto; + width: 100%; } + +.prompt p { + margin: 20px 0; } + +/*=== New article notification */ +#new-article { + text-align: center; + font-size: 1rem; + background: #3366cc; } + +#new-article:hover { + background: #2255cc; } + +#new-article > a { + line-height: 3em; + font-weight: bold; + color: #fff; } + +#new-article > a:hover { + text-decoration: none; } + +/*=== Day indication */ +.day { + padding: 1rem 0 0 1.25rem; + font-weight: 700; + line-height: 3em; + letter-spacing: 1px; + text-transform: uppercase; + font-size: 0.875rem; + color: #5b6871; } + .day .name { + padding: 0 1rem 0 1rem; + font-size: 0.875rem; + color: #303136; + position: relative; + left: 0; + text-transform: uppercase; } + +/*=== Index menu */ +.nav_menu { + text-align: center; + padding: 5px 0; } + .nav_menu .btn { + border-left-width: 0; + padding: 0.5rem 1rem; + background-color: #f9fafb; + background-position: center; + background-repeat: no-repeat; } + .nav_menu .btn:hover { + background-color: #eff0f2; } + .nav_menu .stick { + background: #f9fafb; } + .nav_menu .stick .btn { + border-left-width: 0; + padding: 0.5rem 1rem; + background-color: #f9fafb; + background-position: center; + background-repeat: no-repeat; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .nav_menu .stick .btn:hover { + background-color: #d5d8db; } + .nav_menu .stick .btn.active { + background-color: #3366cc; } + .nav_menu .stick .btn img.icon { + display: none; } + .nav_menu .stick .btn#toggle-read { + background-image: url(icons/read.svg); } + .nav_menu .stick .btn#toggle-read.active { + background-image: url(icons/read-white.svg); } + .nav_menu .stick .btn#toggle-unread { + background-image: url(icons/unread.svg); } + .nav_menu .stick .btn#toggle-unread.active { + background-image: url(icons/unread-white.svg); } + .nav_menu .stick .btn#toggle-starred { + background-image: url(icons/starred.svg); } + .nav_menu .stick .btn#toggle-starred.active { + background-image: url(icons/starred-white.svg); } + .nav_menu .stick .btn#toggle-non-starred { + background-image: url(icons/non-starred.svg); } + .nav_menu .stick .btn#toggle-non-starred.active { + background-image: url(icons/non-starred-white.svg); } + .nav_menu .stick .btn.read_all { + background-color: #f9fafb; + color: #303136; + padding: 5px 16px; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .nav_menu .stick .btn.read_all:hover { + background-color: #d5d8db; } + .nav_menu .stick .btn.view-normal { + background-image: url(icons/view-list.svg); } + .nav_menu .stick .btn.view-normal.active { + background-image: url(icons/view-list-white.svg); } + .nav_menu .stick .btn.view-global { + background-image: url(icons/view-global.svg); } + .nav_menu .stick .btn.view-global.active { + background-image: url(icons/view-global-white.svg); } + .nav_menu .stick .btn.view-reader { + background-image: url(icons/view-reader.svg); } + .nav_menu .stick .btn.view-reader.active { + background-image: url(icons/view-reader-white.svg); } + .nav_menu .stick .btn.view-rss { + background-image: url(icons/rss.svg); } + .nav_menu .stick .dropdown a.dropdown-toggle { + border-left-width: 0; + background-image: url(icons/more.svg); } + +#dropdown-query ~ .dropdown-menu .dropdown-header .icon { + vertical-align: middle; + background-color: #a6a7ae; + border-radius: 3px; } + +/*=== Content of feed articles */ +.content, .content.thin { + padding: 20px 10px; + font-size: 1.125rem; + line-height: 1.8rem; } + .content h1.title a, .content h1 a, .content.thin h1.title a, .content.thin h1 a { + color: #303136; + font-family: "spectral"; + font-size: 2rem; } + .content h1.title a:hover, .content h1 a:hover, .content.thin h1.title a:hover, .content.thin h1 a:hover { + color: #3366cc; + text-decoration: none; } + .content .author, .content.thin .author { + font-size: 1.125rem; + color: #5b6871; } + .content p, .content ul, .content.thin p, .content.thin ul { + font-size: 1.125rem; + line-height: 1.8rem; } + .content .content hr, .content.thin .content hr { + margin: 30px 10px; + height: 1px; + background: #d5d8db; + border: 0; + box-shadow: 0 2px 5px #ccc; } + .content pre, .content.thin pre { + margin: 10px auto; + padding: 10px 20px; + overflow: auto; + background: #1d1e22; + color: #fff; + font-size: 0.9rem; + border-radius: 3px; } + .content pre code, .content.thin pre code { + background: transparent; + color: #fff; + border: none; } + .content code, .content.thin code { + padding: 2px 5px; + color: #eff0f2; + background: #f9fafb; + border: 1px solid #eff0f2; + border-radius: 3px; } + .content blockquote, .content.thin blockquote { + display: block; + margin: 0; + padding: 5px 20px; + border-top: 1px solid #d5d8db; + border-bottom: 1px solid #d5d8db; + background: #f9fafb; + color: #303136; } + .content blockquote p, .content.thin blockquote p { + margin: 0; } + +/*=== Notification and actualize notification */ +.notification { + position: fixed; + top: auto; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 3rem; + padding: 1rem 0; + text-align: center; + font-size: 1em; + line-height: 3em; + z-index: 10; + vertical-align: middle; + background: #d5d8db; + color: #5b6871; + border: none; } + .notification .msg { + font-size: 1rem; + display: inline-block; } + .notification.good { + background: #10f587; + color: #fff; } + .notification.bad { + background: #f5633e; + color: #fff; } + .notification a.close { + padding: 0 15px; + line-height: 3em; + border-radius: 0 3px 3px 0; } + .notification.good a.close:hover { + background: #0c7540; } + .notification.bad a.close:hover { + background: #73341f; } + .notification#actualizeProgress { + line-height: 2em; } + .notification#actualizeProgress br { + display: none; } + +/*=== Navigation menu (for articles) */ +#nav_entries { + margin: 0; + text-align: center; + line-height: 3em; + table-layout: fixed; + background: #303136; } + +/*=== Feed articles */ +.flux { + background: #fff; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .flux:hover { + background: #f9fafb; } + .flux:hover:not(.current):hover .item.title { + background: #f9fafb; } + .flux.current { + border-left-color: #3366cc; + background: #f9fafb; } + .flux.not_read { + background: #f2f6f8; } + .flux.not_read:hover { + background: #fdfdfe; } + .flux.not_read:not(.current):hover .item.title { + background: #fdfdfe; } + .flux.not_read .item.title a { + color: #3366cc; } + .flux.not_read .item.website a { + color: #3366cc; } + .flux.not_read .item.date { + color: #3366cc99; } + .flux.favorite { + background: #FFF6DA; + border-left-color: #FFC300; + -webkit-transition: all 0.15s ease-in-out; + -moz-transition: all 0.15s ease-in-out; + -o-transition: all 0.15s ease-in-out; + -ms-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; } + .flux.favorite:not(.current):hover .item.title { + background: #FFF6DA; } + .flux .website a { + color: #303136; + opacity: 0.75; } + .flux .website .favicon { + padding: 5px; } + .flux .date { + font-size: 0.85rem; + color: #303136; + opacity: 0.75; } + .flux .bottom { + font-size: 1rem; + text-align: center; } + +.flux_header { + font-size: 1rem; + cursor: pointer; + border-top: 1px solid #eff0f2; } + .flux_header .title { + font-size: 1rem; } + +/*=== GLOBAL VIEW */ +/*================*/ +#stream .box.category:not([data-unread="0"]) .box-title .title { + font-weight: bold; } +#stream .box.category .box-title { + background: none; + padding: 1.5rem; } + #stream .box.category .box-title a.title { + font-weight: normal; + text-decoration: none; + text-align: left; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 1px; + color: #5b6871; } + #stream .box.category .box-title a.title:not([data-unread="0"])::after { + position: absolute; + top: 1.75rem; + right: 0; + line-height: 1.5rem; + background: #eff0f2; + border-radius: 12px; + padding: 0 0.75rem; + margin: -0.5rem 1rem 0 0; + text-align: center; } + #stream .box.category .box-title a.title:hover { + color: #3366cc; } +#stream .box.category .box-content { + padding-bottom: 0.5rem; } + #stream .box.category .box-content .item.feed { + font-size: 1rem; + padding: 0.5rem 1.5rem; } + #stream .box.category .box-content .item.feed a { + color: #303136; + font-weight: 400; } + #stream .box.category .box-content .item.feed a:hover { + color: #3366cc; + text-decoration: none; } + +#overlay { + background: rgba(0, 0, 0, 0.65); } + +#panel { + top: 3rem; + right: 3rem; + bottom: 3rem; + left: 3rem; + border-radius: 3px; } + +/*=== READER VIEW */ +/*================*/ +#stream.reader .flux { + padding: 0 0 50px; + background: #eff0f2; + color: #303136; + border: none; } + +#stream.reader .flux .author { + margin: 0 0 10px; + font-size: 90%; + color: #a6a7ae; } + +/*=== Configuration pages */ +.post { + padding: 1rem 2rem; + font-size: 1rem; } + .post form { + margin: 1rem 0; } + .post form .horizontal-list { + margin-bottom: 0.5rem; } + .post.content { + max-width: 550px; } + .post h1, .post h2 { + font-size: 3rem; + margin-top: 1.75rem; + font-weight: 300; + line-height: 1.2em; + color: #303136; } + .post a[href="./"] { + display: inline-block; + min-width: 15px; + line-height: 25px; + margin: 0; + padding: 0.75rem 1.5rem; + font-size: 1rem; + vertical-align: middle; + cursor: pointer; + overflow: hidden; + background: #f9fafb; + border: 1px solid #d5d8db; + border-radius: 5px; + color: #5b6871; } + .post a[href="./"]:hover { + text-decoration: none; + background: #3366cc; + color: white; + border: 1px solid #3366cc; } + +#slider { + border-left: none; + -webkit-box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); + -moz-box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); + box-shadow: 0px 6px 8px 0px rgba(0, 0, 0, 0.35); } + +.slide-container .properties { + background: rgba(0, 0, 0, 0.75); + border: 0; + padding: 1rem; + color: white; } + .slide-container .properties .page-number { + right: 1rem; + top: 1rem; } + +/*=== LOGS */ +/*=========*/ +.loglist { + overflow: hidden; + border: 1px solid #a6a7ae; } + +.log { + margin: 10px 0; + padding: 5px 2%; + overflow: auto; + font-size: 0.8rem; + background: #f9fafb; + color: #5b6871; } + +.log > .date { + margin: 0 10px 0 0; + padding: 5px 10px; + border-radius: 20px; } + +.log.error > .date { + background: #f5633e; + color: #fff; } + +.log.warning > .date { + background: #f4f762; } + +.log.notice > .date { + background: #eff0f2; } + +.log.debug > .date { + background: #1d1e22; + color: #fff; } + +/*=== STATISTICS */ +/*===============*/ +.stat { + margin: 10px 0 20px; } + +.stat th, +.stat td, +.stat tr { + border: none; } + +.stat > table td, +.stat > table th { + border-bottom: 1px solid #d5d8db; } + +.stat > .horizontal-list { + margin: 0 0 5px; } + +.stat > .horizontal-list .item { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } + +.stat > .horizontal-list .item:first-child { + width: 270px; } + +/*=== MOBILE */ +/*===========*/ +@media (max-width: 840px) { + ul.nav .item { + width: 100%; } + ul.nav .item img { + display: none; } + ul.nav .item a { + display: inline-block; + padding: 1rem 1rem 1rem 2.5rem; + color: #FFFFFF; + width: 100%; + background: url("../../themes/icons/logout.svg") no-repeat #17181a 3% center; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + -ms-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + ul.nav .item a:hover, ul.nav .item a:active { + background: url("../../themes/icons/logout.svg") no-repeat #f5633e 3% center; + text-decoration: none; } + + .aside { + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + -ms-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; } + .aside.aside_feed { + padding: 0; } + .aside .tree .tree-folder .tree-folder-items .item a { + padding: 0.5rem 1rem; } + + .aside .toggle_aside, + #panel .close { + display: block; + width: 100%; + height: 50px; + line-height: 50px; + text-align: center; + background: #2255cc; } + + .header { + padding: 0.5rem; } + .header .item.title { + display: none; } + .header .item.search input { + width: 90%; + height: 3.5rem; } + .header .item.search input:focus { + width: 100%; } + .header .item.search .btn { + min-height: 49px; + padding: 0.5rem 2rem; } + .header .item.configure { + width: 2.75rem; + top: 3.125rem; } + .header .item.configure .dropdown .btn { + padding: 1.125rem; } + + .nav_menu .btn { + margin: 0; + padding: 0.85rem 1.25rem; } + .nav_menu .stick { + margin: 0.5rem 0.5rem; } + .nav_menu .stick .btn { + margin: 0; + padding: 0.85rem 1.25rem; } + .nav_menu .stick .btn.read_all { + padding: 0.85rem 1.25rem; } + .nav_menu .search { + display: none; + max-width: 97%; } + .nav_menu .search .input { + max-width: 97%; + width: 90px; } + .nav_menu .search .input::focus { + width: 400px; } + + #stream .flux .flux_header { + padding: 0.5rem 0; } + + .day { + text-align: center; + padding: 1rem 0; } + .day .name { + display: block; + padding: 0; + width: 100%; + line-height: 1.5rem; + margin-bottom: 1rem; } + + .pagination { + margin: 0 0 3.5em; } + + #nav_entries { + line-height: 4.5rem; } + + .notification { + border-radius: 0; } + .notification a.close { + display: block; + left: 0; + background: transparent; } + .notification a.close:hover { + opacity: 0.5; } + .notification a.close .icon { + display: none; } } +html, body { + font-family: "lato", "Helvetica", "Arial", sans-serif; + font-size: 0.875rem; } + +/*=== GENERAL */ +/*============*/ +html, body { + height: 100%; + background: #eff0f2; } + +/*=== Links */ +a, button.as-link { + outline: none; + color: #3366cc; } + +/*# sourceMappingURL=mapco.css.map */ diff --git a/p/themes/Mapco/mapco.css.map b/p/themes/Mapco/mapco.css.map new file mode 100644 index 000000000..9441efeb4 --- /dev/null +++ b/p/themes/Mapco/mapco.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["_fonts.scss","_mixins.scss","_forms.scss","_variables.scss","_tables.scss","_components.scss","_divers.scss","_sidebar.scss","_layout.scss","_list-view.scss","_global-view.scss","_reader-view.scss","_configuration.scss","_logs.scss","_stats.scss","_mobile.scss","mapco.scss"], +"names": [], +"file": "mapco.css" +} \ No newline at end of file diff --git a/p/themes/Mapco/mapco.scss b/p/themes/Mapco/mapco.scss new file mode 100644 index 000000000..1a538b50a --- /dev/null +++ b/p/themes/Mapco/mapco.scss @@ -0,0 +1,51 @@ +@import "fonts"; +@import "mixins"; +@import "variables"; + +@import "forms"; +@import "tables"; +@import "components"; + +@import "divers"; + +@import "sidebar"; +@import "layout"; +@import "list-view"; +@import "global-view"; +@import "reader-view"; + +@import "configuration"; + +@import "logs"; +@import "stats"; + +@import "mobile"; + +html, body{ + font-family: "lato", "Helvetica", "Arial", sans-serif; + font-size: 0.875rem; +} + +@charset "UTF-8"; + +/*=== GENERAL */ +/*============*/ +html, body { + height: 100%; + background: $grey-light; +} + +/*=== Links */ +a, button.as-link { + outline: none; + color: $main-first; +} + + + + + + + + + diff --git a/p/themes/Mapco/metadata.json b/p/themes/Mapco/metadata.json new file mode 100644 index 000000000..24bb04b87 --- /dev/null +++ b/p/themes/Mapco/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "Mapco", + "author": "Thomas Guesnon", + "description": "Thème pour FreshRSS", + "version": 0.1, + "files": ["_template.css", "mapco.css"] +} diff --git a/p/themes/Mapco/sass.sh b/p/themes/Mapco/sass.sh new file mode 100644 index 000000000..316d04cf2 --- /dev/null +++ b/p/themes/Mapco/sass.sh @@ -0,0 +1 @@ +sass --watch mapco.scss:mapco.css diff --git a/p/themes/Mapco/thumbs/original.png b/p/themes/Mapco/thumbs/original.png new file mode 100644 index 000000000..6dd7ec72c Binary files /dev/null and b/p/themes/Mapco/thumbs/original.png differ diff --git a/p/themes/fonts/LatoLatin-Bold.woff b/p/themes/fonts/LatoLatin-Bold.woff new file mode 100644 index 000000000..cdfcbe0fb Binary files /dev/null and b/p/themes/fonts/LatoLatin-Bold.woff differ diff --git a/p/themes/fonts/LatoLatin-BoldItalic.woff b/p/themes/fonts/LatoLatin-BoldItalic.woff new file mode 100644 index 000000000..3e683fea7 Binary files /dev/null and b/p/themes/fonts/LatoLatin-BoldItalic.woff differ diff --git a/p/themes/fonts/LatoLatin-Italic.woff b/p/themes/fonts/LatoLatin-Italic.woff new file mode 100644 index 000000000..d8cf84c8b Binary files /dev/null and b/p/themes/fonts/LatoLatin-Italic.woff differ diff --git a/p/themes/fonts/LatoLatin-Regular.woff b/p/themes/fonts/LatoLatin-Regular.woff new file mode 100644 index 000000000..bf73a6d9f Binary files /dev/null and b/p/themes/fonts/LatoLatin-Regular.woff differ diff --git a/p/themes/fonts/Spectral-Bold.woff b/p/themes/fonts/Spectral-Bold.woff new file mode 100644 index 000000000..10bbc7bbe Binary files /dev/null and b/p/themes/fonts/Spectral-Bold.woff differ diff --git a/p/themes/fonts/Spectral-BoldItalic.woff b/p/themes/fonts/Spectral-BoldItalic.woff new file mode 100644 index 000000000..2486d78a1 Binary files /dev/null and b/p/themes/fonts/Spectral-BoldItalic.woff differ diff --git a/p/themes/fonts/Spectral-Italic.woff b/p/themes/fonts/Spectral-Italic.woff new file mode 100644 index 000000000..3a7d9cbed Binary files /dev/null and b/p/themes/fonts/Spectral-Italic.woff differ diff --git a/p/themes/fonts/Spectral-Regular.woff b/p/themes/fonts/Spectral-Regular.woff new file mode 100644 index 000000000..a472c4be3 Binary files /dev/null and b/p/themes/fonts/Spectral-Regular.woff differ -- cgit v1.2.3 From 142c80a4b8e13ce93f6c2eb697afeb7e6b54431e Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Feb 2019 11:53:20 +0100 Subject: Changelog 2241 2242 2245 https://github.com/FreshRSS/FreshRSS/issues/2241 https://github.com/FreshRSS/FreshRSS/pull/2242 https://github.com/FreshRSS/FreshRSS/pull/2243 https://github.com/FreshRSS/FreshRSS/pull/2245 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db1873ab0..5ef11bf49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,15 @@ * Bug fixing * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) * Fix breaking warning in Fever API [#2239](https://github.com/FreshRSS/FreshRSS/issues/2239) + * Fix encoding problem in Fever API [#2241](https://github.com/FreshRSS/FreshRSS/issues/2241) * UI + * New themes *Ansum* and *Mapco* [#2245](https://github.com/FreshRSS/FreshRSS/pull/2245) * Batch scroll-as-read for better client-side and server-side performance [#2199](https://github.com/FreshRSS/FreshRSS/pull/2199) * Rewrite some jQuery code as native JavaScript [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) * Deployment * Docker image updated to Alpine 3.9 with PHP 7.2.14 and Apache 2.4.38 [#2238](https://github.com/FreshRSS/FreshRSS/pull/2238) +* I18n + * Improved Korean [#2242](https://github.com/FreshRSS/FreshRSS/pull/2242) ## 2019-01-26 FreshRSS 1.13.1 -- cgit v1.2.3 From 2374374ba972eb4cca84d7f71b1900f806c2b914 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Feb 2019 15:06:28 +0100 Subject: Less jQuery (#2234) * Less jQuery Follow-up of https://github.com/FreshRSS/FreshRSS/pull/2199 * Even less jQuery + global view unread title fix * Even less jQuery * Yet even less jQuery * Even less jQuery * Reduce some events * Even less jQuery * jQuery gone from main view +Fixed English i18n * Fix feed folded view * Remove Firefox 64 workaround Remove workaround for Gecko bug 1514498 in Firefox 64, fixed in Firefox 65 * Split to extra.js Avoid loading unneeded JavaScript code for the main view. + several adjustements * Improve CSS transition fold category * Rewrite shortcuts Remove library. Much faster, shorter, one listener instead of many. Control of the shortcut context. Fix https://github.com/FreshRSS/FreshRSS/issues/2215 * Remove debug * Minor syntax * Filter out unwanted shortcut modifiers * Menu overflow fix * Typo * Fix unfolding in mobile view * Remove jQuery from category.js * Remove jQuery from Global view --- README.fr.md | 1 - README.md | 1 - app/Controllers/authController.php | 3 +- app/Controllers/indexController.php | 1 + app/Controllers/statsController.php | 1 + app/Controllers/subscriptionController.php | 3 +- app/Controllers/userController.php | 4 +- app/FreshRSS.php | 5 +- app/i18n/en/conf.php | 2 +- app/i18n/ru/conf.php | 2 +- app/i18n/tr/conf.php | 2 +- app/layout/aside_feed.phtml | 6 +- app/views/helpers/index/normal/entry_bottom.phtml | 2 +- app/views/index/reader.phtml | 2 +- lib/Minz/Request.php | 25 + p/scripts/category.js | 178 ++- p/scripts/extra.js | 235 +++ p/scripts/global_view.js | 128 +- p/scripts/main.js | 1589 +++++++++------------ p/scripts/repartition.js | 4 +- p/scripts/shortcut.js | 225 --- p/scripts/stats.js | 8 +- p/themes/base-theme/template.css | 40 +- 23 files changed, 1180 insertions(+), 1287 deletions(-) create mode 100644 p/scripts/extra.js delete mode 100644 p/scripts/shortcut.js diff --git a/README.fr.md b/README.fr.md index e40ab8296..58647ae4a 100644 --- a/README.fr.md +++ b/README.fr.md @@ -210,7 +210,6 @@ Tout client supportant une API de type Fever ; Sélection : * [php-http-304](https://alexandre.alapetite.fr/doc-alex/php-http-304/) * [jQuery](https://jquery.com/) * [lib_opml](https://github.com/marienfressinaud/lib_opml) -* [keyboard_shortcuts](http://www.openjs.com/scripts/events/keyboard_shortcuts/) * [flotr2](http://www.humblesoftware.com/flotr2) ## Uniquement pour certaines options ou configurations diff --git a/README.md b/README.md index a5a2af725..190ee5639 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,6 @@ Supported clients are: * [php-http-304](https://alexandre.alapetite.fr/doc-alex/php-http-304/) * [jQuery](https://jquery.com/) * [lib_opml](https://github.com/marienfressinaud/lib_opml) -* [keyboard_shortcuts](http://www.openjs.com/scripts/events/keyboard_shortcuts/) * [flotr2](http://www.humblesoftware.com/flotr2) ## Only for some options or configurations diff --git a/app/Controllers/authController.php b/app/Controllers/authController.php index 3b2d78b19..75d4acae0 100644 --- a/app/Controllers/authController.php +++ b/app/Controllers/authController.php @@ -109,8 +109,7 @@ class FreshRSS_auth_Controller extends Minz_ActionController { public function formLoginAction() { invalidateHttpCache(); - $file_mtime = @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'); - Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . $file_mtime)); + Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'))); $conf = Minz_Configuration::get('system'); $limits = $conf->limits; diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index fa914ef87..824d65815 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -104,6 +104,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { return; } + Minz_View::appendScript(Minz_Url::display('/scripts/extra.js?' . @filemtime(PUBLIC_PATH . '/scripts/extra.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/global_view.js?' . @filemtime(PUBLIC_PATH . '/scripts/global_view.js'))); try { diff --git a/app/Controllers/statsController.php b/app/Controllers/statsController.php index acfacb890..1d0d9c124 100644 --- a/app/Controllers/statsController.php +++ b/app/Controllers/statsController.php @@ -52,6 +52,7 @@ class FreshRSS_stats_Controller extends Minz_ActionController { */ public function indexAction() { $statsDAO = FreshRSS_Factory::createStatsDAO(); + Minz_View::prependScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js'))); $this->view->repartition = $statsDAO->calculateEntryRepartition(); $entryCount = $statsDAO->calculateEntryCount(); diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index 46503fc19..62fb3d384 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -29,8 +29,7 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { * It displays categories and associated feeds. */ public function indexAction() { - Minz_View::appendScript(Minz_Url::display('/scripts/category.js?' . - @filemtime(PUBLIC_PATH . '/scripts/category.js'))); + Minz_View::appendScript(Minz_Url::display('/scripts/category.js?' . @filemtime(PUBLIC_PATH . '/scripts/category.js'))); Minz_View::prependTitle(_t('sub.title') . ' · '); $this->view->onlyFeedsWithError = Minz_Request::paramTernary('error'); diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php index 2338c8b2a..71172b9ef 100644 --- a/app/Controllers/userController.php +++ b/app/Controllers/userController.php @@ -128,9 +128,7 @@ class FreshRSS_user_Controller extends Minz_ActionController { public function profileAction() { Minz_View::prependTitle(_t('conf.profile.title') . ' · '); - Minz_View::appendScript(Minz_Url::display( - '/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js') - )); + Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'))); if (Minz_Request::isPost()) { $passwordPlain = Minz_Request::param('newPasswordPlain', '', true); diff --git a/app/FreshRSS.php b/app/FreshRSS.php index dec446a8e..9371081e4 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -94,9 +94,10 @@ class FreshRSS extends Minz_FrontController { } } //Use prepend to insert before extensions. Added in reverse order. + if (Minz_Request::controllerName() !== 'index') { + Minz_View::prependScript(Minz_Url::display('/scripts/extra.js?' . @filemtime(PUBLIC_PATH . '/scripts/extra.js'))); + } Minz_View::prependScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); - Minz_View::prependScript(Minz_Url::display('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js'))); - Minz_View::prependScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js'))); } private static function loadNotifications() { diff --git a/app/i18n/en/conf.php b/app/i18n/en/conf.php index c6471426f..b3d4d8a5c 100644 --- a/app/i18n/en/conf.php +++ b/app/i18n/en/conf.php @@ -92,7 +92,7 @@ return array( 'auto_remove_article' => 'Hide articles after reading', 'confirm_enabled' => 'Display a confirmation dialog on “mark all as read” actions', 'display_articles_unfolded' => 'Show articles unfolded by default', - 'display_categories_unfolded' => 'Show categories folded by default', + 'display_categories_unfolded' => 'Show categories unfolded by default', 'hide_read_feeds' => 'Hide categories & feeds with no unread articles (does not work with “Show all articles” configuration)', 'img_with_lazyload' => 'Use "lazy load" mode to load pictures', 'jump_next' => 'jump to next unread sibling (feed or category)', diff --git a/app/i18n/ru/conf.php b/app/i18n/ru/conf.php index 59ac480bc..841477964 100644 --- a/app/i18n/ru/conf.php +++ b/app/i18n/ru/conf.php @@ -92,7 +92,7 @@ return array( 'auto_remove_article' => 'Hide articles after reading', //TODO - Translation 'confirm_enabled' => 'Display a confirmation dialog on “mark all as read” actions', //TODO - Translation 'display_articles_unfolded' => 'Show articles unfolded by default', //TODO - Translation - 'display_categories_unfolded' => 'Show categories folded by default', //TODO - Translation + 'display_categories_unfolded' => 'Show categories unfolded by default', //TODO - Translation 'hide_read_feeds' => 'Hide categories & feeds with no unread article (does not work with “Show all articles” configuration)', //TODO - Translation 'img_with_lazyload' => 'Use "lazy load" mode to load pictures', //TODO - Translation 'jump_next' => 'jump to next unread sibling (feed or category)', //TODO - Translation diff --git a/app/i18n/tr/conf.php b/app/i18n/tr/conf.php index 507558487..6c57d39da 100644 --- a/app/i18n/tr/conf.php +++ b/app/i18n/tr/conf.php @@ -92,7 +92,7 @@ return array( 'auto_remove_article' => 'Okuduktan sonra makaleleri gizle', 'confirm_enabled' => '"Hepsini okundu say" eylemi için onay iste', 'display_articles_unfolded' => 'Show articles unfolded by default', - 'display_categories_unfolded' => 'Show categories folded by default', + 'display_categories_unfolded' => 'Show categories unfolded by default', 'hide_read_feeds' => 'Okunmamış makalesi olmayan kategori veya akışı gizle ("Tüm makaleleri göster" komutunda çalışmaz)', 'img_with_lazyload' => 'Resimleri yüklemek için "tembel modu" kullan', 'jump_next' => 'Bir sonraki benzer okunmamışa geç (akış veya kategori)', diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml index 5efaa54d1..637acf4a4 100644 --- a/app/layout/aside_feed.phtml +++ b/app/layout/aside_feed.phtml @@ -37,13 +37,14 @@ display_categories; ?>
  • -
      +
        tags as $tag): ?> @@ -64,8 +65,7 @@ $feeds = $cat->feeds(); if (!empty($feeds)) { $c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id()); - $c_show = $c_active && (!FreshRSS_Context::$user_conf->display_categories || - FreshRSS_Context::$current_get['feed']); + $c_show = $c_active || FreshRSS_Context::$user_conf->display_categories; ?>
      • diff --git a/app/views/helpers/index/normal/entry_bottom.phtml b/app/views/helpers/index/normal/entry_bottom.phtml index 1f35318e3..c0edbdf7d 100644 --- a/app/views/helpers/index/normal/entry_bottom.phtml +++ b/app/views/helpers/index/normal/entry_bottom.phtml @@ -93,7 +93,7 @@ name(); ?> name(); ?> -
        +
        diff --git a/app/views/index/reader.phtml b/app/views/index/reader.phtml index 1485a1997..fbe37d2e3 100644 --- a/app/views/index/reader.phtml +++ b/app/views/index/reader.phtml @@ -42,7 +42,7 @@ if (!empty($this->entries)) { isFavorite() ? 'starred' : 'non-starred'); ?> - + ✇ name(); ?>

        title(); ?>

        diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php index 8b2b610d6..912c354ac 100644 --- a/lib/Minz/Request.php +++ b/lib/Minz/Request.php @@ -95,6 +95,7 @@ class Minz_Request { */ public static function init() { self::magicQuotesOff(); + self::initJSON(); } /** @@ -237,6 +238,30 @@ class Minz_Request { } } + /** + * Allows receiving POST data as application/json + */ + private static function initJSON() { + $contentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : ''; + if ($contentType == '') { //PHP < 5.3.16 + $contentType = isset($_SERVER['HTTP_CONTENT_TYPE']) ? $_SERVER['HTTP_CONTENT_TYPE'] : ''; + } + $contentType = strtolower(trim($contentType)); + if ($contentType === 'application/json') { + $ORIGINAL_INPUT = file_get_contents('php://input', false, null, 0, 1048576); + if ($ORIGINAL_INPUT != '') { + $json = json_decode($ORIGINAL_INPUT, true); + if ($json != null) { + foreach ($json as $k => $v) { + if (!isset($_POST[$k])) { + $_POST[$k] = $v; + } + } + } + } + } + } + /** * Permet de récupérer une variable de type $_POST * @param $param nom de la variable diff --git a/p/scripts/category.js b/p/scripts/category.js index caa4fa22f..86d8542f1 100644 --- a/p/scripts/category.js +++ b/p/scripts/category.js @@ -1,6 +1,6 @@ "use strict"; -/* globals i18n */ -/* jshint globalstrict: true */ +/* globals context */ +/* jshint esversion:6, strict:global */ var loading = false, dnd_successful = false; @@ -9,7 +9,7 @@ function dragend_process(t) { t.setAttribute('draggable', 'false'); if (loading) { - window.setTimeout(function() { + setTimeout(function() { dragend_process(t); }, 50); return; @@ -20,11 +20,11 @@ function dragend_process(t) { t.style.opacity = ''; t.setAttribute('draggable', 'true'); } else { - var parent = $(t.parentNode); - $(t).remove(); + const p = t.parentElement; + t.remove(); - if (parent.children().length <= 0) { - parent.append('
      • ' + i18n.category_empty + '
      • '); + if (p.childElementCount <= 0) { + p.insertAdjacentHTML('beforeend', '
      • ' + context.i18n.category_empty + '
      • '); } } } @@ -33,89 +33,109 @@ var dragFeedId = '', dragHtml = ''; function init_draggable() { - if (!(window.$ && window.i18n)) { + if (!window.context) { if (window.console) { - console.log('FreshRSS waiting for JS…'); + console.log('FreshRSS category waiting for JS…'); } - window.setTimeout(init_draggable, 50); + setTimeout(init_draggable, 50); return; } - var draggable = '[draggable="true"]', - dropzone = '[dropzone="move"]'; - - $('.drop-section').on('dragstart', draggable, function(e) { - var drag = $(e.target).closest('[draggable]')[0]; - e.originalEvent.dataTransfer.effectAllowed = 'move'; - dragHtml = drag.outerHTML; - dragFeedId = drag.getAttribute('data-feed-id'); - e.originalEvent.dataTransfer.setData('text', dragFeedId); - drag.style.opacity = 0.3; - - dnd_successful = false; - }); - $('.drop-section').on('dragend', draggable, function(e) { - dragend_process(e.target); - }); - - $('.drop-section').on('dragenter', dropzone, function(e) { - $(this).addClass('drag-hover'); - - e.preventDefault(); - }); - $('.drop-section').on('dragleave', dropzone, function(e) { - var pos_this = $(this).position(), - scroll_top = $(document).scrollTop(), - top = pos_this.top, - left = pos_this.left, - right = left + $(this).width(), - bottom = top + $(this).height(), - mouse_x = e.originalEvent.screenX, - mouse_y = e.originalEvent.clientY + scroll_top; - - if (left <= mouse_x && mouse_x <= right && - top <= mouse_y && mouse_y <= bottom) { - // HACK because dragleave is triggered when hovering children! - return; - } - $(this).removeClass('drag-hover'); - }); - $('.drop-section').on('dragover', dropzone, function(e) { - e.originalEvent.dataTransfer.dropEffect = "move"; - - e.preventDefault(); - return false; - }); - $('.drop-section').on('drop', dropzone, function(e) { - loading = true; - - $.ajax({ - type: 'POST', - url: './?c=feed&a=move', - data: { - f_id: dragFeedId, - c_id: e.target.parentNode.getAttribute('data-cat-id'), - _csrf: context.csrf, + const draggable = '[draggable="true"]', + dropzone = '[dropzone="move"]', + dropSection = document.querySelector('.drop-section'); + + dropSection.ondragstart = function(ev) { + const li = ev.target.closest ? ev.target.closest(draggable) : null; + if (li) { + const drag = ev.target.closest('[draggable]'); + ev.dataTransfer.effectAllowed = 'move'; + dragHtml = drag.outerHTML; + dragFeedId = drag.getAttribute('data-feed-id'); + ev.dataTransfer.setData('text', dragFeedId); + drag.style.opacity = 0.3; + dnd_successful = false; } - }).done(function() { - $(e.target).after(dragHtml); - if ($(e.target).hasClass('disabled')) { - $(e.target).remove(); + }; + + dropSection.ondragend = function(ev) { + const li = ev.target.closest ? ev.target.closest(draggable) : null; + if (li) { + dragend_process(li); } - dnd_successful = true; - }).always(function() { - loading = false; - dragFeedId = ''; - dragHtml = ''; - }); + }; - $(this).removeClass('drag-hover'); + dropSection.ondragenter = function(ev) { + const li = ev.target.closest ? ev.target.closest(dropzone) : null; + if (li) { + li.classList.add('drag-hover'); + return false; + } + }; + + dropSection.onddragleave = function(ev) { + const li = ev.target.closest ? ev.target.closest(dropzone) : null; + if (li) { + const scroll_top = document.documentElement.scrollTop, + top = li.offsetTop, + left = li.offsetLeft, + right = left + li.clientWidth, + bottom = top + li.clientHeight, + mouse_x = ev.screenX, + mouse_y = ev.clientY + scroll_top; + + if (left <= mouse_x && mouse_x <= right && + top <= mouse_y && mouse_y <= bottom) { + // HACK because dragleave is triggered when hovering children! + return; + } + li.classList.remove('drag-hover'); + } + }; - e.preventDefault(); - }); + dropSection.ondragover = function(ev) { + const li = ev.target.closest ? ev.target.closest(dropzone) : null; + if (li) { + ev.dataTransfer.dropEffect = "move"; + return false; + } + }; + + dropSection.ondrop = function(ev) { + const li = ev.target.closest ? ev.target.closest(dropzone) : null; + if (li) { + loading = true; + + const req = new XMLHttpRequest(); + req.open('POST', './?c=feed&a=move', true); + req.responseType = 'json'; + req.onload = function (e) { + if (this.status == 200) { + li.insertAdjacentHTML('afterend', dragHtml); + if (li.classList.contains('disabled')) { + li.remove(); + } + dnd_successful = true; + } + }; + req.onloadend = function (e) { + loading = false; + dragFeedId = ''; + dragHtml = ''; + }; + req.setRequestHeader('Content-Type', 'application/json'); + req.send(JSON.stringify({ + f_id: dragFeedId, + c_id: li.parentElement.getAttribute('data-cat-id'), + _csrf: context.csrf, + })); + + li.classList.remove('drag-hover'); + return false; + } + }; } - if (document.readyState && document.readyState !== 'loading') { init_draggable(); } else if (document.addEventListener) { diff --git a/p/scripts/extra.js b/p/scripts/extra.js new file mode 100644 index 000000000..7a0ef0477 --- /dev/null +++ b/p/scripts/extra.js @@ -0,0 +1,235 @@ +"use strict"; +/* globals context, openNotification, xmlHttpRequestJson */ +/* jshint esversion:6, strict:global */ + +// +function poormanSalt() { //If crypto.getRandomValues is not available + const base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789/abcdefghijklmnopqrstuvwxyz'; + let text = '$2a$04$'; + for (let i = 22; i > 0; i--) { + text += base.charAt(Math.floor(Math.random() * 64)); + } + return text; +} + +function init_crypto_form() { + /* globals dcodeIO */ + const crypto_form = document.getElementById('crypto-form'); + if (!crypto_form) { + return; + } + + if (!(window.dcodeIO)) { + if (window.console) { + console.log('FreshRSS waiting for bcrypt.js…'); + } + setTimeout(init_crypto_form, 100); + return; + } + + crypto_form.onsubmit = function (e) { + const submit_button = this.querySelector('button[type="submit"]'); + submit_button.disabled = true; + let success = false; + + const req = new XMLHttpRequest(); + req.open('GET', './?c=javascript&a=nonce&user=' + document.getElementById('username').value, false); + req.onerror = function () { + openNotification('Communication error!', 'bad'); + }; + req.send(); + if (req.status == 200) { + const json = xmlHttpRequestJson(req); + if (!json.salt1 || !json.nonce) { + openNotification('Invalid user!', 'bad'); + } else { + try { + const strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function'), + s = dcodeIO.bcrypt.hashSync(document.getElementById('passwordPlain').value, json.salt1), + c = dcodeIO.bcrypt.hashSync(json.nonce + s, strong ? dcodeIO.bcrypt.genSaltSync(4) : poormanSalt()); + document.getElementById('challenge').value = c; + if (!s || !c) { + openNotification('Crypto error!', 'bad'); + } else { + success = true; + } + } catch (ex) { + openNotification('Crypto exception! ' + ex, 'bad'); + } + } + } else { + req.onerror(); + } + + submit_button.disabled = false; + return success; + }; +} +// + +function init_share_observers() { + let shares = document.querySelectorAll('.group-share').length; + const shareAdd = document.querySelector('.share.add'); + if (shareAdd) { + shareAdd.onclick = function (ev) { + const s = this.parentElement.querySelector('select'), + opt = s.options[s.selectedIndex]; + let row = this.closest('form').getAttribute('data-' + opt.getAttribute('data-form')); + row = row.replace(/##label##/g, opt.text); + row = row.replace(/##type##/g, opt.value); + row = row.replace(/##help##/g, opt.getAttribute('data-help')); + row = row.replace(/##key##/g, shares); + row = row.replace(/##method##/g, opt.getAttribute('data-method')); + row = row.replace(/##field##/g, opt.getAttribute('data-field')); + this.closest('.form-group').insertAdjacentHTML('beforebegin', row); + shares++; + return false; + }; + } +} + + +function init_remove_observers() { + document.querySelectorAll('.post').forEach(function (div) { + div.onclick = function (ev) { + const a = ev.target.closest('a.remove'); + if (a) { + const remove_what = a.getAttribute('data-remove'); + if (remove_what !== undefined) { + const d = document.getElementById(remove_what); + if (d) { + d.remove(); + } + } + return false; + } + }; + }); +} + +function init_feed_observers() { + const s = document.getElementById('category'); + if (s && s.matches('select')) { + s.onchange = function (ev) { + const detail = document.getElementById('new_category_name').parentElement; + if (this.value === 'nc') { + detail.setAttribute('aria-hidden', 'false'); + detail.querySelector('input').focus(); + } else { + detail.setAttribute('aria-hidden', 'true'); + } + }; + } +} + +function init_password_observers() { + document.querySelectorAll('.toggle-password').forEach(function (a) { + a.onmousedown = function (ev) { + const passwordField = document.getElementById(this.getAttribute('data-toggle')); + passwordField.setAttribute('type', 'text'); + this.classList.add('active'); + return false; + }; + a.onmouseup = function (ev) { + const passwordField = document.getElementById(this.getAttribute('data-toggle')); + passwordField.setAttribute('type', 'password'); + this.classList.remove('active'); + return false; + }; + }); +} + +function init_select_observers() { + document.querySelectorAll('.select-change').forEach(function (s) { + s.onchange = function (ev) { + const opt = s.options[s.selectedIndex]; + location.href = opt.getAttribute('data-url'); + }; + }); +} + +function init_slider_observers() { + const slider = document.getElementById('slider'), + closer = document.getElementById('close-slider'); + if (!slider) { + return; + } + + document.querySelector('.post').onclick = function (ev) { + const a = ev.target.closest('.open-slider'); + if (a) { + if (!context.ajax_loading) { + context.ajax_loading = true; + + const req = new XMLHttpRequest(); + req.open('GET', a.href + '&ajax=1', true); + req.responseType = 'document'; + req.onload = function (e) { + slider.innerHTML = this.response.body.innerHTML; + slider.classList.add('active'); + closer.classList.add('active'); + context.ajax_loading = false; + }; + req.send(); + return false; + } + } + }; + + closer.onclick = function (ev) { + closer.classList.remove('active'); + slider.classList.remove('active'); + return false; + }; +} + +function init_configuration_alert() { + window.onsubmit = function (e) { + window.hasSubmit = true; + }; + window.onbeforeunload = function (e) { + if (window.hasSubmit) { + return; + } + const ds = document.querySelectorAll('[data-leave-validation]'); + for (let i = ds.length - 1; i >= 0; i--) { + const input = ds[i]; + if (input.type === 'checkbox' || input.type === 'radio') { + if (input.checked != input.getAttribute('data-leave-validation')) { + return false; + } + } else if (input.value != input.getAttribute('data-leave-validation')) { + return false; + } + } + }; +} + +function init_extra() { + if (!window.context) { + if (window.console) { + console.log('FreshRSS extra waiting for JS…'); + } + window.setTimeout(init_extra, 50); //Wait for all js to be loaded + return; + } + init_crypto_form(); + init_share_observers(); + init_remove_observers(); + init_feed_observers(); + init_password_observers(); + init_select_observers(); + init_slider_observers(); + init_configuration_alert(); +} + +if (document.readyState && document.readyState !== 'loading') { + init_extra(); +} else { + document.addEventListener('DOMContentLoaded', function () { + if (window.console) { + console.log('FreshRSS extra waiting for DOMContentLoaded…'); + } + init_extra(); + }, false); +} diff --git a/p/scripts/global_view.js b/p/scripts/global_view.js index c5aaa48b1..b1581614a 100644 --- a/p/scripts/global_view.js +++ b/p/scripts/global_view.js @@ -1,6 +1,6 @@ "use strict"; -/* globals init_load_more, init_posts, init_stream */ -/* jshint globalstrict: true */ +/* globals context, init_load_more, init_posts, init_stream */ +/* jshint esversion:6, strict:global */ var panel_loading = false; @@ -11,68 +11,88 @@ function load_panel(link) { panel_loading = true; - $.get(link, function (data) { - $("#panel").append($(".nav_menu, #stream .day, #stream .flux, #stream .pagination, #stream.prompt", data)); - - $("#panel .nav_menu").children().not("#nav_menu_read_all").remove(); - - init_load_more($("#panel")); - init_posts(); - - $("#overlay").fadeIn(); - $("#panel").slideToggle(); - - // force le démarrage du scroll en haut. - // Sans ça, si l'on scroll en lisant une catégorie par exemple, - // en en ouvrant une autre ensuite, on se retrouve au même point de scroll - $("#panel").scrollTop(0); - $(window).scrollTop(0); - - $('#panel').on('click', '#nav_menu_read_all button, #bigMarkAsRead', function () { - console.log($(this).attr("formaction")); - $.ajax({ - type: "POST", - url: $(this).attr("formaction"), - data: { - _csrf: context.csrf, - }, - async: false - }); - window.location.reload(false); - return false; - }); - - panel_loading = false; - }); + const req = new XMLHttpRequest(); + req.open('GET', link, true); + req.responseType = 'document'; + req.onload = function (e) { + if (this.status != 200) { + return; + } + const html = this.response, + foreign = html.querySelectorAll('.nav_menu, #stream .day, #stream .flux, #stream .pagination, #stream.prompt'), + panel = document.getElementById('panel'); + foreign.forEach(function (el) { + panel.appendChild(document.adoptNode(el)); + }); + panel.querySelectorAll('.nav_menu > :not([id="nav_menu_read_all"])').forEach(function (el) { + el.remove(); + }); + + init_load_more(panel); + init_posts(); + + document.getElementById('overlay').classList.add('visible'); + panel.classList.add('visible'); + + // force le démarrage du scroll en haut. + // Sans ça, si l'on scroll en lisant une catégorie par exemple, + // en en ouvrant une autre ensuite, on se retrouve au même point de scroll + panel.scrollTop = 0; + document.documentElement.scrollTop = 0; + + //We already have a click listener in main.js + panel.addEventListener('click', function (ev) { + const b = ev.target.closest('#nav_menu_read_all button, #bigMarkAsRead'); + if (b) { + console.log(b.formAction); + + const req2 = new XMLHttpRequest(); + req2.open('POST', b.formAction, false); + req2.setRequestHeader('Content-Type', 'application/json'); + req2.send(JSON.stringify({ + _csrf: context.csrf, + })); + if (req2.status == 200) { + location.reload(false); + return false; + } + } + }); + + panel_loading = false; + }; + req.send(); } function init_close_panel() { - $("#overlay .close").click(function () { - $("#panel").html(''); - $("#panel").slideToggle(); - $("#overlay").fadeOut(); - - return false; - }); + const panel = document.getElementById('panel'); + document.querySelector('#overlay .close').onclick = function (ev) { + panel.innerHTML = ''; + panel.classList.remove('visible'); + document.getElementById('overlay').classList.remove('visible'); + return false; + }; } function init_global_view() { - // TODO: should be based on generic classes. - $(".box a").click(function () { - var link = $(this).attr("href"); - - load_panel(link); - - return false; - }); + // TODO: should be based on generic classes + document.querySelectorAll('.box a').forEach(function (a) { + a.onclick = function (ev) { + load_panel(a.href); + return false; + }; + }); - $(".nav_menu #nav_menu_read_all, .nav_menu .toggle_aside").remove(); + document.querySelectorAll('.nav_menu #nav_menu_read_all, .nav_menu .toggle_aside').forEach(function (el) { + el.remove(); + }); - init_stream($("#panel")); + const panel = document.getElementById('panel'); + init_stream(panel); } function init_all_global_view() { - if (!(window.$ && window.init_stream)) { + if (!window.context) { if (window.console) { console.log('FreshRSS Global view waiting for JS…'); } @@ -85,7 +105,7 @@ function init_all_global_view() { if (document.readyState && document.readyState !== 'loading') { init_all_global_view(); -} else if (document.addEventListener) { +} else { document.addEventListener('DOMContentLoaded', function () { init_all_global_view(); }, false); diff --git a/p/scripts/main.js b/p/scripts/main.js index 82dc79ce7..345cbe749 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1,5 +1,4 @@ "use strict"; -/* globals $, jQuery, shortcut */ /* jshint esversion:6, strict:global */ // @@ -16,36 +15,34 @@ if (!Element.prototype.closest) Element.prototype.closest = function (s) { if (!Element.prototype.remove) Element.prototype.remove = function () { if (this.parentNode) this.parentNode.removeChild(this); }; // -// -var context, i18n, icons, shortcuts, urls; +// +function xmlHttpRequestJson(req) { + let json = req.response; + if (req.responseType !== 'json') { //IE11 + try { json = JSON.parse(req.responseText); } + catch (ex) { json = null; } + } + return json; +} +// + +// +var context; (function parseJsonVars() { const jsonVars = document.getElementById('jsonVars'), json = JSON.parse(jsonVars.innerHTML); jsonVars.outerHTML = ''; context = json.context; - i18n = json.i18n; - shortcuts = json.shortcuts; - urls = json.urls; - icons = json.icons; - icons.read = decodeURIComponent(icons.read); - icons.unread = decodeURIComponent(icons.unread); + context.ajax_loading = false; + context.i18n = json.i18n; + context.shortcuts = json.shortcuts; + context.urls = json.urls; + context.icons = json.icons; + context.icons.read = decodeURIComponent(context.icons.read); + context.icons.unread = decodeURIComponent(context.icons.unread); }()); - -var $stream = null, - ajax_loading = false, - $nav_entries = null; -// - -function redirect(url, new_tab) { - if (url) { - if (new_tab) { - window.open(url); - } else { - location.href = url; - } - } -} +// function needsScroll(elem) { const winBottom = document.documentElement.scrollTop + document.documentElement.clientHeight, @@ -160,54 +157,64 @@ var pending_entries = {}, mark_read_queue = []; function send_mark_read_queue(queue, asRead) { - $.ajax({ - type: 'POST', - url: '.?c=entry&a=read' + (asRead ? '' : '&is_read=0'), - data: { - ajax: true, - _csrf: context.csrf, - 'id[]': queue, - }, - }).done(function (data) { - for (let i = queue.length - 1; i >= 0; i--) { - const div = document.getElementById('flux_' + queue[i]), - myIcons = icons; - let inc = 0; - if (div.classList.contains('not_read')) { - div.classList.remove('not_read'); - div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=0', '') + '&is_read=1'); }); - div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.read; }); - inc--; - } else { - div.classList.add('not_read'); - div.classList.add('keep_unread'); //Split for IE11 - div.querySelectorAll('a.read').forEach(function (a) { a.setAttribute('href', a.getAttribute('href').replace('&is_read=1', '')); }); - div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.unread; }); - inc++; + const req = new XMLHttpRequest(); + req.open('POST', '.?c=entry&a=read' + (asRead ? '' : '&is_read=0'), true); + req.responseType = 'json'; + req.onerror = function (e) { + openNotification(context.i18n.notif_request_failed, 'bad'); + for (let i = queue.length - 1; i >= 0; i--) { + delete pending_entries['flux_' + queue[i]]; } - let feed_link = div.querySelector('.website > a'); - if (feed_link) { - let feed_url = feed_link.getAttribute('href'); - let feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); - incUnreadsFeed(div, feed_id, inc); + }; + req.onload = function (e) { + if (this.status != 200) { + return req.onerror(e); } - delete pending_entries['flux_' + queue[i]]; - } - faviconNbUnread(); - if (data.tags) { - let tagIds = Object.keys(data.tags); - for (let i = tagIds.length - 1; i >= 0; i--) { - let tagId = tagIds[i]; - incUnreadsTag(tagId, (asRead ? -1 : 1) * data.tags[tagId].length); + const json = xmlHttpRequestJson(this); + for (let i = queue.length - 1; i >= 0; i--) { + const div = document.getElementById('flux_' + queue[i]), + myIcons = context.icons; + let inc = 0; + if (div.classList.contains('not_read')) { + div.classList.remove('not_read'); + div.querySelectorAll('a.read').forEach(function (a) { + a.href = a.href.replace('&is_read=0', '') + '&is_read=1'; + }); + div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.read; }); + inc--; + } else { + div.classList.add('not_read'); + div.classList.add('keep_unread'); //Split for IE11 + div.querySelectorAll('a.read').forEach(function (a) { + a.href = a.href.replace('&is_read=1', ''); + }); + div.querySelectorAll('a.read > .icon').forEach(function (img) { img.outerHTML = myIcons.unread; }); + inc++; + } + let feed_link = div.querySelector('.website > a, a.website'); + if (feed_link) { + let feed_url = feed_link.href; + let feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); + incUnreadsFeed(div, feed_id, inc); + } + delete pending_entries['flux_' + queue[i]]; } - } - onScroll(); - }).fail(function (data) { - openNotification(i18n.notif_request_failed, 'bad'); - for (let i = queue.length - 1; i >= 0; i--) { - delete pending_entries['flux_' + queue[i]]; - } - }); + faviconNbUnread(); + if (json.tags) { + let tagIds = Object.keys(json.tags); + for (let i = tagIds.length - 1; i >= 0; i--) { + let tagId = tagIds[i]; + incUnreadsTag(tagId, (asRead ? -1 : 1) * json.tags[tagId].length); + } + } + onScroll(); + }; + req.setRequestHeader('Content-Type', 'application/json'); + req.send(JSON.stringify({ + ajax: true, + _csrf: context.csrf, + id: queue, + })); } var send_mark_read_queue_timeout = 0; @@ -246,7 +253,7 @@ function mark_favorite(div) { } let a = div.querySelector('a.bookmark'), - url = a ? a.getAttribute('href') : ''; + url = a ? a.href : ''; if (!url) { return false; } @@ -256,45 +263,51 @@ function mark_favorite(div) { } pending_entries[div.id] = true; - $.ajax({ - type: 'POST', - url: url, - data: { - ajax: true, - _csrf: context.csrf, - }, - }).done(function (data) { - let inc = 0; - if (div.classList.contains('favorite')) { - div.classList.remove('favorite'); - inc--; - } else { - div.classList.add('favorite'); - inc++; - } - div.querySelectorAll('a.bookmark').forEach(function (a) { a.setAttribute('href', data.url); }); - div.querySelectorAll('a.bookmark > .icon').forEach(function (img) { img.outerHTML = data.icon; }); + const req = new XMLHttpRequest(); + req.open('POST', url, true); + req.responseType = 'json'; + req.onerror = function (e) { + openNotification(context.i18n.notif_request_failed, 'bad'); + delete pending_entries[div.id]; + }; + req.onload = function (e) { + if (this.status != 200) { + return req.onerror(e); + } + const json = xmlHttpRequestJson(this); + let inc = 0; + if (div.classList.contains('favorite')) { + div.classList.remove('favorite'); + inc--; + } else { + div.classList.add('favorite'); + inc++; + } + div.querySelectorAll('a.bookmark').forEach(function (a) { a.href = json.url; }); + div.querySelectorAll('a.bookmark > .icon').forEach(function (img) { img.outerHTML = json.icon; }); - const favourites = document.querySelector('#aside_feed .favorites .title'); - if (favourites) { - favourites.textContent = favourites.textContent.replace(/((?: \([ 0-9]+\))?\s*)$/, function (m, p1) { - return incLabel(p1, inc, false); - }); - } + const favourites = document.querySelector('#aside_feed .favorites .title'); + if (favourites) { + favourites.textContent = favourites.textContent.replace(/((?: \([ 0-9]+\))?\s*)$/, function (m, p1) { + return incLabel(p1, inc, false); + }); + } - if (div.classList.contains('not_read')) { - const elem = document.querySelector('#aside_feed .favorites .title'), - feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; - if (elem) { - elem.setAttribute('data-unread', numberFormat(feed_unreads + inc)); + if (div.classList.contains('not_read')) { + const elem = document.querySelector('#aside_feed .favorites .title'), + feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; + if (elem) { + elem.setAttribute('data-unread', numberFormat(feed_unreads + inc)); + } } - } - delete pending_entries[div.id]; - }).fail(function (data) { - openNotification(i18n.notif_request_failed, 'bad'); - delete pending_entries[div.id]; - }); + delete pending_entries[div.id]; + }; + req.setRequestHeader('Content-Type', 'application/json'); + req.send(JSON.stringify({ + ajax: true, + _csrf: context.csrf, + })); } var freshrssOpenArticleEvent = document.createEvent('Event'); @@ -307,9 +320,9 @@ function toggleContent(new_active, old_active, skipping) { } if (context.does_lazyload && !skipping) { - new_active.querySelectorAll('img[data-original], iframe[data-original]').forEach(function (elem) { - elem.setAttribute('src', elem.getAttribute('data-original')); - elem.removeAttribute('data-original'); + new_active.querySelectorAll('img[data-original], iframe[data-original]').forEach(function (el) { + el.src = el.getAttribute('data-original'); + el.removeAttribute('data-original'); }); } @@ -322,12 +335,12 @@ function toggleContent(new_active, old_active, skipping) { old_active.classList.remove('active'); old_active.classList.remove('current'); //Split for IE11 } - } else { // collapse_entry calls toggleContent(flux_current, flux_current, false) + } else { new_active.classList.toggle('active'); } const relative_move = context.current_view === 'global', - box_to_move = relative_move ? document.getElementById('#panel') : document.documentElement; + box_to_move = relative_move ? document.getElementById('panel') : document.documentElement; if (context.sticky_post) { let prev_article = new_active.previousElementSibling, @@ -355,7 +368,7 @@ function toggleContent(new_active, old_active, skipping) { if (context.auto_mark_article) { mark_read(new_active, true); } - new_active[0].dispatchEvent(freshrssOpenArticleEvent); + new_active.dispatchEvent(freshrssOpenArticleEvent); } onScroll(); } @@ -373,18 +386,28 @@ function next_entry(skipping) { } function prev_feed() { - const $active_feed = $('#aside_feed .tree-folder-items .item.active'); - if ($active_feed.length > 0) { - $active_feed.prevAll(':visible:first').find('a').each(function () { this.click(); }); + const active_feed = document.querySelector('#aside_feed .feed.active'); + if (active_feed) { + let feed = active_feed; + do feed = feed.previousElementSibling; + while (feed && getComputedStyle(feed).display === 'none'); + if (feed) { + feed.querySelector('a.item-title').click(); + } } else { last_feed(); } } function next_feed() { - const $active_feed = $('#aside_feed .tree-folder-items .item.active'); - if ($active_feed.length > 0) { - $active_feed.nextAll(':visible:first').find('a').each(function () { this.click(); }); + const active_feed = document.querySelector('#aside_feed .feed.active'); + if (active_feed) { + let feed = active_feed; + do feed = feed.nextElementSibling; + while (feed && getComputedStyle(feed).display === 'none'); + if (feed) { + feed.querySelector('a.item-title').click(); + } } else { first_feed(); } @@ -405,31 +428,31 @@ function last_feed() { } function prev_category() { - const $active_cat = $('#aside_feed .tree-folder.active'); - - if ($active_cat.length > 0) { - const $prev_cat = $active_cat.prevAll(':visible:first').find('.tree-folder-title .title'); - if ($prev_cat.length > 0) { - $prev_cat[0].click(); + const active_cat = document.querySelector('#aside_feed .category.active'); + if (active_cat) { + let cat = active_cat; + do cat = cat.previousElementSibling; + while (cat && getComputedStyle(cat).display === 'none'); + if (cat) { + cat.querySelector('a.title').click(); } } else { last_category(); } - return; } function next_category() { - const $active_cat = $('#aside_feed .tree-folder.active'); - - if ($active_cat.length > 0) { - const $next_cat = $active_cat.nextAll(':visible:first').find('.tree-folder-title .title'); - if ($next_cat.length > 0) { - $next_cat[0].click(); + const active_cat = document.querySelector('#aside_feed .category.active'); + if (active_cat) { + let cat = active_cat; + do cat = cat.nextElementSibling; + while (cat && getComputedStyle(cat).display === 'none'); + if (cat) { + cat.querySelector('a.title').click(); } } else { first_category(); } - return; } function first_category() { @@ -452,21 +475,21 @@ function collapse_entry() { } function user_filter(key) { - const $filter = $('#dropdown-query'), - $filters = $filter.siblings('.dropdown-menu').find('.item.query a'); + const filter = document.getElementById('dropdown-query'), + filters = filter.parentElement.querySelectorAll('.dropdown-menu > .query > a'); if (typeof key === 'undefined') { - if (!$filters.length) { + if (!filters.length) { return; } // Display the filter div - location.hash = $filters.attr('id'); + location.hash = filter.id; // Force scrolling to the filter div const scroll = needsScroll(document.querySelector('.header')); if (scroll !== 0) { document.documentElement.scrollTop = scroll; } // Force the key value if there is only one action, so we can trigger it automatically - if ($filters.length === 1) { + if (filters.length === 1) { key = 1; } else { return; @@ -474,8 +497,8 @@ function user_filter(key) { } // Trigger selected share action key = parseInt(key); - if (key <= $filters.length) { - $filters[key - 1].click(); + if (key <= filters.length) { + filters[key - 1].click(); } } @@ -576,384 +599,378 @@ function init_column_categories() { return; } - $('#aside_feed').on('click', '.tree-folder>.tree-folder-title>a.dropdown-toggle', function () { - $(this).children().each(function () { - if (this.alt === '▽') { - this.src = this.src.replace('/icons/down.', '/icons/up.'); - this.alt = '△'; + document.getElementById('aside_feed').onclick = function (ev) { + let a = ev.target.closest('.tree-folder > .tree-folder-title > a.dropdown-toggle'); + if (a) { + const img = a.querySelector('img'); + if (img.alt === '▽') { + img.src = img.src.replace('/icons/down.', '/icons/up.'); + img.alt = '△'; } else { - this.src = this.src.replace('/icons/up.', '/icons/down.'); - this.alt = '▽'; + img.src = img.src.replace('/icons/up.', '/icons/down.'); + img.alt = '▽'; } - }); - $(this).parent().next('.tree-folder-items').slideToggle(300, function () { - //Workaround for Gecko bug 1514498 in Firefox 64 - const sidebar = document.getElementById('sidebar'); - if (sidebar && sidebar.scrollHeight > sidebar.clientHeight && //if needs scrollbar - sidebar.scrollWidth >= sidebar.offsetWidth) { //but no scrollbar - sidebar.style['overflow-y'] = 'scroll'; //then force scrollbar - setTimeout(function () { sidebar.style['overflow-y'] = ''; }, 0); + + const ul = a.closest('li').querySelector('.tree-folder-items'); + let nbVisibleItems = 0; + for (let i = ul.children.length - 1; i >= 0; i--) { + if (ul.children[i].offsetHeight) { + nbVisibleItems++; + } } - }); - return false; - }); + ul.classList.toggle('active'); + //CSS transition does not work on max-height:auto + ul.style.maxHeight = ul.classList.contains('active') ? (nbVisibleItems * 4) + 'em' : 0; + return false; + } - $('#aside_feed').on('click', '.tree-folder-items .feed .dropdown-toggle', function () { - const itemId = $(this).closest('.item').attr('id'), - templateId = itemId.substring(0, 2) === 't_' ? 'tag_config_template' : 'feed_config_template', - id = itemId.substr(2), - feed_web = $(this).data('fweb'), - template = $('#' + templateId) - .html().replace(/------/g, id).replace('http://example.net/', feed_web); - if ($(this).next('.dropdown-menu').length === 0) { - $(this).attr('href', '#dropdown-' + id).prev('.dropdown-target').attr('id', 'dropdown-' + id).parent() - .append(template).find('button.confirm').removeAttr('disabled'); - } else { - if ($(this).next('.dropdown-menu').css('display') === 'none') { - const id2 = $(this).closest('.item').attr('id').substr(2); - $(this).attr('href', '#dropdown-' + id2); + a = ev.target.closest('.tree-folder-items > .feed .dropdown-toggle'); + if (a) { + const itemId = a.closest('.item').id, + templateId = itemId.substring(0, 2) === 't_' ? 'tag_config_template' : 'feed_config_template', + id = itemId.substr(2), + feed_web = a.getAttribute('data-fweb'), + div = a.parentElement, + dropdownMenu = div.querySelector('.dropdown-menu'), + template = document.getElementById(templateId) + .innerHTML.replace(/------/g, id).replace('http://example.net/', feed_web); + if (!dropdownMenu) { + a.href = '#dropdown-' + id; + div.querySelector('.dropdown-target').id = 'dropdown-' + id; + div.insertAdjacentHTML('beforeend', template); + div.querySelector('button.confirm').disabled = false; + } else if (getComputedStyle(dropdownMenu).display === 'none') { + const id2 = div.closest('.item').id.substr(2); + a.href = '#dropdown-' + id2; } else { - $(this).attr('href', '#close'); + a.href = '#close'; } + return true; } - }); + + return true; + }; } function init_shortcuts() { - if (!(window.shortcut)) { - if (window.console) { - console.log('FreshRSS waiting for shortcut.js…'); - } - setTimeout(init_shortcuts, 200); - return; - } - // Manipulation shortcuts - shortcut.add(shortcuts.mark_read, function () { - // Toggle the read state - mark_read(document.querySelector('.flux.current'), false); - }, { - 'disable_in_input': true - }); - shortcut.add('shift+' + shortcuts.mark_read, function () { - // Mark everything as read - $('.nav_menu .read_all').click(); - }, { - 'disable_in_input': true - }); - shortcut.add(shortcuts.mark_favorite, function () { - // Toggle the favorite state - mark_favorite(document.querySelector('.flux.current')); - }, { - 'disable_in_input': true - }); - shortcut.add(shortcuts.collapse_entry, function () { - // Toggle the collapse state - collapse_entry(); - }, { - 'disable_in_input': true - }); - shortcut.add(shortcuts.auto_share, function () { - // Display the share options - auto_share(); - }, { - 'disable_in_input': true - }); + Object.keys(context.shortcuts).forEach(function (k) { + context.shortcuts[k] = (context.shortcuts[k] || '').toUpperCase(); + }); - shortcut.add(shortcuts.user_filter, function () { - // Display the user filters - user_filter(); - }, { - 'disable_in_input': true - }); + document.body.onkeydown = function (ev) { + if (ev.target.closest('input, textarea') || + ev.ctrlKey || ev.metaKey || (ev.altKey && ev.shiftKey)) { + return true; + } - function addShortcut(evt) { - if ($('#dropdown-query').siblings('.dropdown-menu').is(':visible')) { - user_filter(String.fromCharCode(evt.keyCode)); - } else { - auto_share(String.fromCharCode(evt.keyCode)); - } - } - for (let i = 1; i < 10; i++) { - shortcut.add(i.toString(), addShortcut, { - 'disable_in_input': true - }); - } + const s = context.shortcuts, + k = ev.key.toUpperCase(); + if (location.hash.match(/^#dropdown-/)) { + const n = parseInt(k); + if (n) { + if (location.hash === '#dropdown-query') { + user_filter(n); + } else { + auto_share(n); + } + return false; + } + } + if (k === s.next_entry) { + if (ev.altKey) { + next_category(); + } else if (ev.shiftKey) { + next_feed(); + } else { + next_entry(false); + } + return false; + } + if (k === s.prev_entry) { + if (ev.altKey) { + prev_category(); + } else if (ev.shiftKey) { + prev_feed(); + } else { + prev_entry(false); + } + return false; + } + if (k === s.mark_read) { + if (ev.altKey) { + return true; + } else if (ev.shiftKey) { // Mark everything as read + document.querySelector('.nav_menu .read_all').click(); + } else { // Toggle the read state + mark_read(document.querySelector('.flux.current'), false); + } + return false; + } + if (k === s.first_entry) { + if (ev.altKey) { + first_category(); + } else if (ev.shiftKey) { + first_feed(); + } else { + const old_active = document.querySelector('.flux.current'), + first = document.querySelector('.flux'); + if (first.classList.contains('flux')) { + toggleContent(first, old_active, false); + } + } + return false; + } + if (k === s.last_entry) { + if (ev.altKey) { + last_category(); + } else if (ev.shiftKey) { + last_feed(); + } else { + const old_active = document.querySelector('.flux.current'), + last = document.querySelector('.flux:last-of-type'); + if (last.classList.contains('flux')) { + toggleContent(last, old_active, false); + } + } + return false; + } - // Entry navigation shortcuts - shortcut.add(shortcuts.prev_entry, function () { prev_entry(false); }, { - 'disable_in_input': true - }); - shortcut.add(shortcuts.skip_prev_entry, function () { prev_entry(true); }, { - 'disable_in_input': true - }); - shortcut.add(shortcuts.first_entry, function () { - const $old_active = $('.flux.current'), - $first = $('.flux:first'); + if (ev.altKey || ev.shiftKey) { + return true; + } + if (k === s.mark_favorite) { // Toggle the favorite state + mark_favorite(document.querySelector('.flux.current')); + return false; + } + if (k === s.go_website) { + if (context.auto_mark_site) { + mark_read(document.querySelector('.flux.current'), true); + } + window.open(document.querySelector('.flux.current a.go_website').href); + return false; + } + if (k === s.skip_next_entry) { next_entry(true); return false; } + if (k === s.skip_prev_entry) { prev_entry(true); return false; } + if (k === s.collapse_entry) { collapse_entry(); return false; } + if (k === s.auto_share) { auto_share(); return false; } + if (k === s.user_filter) { user_filter(); return false; } + if (k === s.load_more) { load_more_posts(); return false; } + if (k === s.close_dropdown) { location.hash = null; return false; } + if (k === s.help) { window.open(context.urls.help); return false; } + if (k === s.focus_search) { document.getElementById('search').focus(); return false; } + if (k === s.normal_view) { document.querySelector('#nav_menu_views .view-normal').click(); return false; } + if (k === s.reading_view) { document.querySelector('#nav_menu_views .view-reader').click(); return false; } + if (k === s.global_view) { document.querySelector('#nav_menu_views .view-global').click(); return false; } + if (k === s.rss_view) { document.querySelector('#nav_menu_views .view-rss').click(); return false; } + return true; + }; +} - if ($first.hasClass('flux')) { - toggleContent($first, $old_active, false); +function init_stream(stream) { + stream.onclick = function (ev) { + let el = ev.target.closest('.flux a.read'); + if (el) { + mark_read(el.closest('.flux'), false); + return false; } - }, { - 'disable_in_input': true - }); - shortcut.add(shortcuts.next_entry, function () { next_entry(false); }, { - 'disable_in_input': true - }); - shortcut.add(shortcuts.skip_next_entry, function () { next_entry(true); }, { - 'disable_in_input': true - }); - shortcut.add(shortcuts.last_entry, function () { - const $old_active = $('.flux.current'), - $last = $('.flux:last'); - if ($last.hasClass('flux')) { - toggleContent($last, $old_active, false); + el = ev.target.closest('.flux a.bookmark'); + if (el) { + mark_favorite(el.closest('.flux')); + return false; } - }, { - 'disable_in_input': true - }); - // Feed navigation shortcuts - shortcut.add('shift+' + shortcuts.prev_entry, prev_feed, { - 'disable_in_input': true - }); - shortcut.add('shift+' + shortcuts.next_entry, next_feed, { - 'disable_in_input': true - }); - shortcut.add('shift+' + shortcuts.first_entry, first_feed, { - 'disable_in_input': true - }); - shortcut.add('shift+' + shortcuts.last_entry, last_feed, { - 'disable_in_input': true - }); - // Category navigation shortcuts - shortcut.add('alt+' + shortcuts.prev_entry, prev_category, { - 'disable_in_input': true - }); - shortcut.add('alt+' + shortcuts.next_entry, next_category, { - 'disable_in_input': true - }); - shortcut.add('alt+' + shortcuts.first_entry, first_category, { - 'disable_in_input': true - }); - shortcut.add('alt+' + shortcuts.last_entry, last_category, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.go_website, function () { - const url_website = $('.flux.current a.go_website').attr('href'); - if (context.auto_mark_site) { - $('.flux.current').each(function () { - mark_read(this, true); - }); + el = ev.target.closest('.dynamictags'); + if (el) { + loadDynamicTags(el); + return true; } - redirect(url_website, true); - }, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.load_more, load_more_posts, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.focus_search, focus_search, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.help, function () { - redirect(urls.help, true); - }, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.close_dropdown, function () { - location.hash = null; - }, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.normal_view, function () { - $('#nav_menu_views .view-normal').get(0).click(); - }, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.global_view, function () { - $('#nav_menu_views .view-global').get(0).click(); - }, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.reading_view, function () { - $('#nav_menu_views .view-reader').get(0).click(); - }, { - 'disable_in_input': true - }); - - shortcut.add(shortcuts.rss_view, function () { - $('#nav_menu_views .view-rss').get(0).click(); - }, { - 'disable_in_input': true - }); -} - -function init_stream(divStream) { - divStream.on('click', '.flux_header,.flux_content', function (e) { //flux_toggle - if ($(e.target).closest('.content, .item.website, .item.link, .dropdown-menu').length > 0) { - return; - } - if (!context.sides_close_article && $(e.target).is('div.flux_content')) { - // setting for not-closing after clicking outside article area - return; + el = ev.target.closest('.item.title > a'); + if (el) { // Allow default control-click behaviour such as open in backround-tab + return ev.ctrlKey; } - const old_active = document.querySelector('.flux.current'), - new_active = this.parentNode; - if (e.target.tagName.toUpperCase() === 'A') { //Leave real links alone - if (context.auto_mark_article) { - mark_read(new_active, true); + + el = ev.target.closest('.flux .content a'); + if (el) { + if (!el.closest('div').classList.contains('author')) { + el.target = '_blank'; + el.rel = 'noreferrer'; } return true; } - toggleContent(new_active, old_active, false); - }); - - divStream.on('click', '.flux a.read', function () { - mark_read(this.closest('.flux'), false); - return false; - }); - divStream.on('click', '.flux a.bookmark', function () { - mark_favorite(this.closest('.flux')); - return false; - }); + el = ev.target.closest('.item.share > a[href="#"]'); + if (el) { //Print + const content = '' + + el.closest('.flux_content').querySelector('.content').innerHTML + + ''; + const tmp_window = window.open(); + tmp_window.document.writeln(content); + tmp_window.document.close(); + tmp_window.focus(); + tmp_window.print(); + tmp_window.close(); + return false; + } - divStream.on('click', '.item.title > a', function (e) { - // Allow default control-click behaviour such as open in backround-tab. - return e.ctrlKey; - }); - divStream.on('mouseup', '.item.title > a', function (e) { - // Mouseup enables us to catch middle click. - if (e.ctrlKey) { - // CTRL+click, it will be manage by previous rule. - return; + el = ev.target.closest('.item.share > a[href="POST"]'); + if (el) { //Share by POST + const f = el.parentElement.querySelector('form'); + f.disabled = false; + f.submit(); + return false; } - if (e.which == 2) { - // If middle click, we want same behaviour as CTRL+click. - const ev = jQuery.Event('click'); - ev.ctrlKey = true; - $(this).trigger(ev); - } else if (e.which == 1) { - // Normal click, just toggle article. - $(this).parent().click(); + el = ev.target.closest('.flux_header, .flux_content'); + if (el) { //flux_toggle + if (ev.target.closest('.content, .item.website, .item.link, .dropdown-menu')) { + return true; + } + if (!context.sides_close_article && ev.target.matches('div.flux_content')) { + // setting for not-closing after clicking outside article area + return false; + } + const old_active = document.querySelector('.flux.current'), + new_active = el.parentNode; + if (ev.target.tagName.toUpperCase() === 'A') { //Leave real links alone + if (context.auto_mark_article) { + mark_read(new_active, true); + } + return true; + } + toggleContent(new_active, old_active, false); + return false; } - }); + }; - divStream.on('click', '.flux .content a', function () { - if (!$(this).closest('div').hasClass('author')) { - $(this).attr('target', '_blank').attr('rel', 'noreferrer'); + stream.onmouseup = function (ev) { // Mouseup enables us to catch middle click + let el = ev.target.closest('.item.title > a'); + if (el) { + if (ev.ctrlKey) { + return; // CTRL+click, it will be manage by previous rule. + } + if (ev.which == 2) { + // If middle click, we want same behaviour as CTRL+click. + const evc = document.createEvent('click'); + evc.ctrlKey = true; + el.dispatchEvent(evc); + } else if (ev.which == 1) { + // Normal click, just toggle article. + el.parentElement.click(); + } } - }); - if (context.auto_mark_site) { - // catch mouseup instead of click so we can have the correct behaviour - // with middle button click (scroll button). - divStream.on('mouseup', '.flux .link > a', function (e) { - if (e.which == 3) { - return; + if (context.auto_mark_site) { + // catch mouseup instead of click so we can have the correct behaviour + // with middle button click (scroll button). + el = ev.target.closest('.flux .link > a'); + if (el) { + if (ev.which == 3) { + return; + } + mark_read(el.closest('.flux'), true); } + } + }; - mark_read(this.closest('.flux'), true); - }); - } + stream.onchange = function (ev) { + const checkboxTag = ev.target.closest('.checkboxTag'); + if (checkboxTag) { //Dynamic tags + ev.stopPropagation(); + const isChecked = checkboxTag.checked, + tagId = checkboxTag.name.replace(/^t_/, ''), + tagName = checkboxTag.nextElementSibling ? checkboxTag.nextElementSibling.value : '', + entry = checkboxTag.closest('div.flux'), + entryId = entry.id.replace(/^flux_/, ''); + checkboxTag.disabled = true; + + const req = new XMLHttpRequest(); + req.open('POST', './?c=tag&a=tagEntry', true); + req.responseType = 'json'; + req.onerror = function (e) { + checkboxTag.checked = !isChecked; + }; + req.onload = function (e) { + if (this.status != 200) { + return req.onerror(e); + } + if (entry.classList.contains('not_read')) { + incUnreadsTag('t_' + tagId, isChecked ? 1 : -1); + } + }; + req.onloadend = function (e) { + checkboxTag.disabled = false; + if (tagId == 0) { + loadDynamicTags(checkboxTag.closest('div.dropdown')); + } + }; + req.setRequestHeader('Content-Type', 'application/json'); + req.send(JSON.stringify({ + _csrf: context.csrf, + id_tag: tagId, + name_tag: tagId == 0 ? tagName : '', + id_entry: entryId, + checked: isChecked, + })); + } + }; } function init_nav_entries() { - $nav_entries = $('#nav_entries'); - $nav_entries.find('.previous_entry').click(function () { - prev_entry(false); - return false; - }); - $nav_entries.find('.next_entry').click(function () { - next_entry(false); - return false; - }); - $nav_entries.find('.up').click(function () { - const $active_item = $('.flux.current'), - windowTop = $(window).scrollTop(), - item_top = $active_item.offset().top; + const nav_entries = document.getElementById('nav_entries'); + if (nav_entries) { + nav_entries.querySelector('.previous_entry').onclick = function (e) { + prev_entry(false); + return false; + }; + nav_entries.querySelector('.next_entry').onclick = function (e) { + next_entry(false); + return false; + }; + nav_entries.querySelector('.up').onclick = function (e) { + const active_item = document.querySelector('.flux.current'), + windowTop = document.documentElement.scrollTop, + item_top = active_item.offsetParent.offsetTop + active_item.offsetTop; - if (windowTop > item_top) { - $('html,body').scrollTop(item_top); - } else { - $('html,body').scrollTop(0); - } - return false; - }); + document.documentElement.scrollTop = windowTop > item_top ? item_top : 0; + return false; + }; + } } -function loadDynamicTags($div) { - $div.removeClass('dynamictags'); - $div.find('li.item').remove(); - const entryId = $div.closest('div.flux').attr('id').replace(/^flux_/, ''); - $.getJSON('./?c=tag&a=getTagsForEntry&id_entry=' + entryId) - .done(function (data) { - const $ul = $div.find('.dropdown-menu'); - $ul.append('
      • '); - if (data && data.length) { - for (let i = 0; i < data.length; i++) { - const tag = data[i]; - $ul.append('
      • '); - } +function loadDynamicTags(div) { + div.classList.remove('dynamictags'); + div.querySelectorAll('li.item').forEach(function (li) { li.remove(); }); + const entryId = div.closest('div.flux').id.replace(/^flux_/, ''); + + const req = new XMLHttpRequest(); + req.open('GET', './?c=tag&a=getTagsForEntry&id_entry=' + entryId, true); + req.responseType = 'json'; + req.onerror = function (e) { + div.querySelectorAll('li.item').forEach(function (li) { li.remove(); }); + div.classList.add('dynamictags'); + }; + req.onload = function (e) { + if (this.status != 200) { + return req.onerror(e); } - }) - .fail(function () { - $div.find('li.item').remove(); - $div.addClass('dynamictags'); - }); -} - -function init_dynamic_tags() { - $stream.on('click', '.dynamictags', function () { - loadDynamicTags($(this)); - }); - - $stream.on('change', '.checkboxTag', function (ev) { - const $checkbox = $(this), - isChecked = $checkbox.prop('checked'), - tagId = $checkbox.attr('name').replace(/^t_/, ''), - tagName = $checkbox.siblings('input[name]').val(), - $entry = $checkbox.closest('div.flux'), - entryId = $entry.attr('id').replace(/^flux_/, ''); - $checkbox.prop('disabled', true); - $.ajax({ - type: 'POST', - url: './?c=tag&a=tagEntry', - data: { - _csrf: context.csrf, - id_tag: tagId, - name_tag: tagId == 0 ? tagName : '', - id_entry: entryId, - checked: isChecked, - }, - }) - .done(function () { - if ($entry.hasClass('not_read')) { - incUnreadsTag('t_' + tagId, isChecked ? 1 : -1); - } - }) - .fail(function () { - $checkbox.prop('checked', !isChecked); - }) - .always(function () { - $checkbox.prop('disabled', false); - if (tagId == 0) { - loadDynamicTags($checkbox.closest('div.dropdown')); + const json = xmlHttpRequestJson(this); + let html = '
      • '; + if (json && json.length) { + for (let i = 0; i < json.length; i++) { + const tag = json[i]; + html += '
      • '; } - }); - }); + } + div.querySelector('.dropdown-menu').insertAdjacentHTML('beforeend', html); + }; + req.send(); } // @@ -964,86 +981,93 @@ function updateFeed(feeds, feeds_count) { if (!feed) { return; } - $.ajax({ - type: 'POST', - url: feed.url, - data: { - _csrf: context.csrf, - noCommit: 1, - }, - }).always(function (data) { - feed_processed++; - $('#actualizeProgress .progress').html(feed_processed + ' / ' + feeds_count); - $('#actualizeProgress .title').html(feed.title); - - if (feed_processed === feeds_count) { - $.ajax({ //Empty request to commit new articles - type: 'POST', - url: './?c=feed&a=actualize&id=-1&ajax=1', - data: { + const req = new XMLHttpRequest(); + req.open('POST', feed.url, true); + req.onloadend = function (e) { + feed_processed++; + const div = document.getElementById('actualizeProgress'); + div.querySelector('.progress').innerHTML = feed_processed + ' / ' + feeds_count; + div.querySelector('.title').innerHTML = feed.title; + if (feed_processed === feeds_count) { + //Empty request to commit new articles + const req2 = new XMLHttpRequest(); + req2.open('POST', './?c=feed&a=actualize&id=-1&ajax=1', true); + req2.onloadend = function (e) { + location.reload(); + }; + req2.setRequestHeader('Content-Type', 'application/json'); + req2.send(JSON.stringify({ _csrf: context.csrf, noCommit: 0, - }, - }).always(function (data) { - location.reload(); - }); - } else { - updateFeed(feeds, feeds_count); - } - }); + })); + } else { + updateFeed(feeds, feeds_count); + } + }; + req.setRequestHeader('Content-Type', 'application/json'); + req.send(JSON.stringify({ + _csrf: context.csrf, + noCommit: 1, + })); } function init_actualize() { let auto = false; - $('#actualize').click(function () { - if (ajax_loading) { + document.getElementById('actualize').onclick = function () { + if (context.ajax_loading) { return false; } - ajax_loading = true; - - $.getJSON('./?c=javascript&a=actualize').done(function (data) { - if (auto && data.feeds.length < 1) { - auto = false; - ajax_loading = false; - return false; - } - if (data.feeds.length === 0) { - openNotification(data.feedback_no_refresh, 'good'); - $.ajax({ //Empty request to force refresh server database cache - type: 'POST', - url: './?c=feed&a=actualize&id=-1&ajax=1', - data: { - _csrf: context.csrf, - noCommit: 0, - }, - }).always(function (data) { - ajax_loading = false; - }); - return; - } - //Progress bar - const feeds_count = data.feeds.length; - $('body').after('
        ' + data.feedback_actualize + - '
        /
        0 / ' + feeds_count + - '
        '); - for (let i = 10; i > 0; i--) { - updateFeed(data.feeds, feeds_count); - } - }); + context.ajax_loading = true; + + const req = new XMLHttpRequest(); + req.open('GET', './?c=javascript&a=actualize', true); + req.responseType = 'json'; + req.onload = function (e) { + const json = xmlHttpRequestJson(this); + if (auto && json.feeds.length < 1) { + auto = false; + context.ajax_loading = false; + return false; + } + if (json.feeds.length === 0) { + openNotification(json.feedback_no_refresh, 'good'); + //Empty request to commit new articles + const req2 = new XMLHttpRequest(); + req2.open('POST', './?c=feed&a=actualize&id=-1&ajax=1', true); + req2.onloadend = function (e) { + context.ajax_loading = false; + }; + req2.setRequestHeader('Content-Type', 'application/json'); + req2.send(JSON.stringify({ + _csrf: context.csrf, + noCommit: 0, + })); + return; + } + //Progress bar + const feeds_count = json.feeds.length; + document.body.insertAdjacentHTML('beforeend', '
        ' + + json.feedback_actualize + '
        /
        0 / ' + + feeds_count + '
        '); + for (let i = 10; i > 0; i--) { + updateFeed(json.feeds, feeds_count); + } + }; + req.send(); return false; - }); + }; if (context.auto_actualize_feeds) { auto = true; - $('#actualize').click(); + document.getElementById('actualize').click(); } } //
        // -var $notification = null, +var notification = null, notification_interval = null, notification_working = false; @@ -1051,37 +1075,29 @@ function openNotification(msg, status) { if (notification_working === true) { return false; } - notification_working = true; - - $notification.removeClass(); - $notification.addClass('notification'); - $notification.addClass(status); - $notification.find('.msg').html(msg); - $notification.fadeIn(300); + notification.querySelector('.msg').innerHTML = msg; + notification.className = 'notification'; + notification.classList.add(status); notification_interval = setTimeout(closeNotification, 4000); } function closeNotification() { - $notification.fadeOut(600, function () { - $notification.removeClass(); - $notification.addClass('closed'); - - clearInterval(notification_interval); - notification_working = false; - }); + notification.classList.add('closed'); + clearInterval(notification_interval); + notification_working = false; } function init_notifications() { - $notification = $('#notification'); + notification = document.getElementById('notification'); - $notification.find('a.close').click(function () { - closeNotification(); - return false; - }); + notification.querySelector('a.close').onclick = function () { + closeNotification(); + return false; + }; - if ($notification.find('.msg').html().length > 0) { + if (notification.querySelector('.msg').innerHTML.length > 0) { notification_working = true; notification_interval = setTimeout(closeNotification, 4000); } @@ -1106,9 +1122,9 @@ function notifs_html5_show(nb) { return; } - const notification = new window.Notification(i18n.notif_title_articles, { + const notification = new window.Notification(context.i18n.notif_title_articles, { icon: '../themes/icons/favicon-256.png', - body: i18n.notif_body_articles.replace('%d', nb), + body: context.i18n.notif_body_articles.replace('%d', nb), tag: 'freshRssNewArticles', }); @@ -1135,40 +1151,56 @@ function init_notifs_html5() { // function refreshUnreads() { - $.getJSON('./?c=javascript&a=nbUnreadsPerFeed').done(function (data) { - const isAll = document.querySelector('.category.all.active'); - let new_articles = false; - - $.each(data.feeds, function (feed_id, nbUnreads) { - feed_id = 'f_' + feed_id; - const elem = document.getElementById(feed_id), - feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; - - if ((incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads) || isAll) && //Update of current view? - (nbUnreads - feed_unreads > 0)) { - $('#new-article').attr('aria-hidden', 'false').show(); - new_articles = true; - } - }); + const req = new XMLHttpRequest(); + req.open('GET', './?c=javascript&a=nbUnreadsPerFeed', true); + req.responseType = 'json'; + req.onload = function (e) { + const json = xmlHttpRequestJson(this); + const isAll = document.querySelector('.category.all.active'); + let new_articles = false; + + Object.keys(json.feeds).forEach(function (feed_id) { + const nbUnreads = json.feeds[feed_id]; + feed_id = 'f_' + feed_id; + const elem = document.getElementById(feed_id), + feed_unreads = elem ? str2int(elem.getAttribute('data-unread')) : 0; + + if ((incUnreadsFeed(null, feed_id, nbUnreads - feed_unreads) || isAll) && //Update of current view? + (nbUnreads - feed_unreads > 0)) { + const newArticle = document.getElementById('new-article'); + newArticle.setAttribute('aria-hidden', 'false'); + newArticle.style.display = 'block'; + new_articles = true; + } + }); - let nbUnreadTags = 0; + let nbUnreadTags = 0; - $.each(data.tags, function (tag_id, nbUnreads) { - nbUnreadTags += nbUnreads; - $('#t_' + tag_id).attr('data-unread', nbUnreads) - .children('.item-title').attr('data-unread', numberFormat(nbUnreads)); - }); + Object.keys(json.tags).forEach(function (tag_id) { + const nbUnreads = json.tags[tag_id]; + nbUnreadTags += nbUnreads; + const tag = document.getElementById('t_' + tag_id); + if (tag) { + tag.setAttribute('data-unread', nbUnreads); + tag.querySelector('.item-title').setAttribute('data-unread', numberFormat(nbUnreads)); + } + }); - $('.category.tags').attr('data-unread', nbUnreadTags) - .find('.title').attr('data-unread', numberFormat(nbUnreadTags)); + const tags = document.querySelector('.category.tags'); + if (tags) { + tags.setAttribute('data-unread', nbUnreadTags); + tags.querySelector('.title').setAttribute('data-unread', numberFormat(nbUnreadTags)); + } - const nb_unreads = str2int($('.category.all .title').attr('data-unread')); + const title = document.querySelector('.category.all .title'), + nb_unreads = title ? str2int(title.getAttribute('data-unread')) : 0; - if (nb_unreads > 0 && new_articles) { - faviconNbUnread(nb_unreads); - notifs_html5_show(nb_unreads); - } - }); + if (nb_unreads > 0 && new_articles) { + faviconNbUnread(nb_unreads); + notifs_html5_show(nb_unreads); + } + }; + req.send(); } // @@ -1177,49 +1209,59 @@ var url_load_more = '', box_load_more = null; function load_more_posts() { - if (load_more || url_load_more === '' || box_load_more === null) { + if (load_more || !url_load_more || !box_load_more) { return; } - load_more = true; document.getElementById('load_more').classList.add('loading'); - $.get(url_load_more, function (data) { - box_load_more.children('.flux:last').after($('#stream', data).children('.flux, .day')); - $('.pagination').replaceWith($('.pagination', data)); - if (context.display_order === 'ASC') { - $('#nav_menu_read_all .read_all').attr( - 'formaction', $('#bigMarkAsRead').attr('formaction') - ); - } else { - $('#bigMarkAsRead').attr( - 'formaction', $('#nav_menu_read_all .read_all').attr('formaction') - ); - } - $('[id^=day_]').each(function (i) { - const ids = $('[id="' + this.id + '"]'); - if (ids.length > 1) { - $('[id="' + this.id + '"]:gt(0)').remove(); + const req = new XMLHttpRequest(); + req.open('GET', url_load_more, true); + req.responseType = 'document'; + req.onload = function (e) { + const html = this.response, + formPagination = document.getElementById('mark-read-pagination'); + + const streamAdopted = document.adoptNode(html.getElementById('stream')); + streamAdopted.querySelectorAll('.flux, .day').forEach(function (div) { + box_load_more.insertBefore(div, formPagination); + }); + + const paginationOld = formPagination.querySelector('.pagination'), + paginationNew = streamAdopted.querySelector('.pagination'); + formPagination.replaceChild(paginationNew, paginationOld); + + if (context.display_order === 'ASC') { + document.querySelector('#nav_menu_read_all .read_all').formAction = + document.getElementById('bigMarkAsRead').formAction; + } else { + const bigMarkAsRead = document.getElementById('bigMarkAsRead'); + if (bigMarkAsRead) { + bigMarkAsRead.formAction = document.querySelector('#nav_menu_read_all .read_all').formAction; + } } - }); - init_load_more(box_load_more); + document.querySelectorAll('[id^=day_]').forEach(function (div) { + const ids = document.querySelectorAll('[id="' + div.id + '"]'); + for (let i = ids.length - 1; i > 0; i--) { //Keep only the first + ids[i].remove(); + } + }); - const bigMarkAsRead = document.getElementById('bigMarkAsRead'), - div_load_more = document.getElementById('load_more'); - if (bigMarkAsRead) { - bigMarkAsRead.removeAttribute('disabled'); - } - if (div_load_more) { - div_load_more.classList.remove('loading'); - } + init_load_more(box_load_more); - load_more = false; - }); -} + const bigMarkAsRead = document.getElementById('bigMarkAsRead'), + div_load_more = document.getElementById('load_more'); + if (bigMarkAsRead) { + bigMarkAsRead.removeAttribute('disabled'); + } + if (div_load_more) { + div_load_more.classList.remove('loading'); + } -function focus_search() { - $('#search').focus(); + load_more = false; + }; + req.send(); } var freshrssLoadMoreEvent = document.createEvent('Event'); @@ -1229,193 +1271,40 @@ function init_load_more(box) { box_load_more = box; document.body.dispatchEvent(freshrssLoadMoreEvent); - const $next_link = $('#load_more'); - if (!$next_link.length) { + const next_link = document.getElementById('load_more'); + if (!next_link) { // no more article to load url_load_more = ''; return; } - url_load_more = $next_link.attr('href'); + url_load_more = next_link.href; - $next_link.click(function () { - load_more_posts(); - return false; - }); + next_link.onclick = function (e) { + load_more_posts(); + return false; + }; } // -// -function poormanSalt() { //If crypto.getRandomValues is not available - const base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789/abcdefghijklmnopqrstuvwxyz'; - let text = '$2a$04$'; - for (let i = 22; i > 0; i--) { - text += base.charAt(Math.floor(Math.random() * 64)); - } - return text; -} - -function init_crypto_form() { - /* globals dcodeIO */ - const $crypto_form = $('#crypto-form'); - if ($crypto_form.length === 0) { - return; - } - - if (!(window.dcodeIO)) { - if (window.console) { - console.log('FreshRSS waiting for bcrypt.js…'); - } - setTimeout(init_crypto_form, 100); - return; - } - - $crypto_form.on('submit', function () { - const $submit_button = $(this).find('button[type="submit"]'); - $submit_button.attr('disabled', ''); - - let success = false; - $.ajax({ - url: './?c=javascript&a=nonce&user=' + $('#username').val(), - dataType: 'json', - async: false - }).done(function (data) { - if (!data.salt1 || !data.nonce) { - openNotification('Invalid user!', 'bad'); - } else { - try { - const strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function'), - s = dcodeIO.bcrypt.hashSync($('#passwordPlain').val(), data.salt1), - c = dcodeIO.bcrypt.hashSync(data.nonce + s, strong ? dcodeIO.bcrypt.genSaltSync(4) : poormanSalt()); - $('#challenge').val(c); - if (!s || !c) { - openNotification('Crypto error!', 'bad'); - } else { - success = true; - } - } catch (e) { - openNotification('Crypto exception! ' + e, 'bad'); +function init_confirm_action() { + document.body.onclick = function (ev) { + const b = ev.target.closest('.confirm'); + if (b) { + let str_confirmation = this.getAttribute('data-str-confirm'); + if (!str_confirmation) { + str_confirmation = context.i18n.confirmation_default; } + return confirm(str_confirmation); } - }).fail(function () { - openNotification('Communication error!', 'bad'); - }); - - $submit_button.removeAttr('disabled'); - return success; - }); -} -// - -function init_confirm_action() { - $('body').on('click', '.confirm', function () { - let str_confirmation = $(this).attr('data-str-confirm'); - if (!str_confirmation) { - str_confirmation = i18n.confirmation_default; - } - - return confirm(str_confirmation); - }); - $('button.confirm').removeAttr('disabled'); -} - -function init_print_action() { - $('.item.share > a[href="#"]').click(function (e) { - const content = '' + - $(e.target).closest('.flux_content').find('.content').html() + - ''; - - const tmp_window = window.open(); - tmp_window.document.writeln(content); - tmp_window.document.close(); - tmp_window.focus(); - tmp_window.print(); - tmp_window.close(); - - return false; - }); -} - -function init_post_action() { - $('.item.share > a[href="POST"]').click(function (e) { - e.preventDefault(); - const $form = $(this).next('form'); - $.post($form.data('url'), $form.serialize()); - }); -} - -var shares = 0; - -function init_share_observers() { - shares = $('.group-share').length; - - $('.share.add').on('click', function (e) { - const $opt = $(this).siblings('select').find(':selected'); - let row = $(this).parents('form').data($opt.data('form')); - row = row.replace(/##label##/g, $opt.html().trim()); - row = row.replace(/##type##/g, $opt.val()); - row = row.replace(/##help##/g, $opt.data('help')); - row = row.replace(/##key##/g, shares); - row = row.replace(/##method##/g, $opt.data('method')); - row = row.replace(/##field##/g, $opt.data('field')); - $(this).parents('.form-group').before(row); - shares++; - - return false; - }); -} - -function init_stats_observers() { - $('.select-change').on('change', function (e) { - redirect($(this).find(':selected').data('url')); - }); -} - -function init_remove_observers() { - $('.post').on('click', 'a.remove', function (e) { - const remove_what = $(this).attr('data-remove'); - if (remove_what !== undefined) { - $('#' + remove_what).remove(); - } - return false; - }); -} - -function init_feed_observers() { - $('select[id="category"]').on('change', function () { - const $detail = $('#new_category_name').parent(); - if ($(this).val() === 'nc') { - $detail.attr('aria-hidden', 'false').show(); - $detail.find('input').focus(); - } else { - $detail.attr('aria-hidden', 'true').hide(); - } - }); -} - -function init_password_observers() { - $('.toggle-password').on('mousedown', function (e) { - const $button = $(this), - $passwordField = $('#' + $button.attr('data-toggle')); - $passwordField.attr('type', 'text'); - $button.addClass('active'); - return false; - }).on('mouseup', function (e) { - const $button = $(this), - $passwordField = $('#' + $button.attr('data-toggle')); - $passwordField.attr('type', 'password'); - $button.removeClass('active'); - return false; - }); + }; + document.querySelectorAll('button.confirm').forEach(function (b) { b.disabled = false; }); } function faviconNbUnread(n) { if (typeof n === 'undefined') { - n = str2int($('.category.all .title').attr('data-unread')); + const t = document.querySelector('.category.all .title'); + n = t ? str2int(t.getAttribute('data-unread')) : 0; } //http://remysharp.com/2010/08/24/dynamic-favicons/ const canvas = document.createElement('canvas'), @@ -1442,79 +1331,16 @@ function faviconNbUnread(n) { ctx.fillText(text, 0, canvas.height - 1); } link.href = canvas.toDataURL('image/png'); - $('link[rel~=icon]').remove(); + document.querySelector('link[rel~=icon]').remove(); document.head.appendChild(link); }; img.src = '../favicon.ico'; } } -function init_slider_observers() { - const $slider = $('#slider'), - $closer = $('#close-slider'); - if ($slider.length < 1) { - return; - } - - $('.post').on('click', '.open-slider', function () { - if (ajax_loading) { - return false; - } - - ajax_loading = true; - - $.ajax({ - type: 'GET', - url: $(this).attr('href'), - data: { ajax: true } - }).done(function (data) { - $slider.html(data); - $closer.addClass('active'); - $slider.addClass('active'); - ajax_loading = false; - }); - - return false; - }); - - $closer.on('click', function () { - $closer.removeClass('active'); - $slider.removeClass('active'); - return false; - }); -} - -function init_configuration_alert() { - $(window).on('submit', function (e) { - window.hasSubmit = true; - }); - $(window).on('beforeunload', function (e) { - if (window.hasSubmit) { - return; - } - const inputs = document.querySelectorAll('[data-leave-validation]'); - for (let i = inputs.length - 1; i >= 0; i--) { - const input = inputs[i]; - if (input.type === 'checkbox' || input.type === 'radio') { - if (input.checked != input.getAttribute('data-leave-validation')) { - return false; - } - } else if (input.value != input.getAttribute('data-leave-validation')) { - return false; - } - } - }); -} - -function init_subscription() { - $('body').on('click', '.bookmarkClick', function (e) { - return false; - }); -} - function init_normal() { - $stream = $('#stream'); - if ($stream.length < 1) { + const stream = document.getElementById('stream'); + if (!stream) { if (window.console) { console.log('FreshRSS waiting for content…'); } @@ -1522,59 +1348,32 @@ function init_normal() { return; } init_column_categories(); - init_stream($stream); + init_stream(stream); init_shortcuts(); init_actualize(); faviconNbUnread(); } function init_beforeDOM() { - if (!window.$) { - if (window.console) { - console.log('FreshRSS waiting for jQuery…'); - } - setTimeout(init_beforeDOM, 100); - return; - } if (['normal', 'reader', 'global'].indexOf(context.current_view) >= 0) { init_normal(); } } function init_afterDOM() { - if (!window.$) { - if (window.console) { - console.log('FreshRSS waiting again for jQuery…'); - } - setTimeout(init_afterDOM, 100); - return; - } init_notifications(); init_confirm_action(); - $stream = $('#stream'); - if ($stream.length > 0) { - init_load_more($stream); + const stream = document.getElementById('stream'); + if (stream) { + init_load_more(stream); init_posts(); init_nav_entries(); - init_dynamic_tags(); - init_print_action(); - init_post_action(); init_notifs_html5(); setInterval(refreshUnreads, 120000); - } else { - init_subscription(); - init_crypto_form(); - init_share_observers(); - init_remove_observers(); - init_feed_observers(); - init_password_observers(); - init_stats_observers(); - init_slider_observers(); - init_configuration_alert(); } if (window.console) { - console.log('FreshRSS init done.'); + console.log('FreshRSS main init done.'); } } @@ -1582,11 +1381,11 @@ init_beforeDOM(); //Can be called before DOM is fully loaded if (document.readyState && document.readyState !== 'loading') { init_afterDOM(); -} else if (document.addEventListener) { +} else { document.addEventListener('DOMContentLoaded', function () { - if (window.console) { - console.log('FreshRSS waiting for DOMContentLoaded…'); - } - init_afterDOM(); - }, false); + if (window.console) { + console.log('FreshRSS waiting for DOMContentLoaded…'); + } + init_afterDOM(); + }, false); } diff --git a/p/scripts/repartition.js b/p/scripts/repartition.js index be70456fa..e71fa71c4 100644 --- a/p/scripts/repartition.js +++ b/p/scripts/repartition.js @@ -1,6 +1,6 @@ "use strict"; /* globals Flotr, numberFormat */ -/* jshint globalstrict: true */ +/* jshint esversion:6, strict:global */ function initStats() { if (!window.Flotr) { @@ -10,7 +10,7 @@ function initStats() { window.setTimeout(initStats, 50); return; } - var jsonRepartition = document.getElementById('jsonRepartition'), + const jsonRepartition = document.getElementById('jsonRepartition'), stats = JSON.parse(jsonRepartition.innerHTML); jsonRepartition.outerHTML = ''; // Entry per hour diff --git a/p/scripts/shortcut.js b/p/scripts/shortcut.js deleted file mode 100644 index e78cf6f5e..000000000 --- a/p/scripts/shortcut.js +++ /dev/null @@ -1,225 +0,0 @@ -/** - * http://www.openjs.com/scripts/events/keyboard_shortcuts/ - * Version : 2.01.B - * By Binny V A - * License : BSD - */ -shortcut = { - 'all_shortcuts':{},//All the shortcuts are stored in this array - 'add': function(shortcut_combination,callback,opt) { - //Provide a set of default options - var default_options = { - 'type':'keydown', - 'propagate':false, - 'disable_in_input':false, - 'target':document, - 'keycode':false - } - if(!opt) opt = default_options; - else { - for(var dfo in default_options) { - if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo]; - } - } - - var ele = opt.target; - if(typeof opt.target == 'string') ele = document.getElementById(opt.target); - var ths = this; - shortcut_combination = shortcut_combination.toLowerCase(); - - //The function to be called at keypress - var func = function(e) { - e = e || window.event; - - if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields - var element; - if(e.target) element=e.target; - else if(e.srcElement) element=e.srcElement; - if(element.nodeType==3) element=element.parentNode; - - if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return; - } - - //Find Which key is pressed - if (e.keyCode) code = e.keyCode; - else if (e.which) code = e.which; - if (code == 32 || (code >= 48 && code <= 90) || (code >= 96 && code <= 111) || (code >= 186 && code <= 192) || (code >= 219 && code <= 222)) { //FreshRSS - var character = String.fromCharCode(code).toLowerCase(); - } - - if(code == 188) character=","; //If the user presses , when the type is onkeydown - if(code == 190) character="."; //If the user presses , when the type is onkeydown - - var keys = shortcut_combination.split("+"); - //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked - var kp = 0; - - //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken - var shift_nums = { - "`":"~", - "1":"!", - "2":"@", - "3":"#", - "4":"$", - "5":"%", - "6":"^", - "7":"&", - "8":"*", - "9":"(", - "0":")", - "-":"_", - "=":"+", - ";":":", - "'":"\"", - ",":"<", - ".":">", - "/":"?", - "\\":"|" - } - //Special Keys - and their codes - var special_keys = { - 'esc':27, - 'escape':27, - 'tab':9, - 'space':32, - 'return':13, - 'enter':13, - 'backspace':8, - - 'scrolllock':145, - 'scroll_lock':145, - 'scroll':145, - 'capslock':20, - 'caps_lock':20, - 'caps':20, - 'numlock':144, - 'num_lock':144, - 'num':144, - - 'pause':19, - 'break':19, - - 'insert':45, - 'home':36, - 'delete':46, - 'end':35, - - 'pageup':33, - 'page_up':33, - 'pu':33, - - 'pagedown':34, - 'page_down':34, - 'pd':34, - - 'left':37, - 'up':38, - 'right':39, - 'down':40, - - 'f1':112, - 'f2':113, - 'f3':114, - 'f4':115, - 'f5':116, - 'f6':117, - 'f7':118, - 'f8':119, - 'f9':120, - 'f10':121, - 'f11':122, - 'f12':123 - } - - var modifiers = { - shift: { wanted:false, pressed:false}, - ctrl : { wanted:false, pressed:false}, - alt : { wanted:false, pressed:false}, - meta : { wanted:false, pressed:false} //Meta is Mac specific - }; - - if(e.ctrlKey) modifiers.ctrl.pressed = true; - if(e.shiftKey) modifiers.shift.pressed = true; - if(e.altKey) modifiers.alt.pressed = true; - if(e.metaKey) modifiers.meta.pressed = true; - - for(var i=0; k=keys[i],i 1) { //If it is a special key - if(special_keys[k] == code) kp++; - - } else if(opt['keycode']) { - if(opt['keycode'] == code) kp++; - - } else { //The special keys did not match - if(character == k) kp++; - else { - if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase - character = shift_nums[character]; - if(character == k) kp++; - } - } - } - } - - if(kp == keys.length && - modifiers.ctrl.pressed == modifiers.ctrl.wanted && - modifiers.shift.pressed == modifiers.shift.wanted && - modifiers.alt.pressed == modifiers.alt.wanted && - modifiers.meta.pressed == modifiers.meta.wanted) { - callback(e); - - if(!opt['propagate']) { //Stop the event - //e.cancelBubble is supported by IE - this will kill the bubbling process. - e.cancelBubble = true; - e.returnValue = false; - - //e.stopPropagation works in Firefox. - if (e.stopPropagation) { - e.stopPropagation(); - e.preventDefault(); - } - return false; - } - } - } - this.all_shortcuts[shortcut_combination] = { - 'callback':func, - 'target':ele, - 'event': opt['type'] - }; - //Attach the function with the event - if(ele.addEventListener) ele.addEventListener(opt['type'], func, false); - else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func); - else ele['on'+opt['type']] = func; - }, - - //Remove the shortcut - just specify the shortcut and I will remove the binding - 'remove':function(shortcut_combination) { - shortcut_combination = shortcut_combination.toLowerCase(); - var binding = this.all_shortcuts[shortcut_combination]; - delete(this.all_shortcuts[shortcut_combination]) - if(!binding) return; - var type = binding['event']; - var ele = binding['target']; - var callback = binding['callback']; - - if(ele.detachEvent) ele.detachEvent('on'+type, callback); - else if(ele.removeEventListener) ele.removeEventListener(type, callback, false); - else ele['on'+type] = false; - } -} \ No newline at end of file diff --git a/p/scripts/stats.js b/p/scripts/stats.js index 9cd14721c..b47188d77 100644 --- a/p/scripts/stats.js +++ b/p/scripts/stats.js @@ -1,6 +1,6 @@ "use strict"; /* globals Flotr, numberFormat */ -/* jshint globalstrict: true */ +/* jshint esversion:6, strict:global */ function initStats() { if (!window.Flotr) { @@ -10,12 +10,12 @@ function initStats() { window.setTimeout(initStats, 50); return; } - var jsonStats = document.getElementById('jsonStats'), + const jsonStats = document.getElementById('jsonStats'), stats = JSON.parse(jsonStats.innerHTML); jsonStats.outerHTML = ''; // Entry per day - var avg = []; - for (var i = -31; i <= 0; i++) { + const avg = []; + for (let i = -31; i <= 0; i++) { avg.push([i, stats.average]); } Flotr.draw(document.getElementById('statsEntryPerDay'), diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index 099aee916..2ea058786 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -280,7 +280,7 @@ a.btn { left: 0; right: 0; display: block; z-index: -10; - cursor: default; + cursor: default; } .separator { display: block; @@ -418,8 +418,10 @@ a.btn { } .tree-folder-items { - padding: 0; list-style: none; + max-height: 200em; + padding: 0; + transition: max-height .3s linear; } .tree-folder-title { display: block; @@ -502,7 +504,8 @@ a.btn { padding: 0px 15px; } .aside_feed .tree-folder-items:not(.active) { - display: none; + max-height: 0; + overflow: hidden; } .aside_feed .tree-folder-items .dropdown { vertical-align: top; @@ -632,9 +635,13 @@ br + br + br { z-index: 10; background: #fff; border: 1px solid #aaa; + opacity: 1; + visibility: visible; + transition: visibility 0s, opacity .3s linear; } .notification.closed { - display: none; + opacity: 0; + visibility: hidden; } .notification a.close { position: absolute; @@ -710,15 +717,15 @@ br + br + br { /*=== LOGIN VIEW */ /*================*/ .formLogin .header > .item { - padding: 10px 30px; + padding: 10px 30px; } .formLogin .header > .item.title { - text-align: left; + text-align: left; } .formLogin .header > .item.configure { - text-align: right; + text-align: right; } @@ -731,14 +738,29 @@ br + br + br { #stream.global .box { text-align: left; } - +#global > #panel { + bottom: 99vh; + display: block; + transition: visibility .3s, bottom .3s; + visibility: hidden; +} +#global > #panel.visible { + bottom: 1em; + visibility: visible; +} /*=== Panel */ #overlay { - display: none; position: fixed; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.9); + opacity: 0; + transition: visibility .3s, opacity .3s; + visibility: hidden; +} +#overlay.visible { + opacity: 1; + visibility: visible; } #panel { display: none; -- cgit v1.2.3 From 7aa7aee5db0a811c6c56a86f7c8d03ced971947d Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Feb 2019 15:34:20 +0100 Subject: Changelog 2234 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ef11bf49..ee7c5602c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,8 @@ * Fix encoding problem in Fever API [#2241](https://github.com/FreshRSS/FreshRSS/issues/2241) * UI * New themes *Ansum* and *Mapco* [#2245](https://github.com/FreshRSS/FreshRSS/pull/2245) + * Rewrite jQuery and keyboard shortcut code as native JavaScript ES6 (except for graphs on the statistics pages) [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) * Batch scroll-as-read for better client-side and server-side performance [#2199](https://github.com/FreshRSS/FreshRSS/pull/2199) - * Rewrite some jQuery code as native JavaScript [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) * Deployment * Docker image updated to Alpine 3.9 with PHP 7.2.14 and Apache 2.4.38 [#2238](https://github.com/FreshRSS/FreshRSS/pull/2238) * I18n -- cgit v1.2.3 From 0b997b58a56bd0a4e8758c72653674810092c17d Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Feb 2019 15:45:01 +0100 Subject: Removes HHVM from Travis Because HHVM removes PHP support https://www.phoronix.com/scan.php?page=news_item&px=HHVM-4.0-Released --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 24e0bf36b..44bc59e3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ php: - '7.0' - '7.1' - '7.2' - - hhvm install: # newest version without https://github.com/squizlabs/PHP_CodeSniffer/pull/1404 -- cgit v1.2.3 From 75a802f623672dab0179d64a0e84d63d212bcd93 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Feb 2019 15:51:28 +0100 Subject: Changelog 2249 https://github.com/FreshRSS/FreshRSS/pull/2249 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee7c5602c..f9d1bc1d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ * Docker image updated to Alpine 3.9 with PHP 7.2.14 and Apache 2.4.38 [#2238](https://github.com/FreshRSS/FreshRSS/pull/2238) * I18n * Improved Korean [#2242](https://github.com/FreshRSS/FreshRSS/pull/2242) +* Misc. + * Remove HHMV from Travis continuous integration [#2249](https://github.com/FreshRSS/FreshRSS/pull/2249) ## 2019-01-26 FreshRSS 1.13.1 -- cgit v1.2.3 From 75356c64a2b13a89497bd8125c1bfe79293084f9 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 13 Feb 2019 17:18:21 +0100 Subject: Remove deprecated CSP child-src It's been probably long enough since https://github.com/FreshRSS/FreshRSS/pull/1099 --- app/FreshRSS.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 9371081e4..1dc80718e 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -117,7 +117,7 @@ class FreshRSS extends Minz_FrontController { } }, FreshRSS_Context::$user_conf->sharing)); $connectSrc = count($urlToAuthorize) ? sprintf("; connect-src 'self' %s", implode(' ', $urlToAuthorize)) : ''; - header(sprintf("Content-Security-Policy: default-src 'self'; child-src *; frame-src *; img-src * data:; media-src *%s", $connectSrc)); + header(sprintf("Content-Security-Policy: default-src 'self'; frame-src *; img-src * data:; media-src *%s", $connectSrc)); break; case 'stats': header("Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'"); -- cgit v1.2.3 From 387f763482412d47769ae1a7314d56cc12986420 Mon Sep 17 00:00:00 2001 From: Quentí <33203663+Quenty31@users.noreply.github.com> Date: Sat, 16 Feb 2019 12:33:24 +0100 Subject: Odre des mots --- app/i18n/oc/admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/i18n/oc/admin.php b/app/i18n/oc/admin.php index 4a47374d7..2f8ede873 100644 --- a/app/i18n/oc/admin.php +++ b/app/i18n/oc/admin.php @@ -130,7 +130,7 @@ return array( 'category' => 'Categoria', 'entry_count' => 'Nombre d’articles', 'entry_per_category' => 'Articles per categoria', - 'entry_per_day' => 'Nombre d’articles per jorn (30 darrièrs jorns)', + 'entry_per_day' => 'Nombre d’articles per jorn (darrièrs 30 jorns)', 'entry_per_day_of_week' => 'Per jorn de la setmana (mejana : %.2f messatges)', 'entry_per_hour' => 'Per ora (mejana : %.2f messatges)', 'entry_per_month' => 'Per mes (mejana : %.2f messatges)', -- cgit v1.2.3 From 3d57714bff3462bd7dafb72ffb1ff4b7d640b3cd Mon Sep 17 00:00:00 2001 From: Quentí <33203663+Quenty31@users.noreply.github.com> Date: Sat, 16 Feb 2019 12:33:56 +0100 Subject: Ordre des mots --- app/i18n/oc/gen.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/i18n/oc/gen.php b/app/i18n/oc/gen.php index 168ea4732..7f9793283 100644 --- a/app/i18n/oc/gen.php +++ b/app/i18n/oc/gen.php @@ -68,8 +68,8 @@ return array( 'Jun' => '\\j\\u\\n\\h', 'jun' => 'junh', 'june' => 'junh', - 'last_3_month' => 'Dempuèi los tres darrièrs meses', - 'last_6_month' => 'Dempuèi los sièis darrièrs meses', + 'last_3_month' => 'Dempuèi los darrièrs tres meses', + 'last_6_month' => 'Dempuèi los darrièrs sièis meses', 'last_month' => 'Dempuèi lo mes passat', 'last_week' => 'Dempuèi la setmana passada', 'last_year' => 'Dempuèi l’annada passada', -- cgit v1.2.3 From b869c2944a01c5060d05a093d5e0c797d48bb159 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 23 Feb 2019 14:39:20 +0100 Subject: JavaScript fixes + new navigation loop behaviour (#2255) * Fixed user configuration 404 https://github.com/FreshRSS/FreshRSS/pull/2234#issuecomment-466561555 * Fixed "SPACE" shortcut bug https://github.com/FreshRSS/FreshRSS/pull/2234#issuecomment-466626412 * Use next feed / previous feed when reaching last / first article instead of looping * Jump to next / previous category when reaching last / first feed instead of looping --- app/views/user/manage.phtml | 2 +- p/scripts/extra.js | 10 ++++++-- p/scripts/main.js | 62 +++++++++++++++++++++++++++++++-------------- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/app/views/user/manage.phtml b/app/views/user/manage.phtml index 9d457f7a5..d0e5928ef 100644 --- a/app/views/user/manage.phtml +++ b/app/views/user/manage.phtml @@ -53,7 +53,7 @@
        - diff --git a/p/scripts/extra.js b/p/scripts/extra.js index 7a0ef0477..c0d0c89e1 100644 --- a/p/scripts/extra.js +++ b/p/scripts/extra.js @@ -142,8 +142,14 @@ function init_password_observers() { function init_select_observers() { document.querySelectorAll('.select-change').forEach(function (s) { s.onchange = function (ev) { - const opt = s.options[s.selectedIndex]; - location.href = opt.getAttribute('data-url'); + const opt = s.options[s.selectedIndex], + url = opt.getAttribute('data-url'); + if (url) { + s.form.querySelectorAll('[type=submit]').forEach(function (b) { + b.disabled = true; + }); + location.href = url; + } }; }); } diff --git a/p/scripts/main.js b/p/scripts/main.js index 345cbe749..90a41d767 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -374,41 +374,65 @@ function toggleContent(new_active, old_active, skipping) { } function prev_entry(skipping) { - const old_active = document.querySelector('.flux.current'), - new_active = old_active ? old_active.previousElementSibling : document.querySelector('.flux'); + const old_active = document.querySelector('.flux.current'); + let new_active = old_active; + if (new_active) { + do new_active = new_active.previousElementSibling; + while (new_active && !new_active.classList.contains('flux')); + if (!new_active) { + prev_feed(); + } + } else { + new_active = document.querySelector('.flux'); + } toggleContent(new_active, old_active, skipping); } function next_entry(skipping) { - const old_active = document.querySelector('.flux.current'), - new_active = old_active ? old_active.nextElementSibling : document.querySelector('.flux'); + const old_active = document.querySelector('.flux.current'); + let new_active = old_active; + if (new_active) { + do new_active = new_active.nextElementSibling; + while (new_active && !new_active.classList.contains('flux')); + if (!new_active) { + next_feed(); + } + } else { + new_active = document.querySelector('.flux'); + } toggleContent(new_active, old_active, skipping); } function prev_feed() { - const active_feed = document.querySelector('#aside_feed .feed.active'); - if (active_feed) { - let feed = active_feed; - do feed = feed.previousElementSibling; - while (feed && getComputedStyle(feed).display === 'none'); - if (feed) { + let found = false; + const feeds = document.querySelectorAll('#aside_feed .feed'); + for (let i = feeds.length - 1; i >= 0; i--) { + const feed = feeds[i]; + if (found && getComputedStyle(feed).display !== 'none') { feed.querySelector('a.item-title').click(); + break; + } else if (feed.classList.contains('active')) { + found = true; } - } else { + } + if (!found) { last_feed(); } } function next_feed() { - const active_feed = document.querySelector('#aside_feed .feed.active'); - if (active_feed) { - let feed = active_feed; - do feed = feed.nextElementSibling; - while (feed && getComputedStyle(feed).display === 'none'); - if (feed) { + let found = false; + const feeds = document.querySelectorAll('#aside_feed .feed'); + for (let i = 0; i < feeds.length; i++) { + const feed = feeds[i]; + if (found && getComputedStyle(feed).display !== 'none') { feed.querySelector('a.item-title').click(); + break; + } else if (feed.classList.contains('active')) { + found = true; } - } else { + } + if (!found) { first_feed(); } } @@ -664,7 +688,7 @@ function init_shortcuts() { } const s = context.shortcuts, - k = ev.key.toUpperCase(); + k = (ev.key.trim() || ev.code).toUpperCase(); if (location.hash.match(/^#dropdown-/)) { const n = parseInt(k); if (n) { -- cgit v1.2.3 From 2b2d9583cd2a4dc39c6f95dd73866c009f4480ce Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 2 Mar 2019 20:39:18 +0100 Subject: Fix mark_updated_article_unread https://github.com/FreshRSS/FreshRSS/issues/2200 --- app/Controllers/feedController.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 74c9eacfa..42cb46834 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -353,11 +353,10 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } else { //This entry already exists but has been updated //Minz_Log::debug('Entry with GUID `' . $entry->guid() . '` updated in feed ' . $feed->url(false) . //', old hash ' . $existingHash . ', new hash ' . $entry->hash()); - $mark_updated_article_unread = $feed->attributes('mark_updated_article_unread') !== null ? ( - $feed->attributes('mark_updated_article_unread') - ) : FreshRSS_Context::$user_conf->mark_updated_article_unread; + $mark_updated_article_unread = $feed->attributes('mark_updated_article_unread') !== null ? + $feed->attributes('mark_updated_article_unread') : FreshRSS_Context::$user_conf->mark_updated_article_unread; $needFeedCacheRefresh = $mark_updated_article_unread; - $entry->_isRead(FreshRSS_Context::$user_conf->mark_updated_article_unread ? false : null); //Change is_read according to policy. + $entry->_isRead($mark_updated_article_unread ? false : null); //Change is_read according to policy. $entry = Minz_ExtensionManager::callHook('entry_before_insert', $entry); if ($entry === null) { -- cgit v1.2.3 From f1978da394eb6e400d9aa58faf5322129ad635ce Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 2 Mar 2019 20:43:51 +0100 Subject: Boolean error --- app/Controllers/feedController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 42cb46834..179a8971e 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -356,7 +356,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $mark_updated_article_unread = $feed->attributes('mark_updated_article_unread') !== null ? $feed->attributes('mark_updated_article_unread') : FreshRSS_Context::$user_conf->mark_updated_article_unread; $needFeedCacheRefresh = $mark_updated_article_unread; - $entry->_isRead($mark_updated_article_unread ? false : null); //Change is_read according to policy. + $entry->_isRead($mark_updated_article_unread ? true : null); //Change is_read according to policy. $entry = Minz_ExtensionManager::callHook('entry_before_insert', $entry); if ($entry === null) { -- cgit v1.2.3 From 7d76acad04f1ac31829611c90a8941104f74b6a4 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 2 Mar 2019 20:56:03 +0100 Subject: Re-introduce Travis workaround --- app/Controllers/feedController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 179a8971e..57c2e392d 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -353,8 +353,9 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } else { //This entry already exists but has been updated //Minz_Log::debug('Entry with GUID `' . $entry->guid() . '` updated in feed ' . $feed->url(false) . //', old hash ' . $existingHash . ', new hash ' . $entry->hash()); - $mark_updated_article_unread = $feed->attributes('mark_updated_article_unread') !== null ? - $feed->attributes('mark_updated_article_unread') : FreshRSS_Context::$user_conf->mark_updated_article_unread; + $mark_updated_article_unread = $feed->attributes('mark_updated_article_unread') !== null ? ( + $feed->attributes('mark_updated_article_unread') + ) : FreshRSS_Context::$user_conf->mark_updated_article_unread; $needFeedCacheRefresh = $mark_updated_article_unread; $entry->_isRead($mark_updated_article_unread ? true : null); //Change is_read according to policy. -- cgit v1.2.3 From 2856f7b8b47abcddf20589e19be1f5b98caa1ae3 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 2 Mar 2019 21:06:56 +0100 Subject: Revert wrong boolean --- app/Controllers/feedController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 57c2e392d..d5ae235ad 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -357,7 +357,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $feed->attributes('mark_updated_article_unread') ) : FreshRSS_Context::$user_conf->mark_updated_article_unread; $needFeedCacheRefresh = $mark_updated_article_unread; - $entry->_isRead($mark_updated_article_unread ? true : null); //Change is_read according to policy. + $entry->_isRead($mark_updated_article_unread ? false : null); //Change is_read according to policy. $entry = Minz_ExtensionManager::callHook('entry_before_insert', $entry); if ($entry === null) { -- cgit v1.2.3 From fc8fb0a7ee0d98f8c31be3bd6e76719ebb0e68ee Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 2 Mar 2019 21:49:20 +0100 Subject: Docker image alternative using Ubuntu (#2205) * Docker image alternative using Ubuntu Ubuntu seems to be faster, cf. e.g. PHPBench. It is quite usual for Docker images to offer both a Debian/Ubuntu and an Alpine version, so we could also do the same if there is any need. Follow-up of https://github.com/FreshRSS/FreshRSS/pull/2202 * Only explicit use of Apache confs Fix double-logging issue * Explicit ServerTokens OS Default Apache configuration in Ubuntu, which was removed when disabling all confs. It is also the default Apache configuration in Alpine. * Take advantage of syslog for actualization Same than for Alpine https://github.com/FreshRSS/FreshRSS/pull/2208/commits/43ab629e27799cb28ec28ad409a512e128d11e97 * COPY_SYSLOG_TO_STDERR Same as https://github.com/FreshRSS/FreshRSS/pull/2213 * Update to libapache2-mod-php instead of php-fpm * Default to Ubuntu Ubuntu mod-php wins, being ~14% faster than Ubuntu php-fpm (which was ~300% faster than Alpine mod-php) --- Docker/Dockerfile | 44 ++++++++++++++++++++++++-------------------- Docker/Dockerfile-Alpine | 34 ++++++++++++++++++++++++++++++++++ Docker/FreshRSS.Apache.conf | 1 + 3 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 Docker/Dockerfile-Alpine diff --git a/Docker/Dockerfile b/Docker/Dockerfile index cd0f521a0..53feb31d4 100644 --- a/Docker/Dockerfile +++ b/Docker/Dockerfile @@ -1,28 +1,31 @@ -FROM alpine:3.9 +FROM ubuntu:18.10 ENV TZ UTC +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone -RUN apk add --no-cache \ - apache2 php7-apache2 \ - php7 php7-curl php7-gmp php7-intl php7-mbstring php7-xml php7-zip \ - php7-ctype php7-dom php7-fileinfo php7-iconv php7-json php7-session php7-simplexml php7-xmlreader php7-zlib \ - php7-pdo_sqlite php7-pdo_mysql php7-pdo_pgsql +RUN apt update && \ + apt install --no-install-recommends -y \ + cron \ + apache2 libapache2-mod-php \ + php-curl php-intl php-mbstring php-xml php-zip \ + php-sqlite3 php-mysql php-pgsql && \ + rm -rf /var/lib/apt/lists/ -RUN mkdir -p /var/www/FreshRSS /run/apache2/ +RUN mkdir -p /var/www/FreshRSS /run/apache2/ /run/php/ WORKDIR /var/www/FreshRSS COPY . /var/www/FreshRSS -COPY ./Docker/*.Apache.conf /etc/apache2/conf.d/ - -RUN rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ - /etc/apache2/conf.d/status.conf /etc/apache2/conf.d/userdir.conf && \ - sed -r -i "/^\s*LoadModule .*mod_(alias|autoindex|negotiation|status).so$/s/^/#/" \ - /etc/apache2/httpd.conf && \ - sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|headers|mime|setenvif).so$/s/^\s*#//" \ - /etc/apache2/httpd.conf && \ - sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" \ - /etc/apache2/httpd.conf && \ - echo "17,37 * * * * su apache -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' 2>> /proc/1/fd/2 > /tmp/FreshRSS.log" >> \ +COPY ./Docker/*.Apache.conf /etc/apache2/sites-available/ + +RUN a2dismod -f alias autoindex negotiation status && \ + a2enmod deflate expires headers mime proxy_fcgi setenvif && \ + a2disconf '*' && \ + a2dissite '*' && \ + a2ensite 'FreshRSS*' + +RUN sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" /etc/apache2/apache2.conf && \ + sed -r -i "/^\s*Listen /s/^/#/" /etc/apache2/ports.conf && \ + echo "17,37 su apache -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' 2>> /proc/1/fd/2 > /tmp/FreshRSS.log" >> \ /var/spool/cron/crontabs/root ENV COPY_SYSLOG_TO_STDERR On @@ -30,5 +33,6 @@ ENV CRON_MIN '' ENTRYPOINT ["./Docker/entrypoint.sh"] EXPOSE 80 -CMD ([ -z "$CRON_MIN" ] || crond -d 6) && \ - exec httpd -D FOREGROUND +CMD ([ -z "$CRON_MIN" ] || cron) && \ + . /etc/apache2/envvars && \ + exec apache2 -D FOREGROUND diff --git a/Docker/Dockerfile-Alpine b/Docker/Dockerfile-Alpine new file mode 100644 index 000000000..cd0f521a0 --- /dev/null +++ b/Docker/Dockerfile-Alpine @@ -0,0 +1,34 @@ +FROM alpine:3.9 + +ENV TZ UTC + +RUN apk add --no-cache \ + apache2 php7-apache2 \ + php7 php7-curl php7-gmp php7-intl php7-mbstring php7-xml php7-zip \ + php7-ctype php7-dom php7-fileinfo php7-iconv php7-json php7-session php7-simplexml php7-xmlreader php7-zlib \ + php7-pdo_sqlite php7-pdo_mysql php7-pdo_pgsql + +RUN mkdir -p /var/www/FreshRSS /run/apache2/ +WORKDIR /var/www/FreshRSS + +COPY . /var/www/FreshRSS +COPY ./Docker/*.Apache.conf /etc/apache2/conf.d/ + +RUN rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \ + /etc/apache2/conf.d/status.conf /etc/apache2/conf.d/userdir.conf && \ + sed -r -i "/^\s*LoadModule .*mod_(alias|autoindex|negotiation|status).so$/s/^/#/" \ + /etc/apache2/httpd.conf && \ + sed -r -i "/^\s*#\s*LoadModule .*mod_(deflate|expires|headers|mime|setenvif).so$/s/^\s*#//" \ + /etc/apache2/httpd.conf && \ + sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" \ + /etc/apache2/httpd.conf && \ + echo "17,37 * * * * su apache -s /bin/sh -c 'php /var/www/FreshRSS/app/actualize_script.php' 2>> /proc/1/fd/2 > /tmp/FreshRSS.log" >> \ + /var/spool/cron/crontabs/root + +ENV COPY_SYSLOG_TO_STDERR On +ENV CRON_MIN '' +ENTRYPOINT ["./Docker/entrypoint.sh"] + +EXPOSE 80 +CMD ([ -z "$CRON_MIN" ] || crond -d 6) && \ + exec httpd -D FOREGROUND diff --git a/Docker/FreshRSS.Apache.conf b/Docker/FreshRSS.Apache.conf index 80f6389d8..6621ff16f 100644 --- a/Docker/FreshRSS.Apache.conf +++ b/Docker/FreshRSS.Apache.conf @@ -4,6 +4,7 @@ DocumentRoot /var/www/FreshRSS/p/ CustomLog /dev/stdout combined ErrorLog /dev/stderr AllowEncodedSlashes On +ServerTokens OS AllowOverride None -- cgit v1.2.3 From 60b7f5e6d966bbfb9d3c24a3b51057abd9b6e718 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 2 Mar 2019 22:53:04 +0100 Subject: Docker Ubuntu notes (#2259) https://github.com/FreshRSS/FreshRSS/pull/2205 (And removed proxy_fcgi forgotten from php-fpm) --- CHANGELOG.md | 12 +++++++----- Docker/Dockerfile | 2 +- Docker/README.md | 14 +++++++++++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9d1bc1d6..fc71fabe6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,18 @@ ## 2019-0X-XX FreshRSS 1.13.2-dev -* Bug fixing - * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) - * Fix breaking warning in Fever API [#2239](https://github.com/FreshRSS/FreshRSS/issues/2239) - * Fix encoding problem in Fever API [#2241](https://github.com/FreshRSS/FreshRSS/issues/2241) * UI * New themes *Ansum* and *Mapco* [#2245](https://github.com/FreshRSS/FreshRSS/pull/2245) * Rewrite jQuery and keyboard shortcut code as native JavaScript ES6 (except for graphs on the statistics pages) [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) * Batch scroll-as-read for better client-side and server-side performance [#2199](https://github.com/FreshRSS/FreshRSS/pull/2199) * Deployment - * Docker image updated to Alpine 3.9 with PHP 7.2.14 and Apache 2.4.38 [#2238](https://github.com/FreshRSS/FreshRSS/pull/2238) + * New default Docker image based on Ubuntu (~3 times faster, but ~2.5 times larger) [#2205](https://github.com/FreshRSS/FreshRSS/pull/2205) + * Using Ubuntu 18.10 with PHP 7.2.15 and Apache 2.4.34 + * Alpine version updated to Alpine 3.9 with PHP 7.2.14 and Apache 2.4.38 [#2238](https://github.com/FreshRSS/FreshRSS/pull/2238) +* Bug fixing + * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) + * Fix breaking warning in Fever API [#2239](https://github.com/FreshRSS/FreshRSS/issues/2239) + * Fix encoding problem in Fever API [#2241](https://github.com/FreshRSS/FreshRSS/issues/2241) * I18n * Improved Korean [#2242](https://github.com/FreshRSS/FreshRSS/pull/2242) * Misc. diff --git a/Docker/Dockerfile b/Docker/Dockerfile index 53feb31d4..8f15bec96 100644 --- a/Docker/Dockerfile +++ b/Docker/Dockerfile @@ -18,7 +18,7 @@ COPY . /var/www/FreshRSS COPY ./Docker/*.Apache.conf /etc/apache2/sites-available/ RUN a2dismod -f alias autoindex negotiation status && \ - a2enmod deflate expires headers mime proxy_fcgi setenvif && \ + a2enmod deflate expires headers mime setenvif && \ a2disconf '*' && \ a2dissite '*' && \ a2ensite 'FreshRSS*' diff --git a/Docker/README.md b/Docker/README.md index ac745c49d..ba6169ea3 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -10,6 +10,18 @@ sh get-docker.sh ``` +## [Docker tags](https://hub.docker.com/r/freshrss/freshrss/tags) +The tags correspond to FreshRSS branches and versions: +* `:latest` (default) is the `master` branch, more stable +* `:dev` is the `dev` branch, rolling release +* `:x.y.z` are specific FreshRSS releases + +### Linux: Ubuntu vs. Alpine +Our default image is based on [Ubuntu](https://www.ubuntu.com/server). We offer an alternative based on [Alpine](https://alpinelinux.org/) (with the `-alpine` tag suffix). +In [our tests](https://github.com/FreshRSS/FreshRSS/pull/2205), Ubuntu is ~3 times faster, +while Alpine is ~2.5 times [smaller on disk](https://hub.docker.com/r/freshrss/freshrss/tags) (and much faster to build). + + ## Optional: Build Docker image of FreshRSS Optional, as a *less recent* online image can be automatically fetched during the next step (run), but online images are not available for as many platforms (e.g. Raspberry Pi / ARM) as if you build yourself. @@ -20,7 +32,7 @@ git clone https://github.com/FreshRSS/FreshRSS.git cd ./FreshRSS/ git pull -sudo docker pull alpine:3.8 +sudo docker pull ubuntu:18.10 sudo docker build --tag freshrss/freshrss -f Docker/Dockerfile . ``` -- cgit v1.2.3 From 1bdc3837de6f9b2555220578bb3584651da9ab82 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 2 Mar 2019 23:07:10 +0100 Subject: Changelog 2250 2253 2255 2258 https://github.com/FreshRSS/FreshRSS/issues/2200 https://github.com/FreshRSS/FreshRSS/pull/2250 https://github.com/FreshRSS/FreshRSS/pull/2253 https://github.com/FreshRSS/FreshRSS/pull/2255 https://github.com/FreshRSS/FreshRSS/pull/2258 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc71fabe6..8835d7be0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,16 +6,21 @@ * New themes *Ansum* and *Mapco* [#2245](https://github.com/FreshRSS/FreshRSS/pull/2245) * Rewrite jQuery and keyboard shortcut code as native JavaScript ES6 (except for graphs on the statistics pages) [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) * Batch scroll-as-read for better client-side and server-side performance [#2199](https://github.com/FreshRSS/FreshRSS/pull/2199) + * Keyboard-shortcut navigation at end of feed or category continues to the next one [#2255](https://github.com/FreshRSS/FreshRSS/pull/2255) * Deployment * New default Docker image based on Ubuntu (~3 times faster, but ~2.5 times larger) [#2205](https://github.com/FreshRSS/FreshRSS/pull/2205) * Using Ubuntu 18.10 with PHP 7.2.15 and Apache 2.4.34 * Alpine version updated to Alpine 3.9 with PHP 7.2.14 and Apache 2.4.38 [#2238](https://github.com/FreshRSS/FreshRSS/pull/2238) * Bug fixing + * Fix feed option for marking modified articles as unread [#2200](https://github.com/FreshRSS/FreshRSS/issues/2200) * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) * Fix breaking warning in Fever API [#2239](https://github.com/FreshRSS/FreshRSS/issues/2239) * Fix encoding problem in Fever API [#2241](https://github.com/FreshRSS/FreshRSS/issues/2241) * I18n * Improved Korean [#2242](https://github.com/FreshRSS/FreshRSS/pull/2242) + * Improve Occitan [#2253](https://github.com/FreshRSS/FreshRSS/pull/2253) +* Security + * Remove deprecated CSP `child-src` instruction (was already replaced by `frame-src`) [#2250](https://github.com/FreshRSS/FreshRSS/pull/2250) * Misc. * Remove HHMV from Travis continuous integration [#2249](https://github.com/FreshRSS/FreshRSS/pull/2249) -- cgit v1.2.3 From 999d1b8c035f4de31026198dad93f485392df8d4 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 4 Mar 2019 21:21:38 +0100 Subject: Use getenv instead of $_SERVER for environment variables getenv() is the proper way, and $_SERVER was not working on some configurations. Improvement of https://github.com/FreshRSS/FreshRSS/pull/2213 --- constants.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.php b/constants.php index 2072e5ea1..dacbb11aa 100644 --- a/constants.php +++ b/constants.php @@ -33,7 +33,7 @@ safe_define('FRESHRSS_USERAGENT', 'FreshRSS/' . FRESHRSS_VERSION . ' (' . PHP_OS safe_define('PHP_COMPRESSION', false); // For cases when syslog is not available -safe_define('COPY_SYSLOG_TO_STDERR', isset($_SERVER['COPY_SYSLOG_TO_STDERR']) ? filter_var($_SERVER['COPY_SYSLOG_TO_STDERR'], FILTER_VALIDATE_BOOLEAN) : false); +safe_define('COPY_SYSLOG_TO_STDERR', filter_var(getenv('COPY_SYSLOG_TO_STDERR'), FILTER_VALIDATE_BOOLEAN)); // Maximum log file size in Bytes, before it will be divided by two safe_define('MAX_LOG_SIZE', 1048576); -- cgit v1.2.3 From b5e83abfc9dadce20cb4bf7024dc7dd9d0f3324b Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 9 Mar 2019 12:50:03 +0100 Subject: Add reference to Readably app https://github.com/FreshRSS/FreshRSS/issues/1406#issuecomment-469310998 --- CHANGELOG.md | 2 ++ README.fr.md | 2 ++ README.md | 2 ++ docs/en/users/06_Fever_API.md | 6 +++--- docs/fr/users/06_Fever_API.md | 3 +++ 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8835d7be0..9e36f9592 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) * Fix breaking warning in Fever API [#2239](https://github.com/FreshRSS/FreshRSS/issues/2239) * Fix encoding problem in Fever API [#2241](https://github.com/FreshRSS/FreshRSS/issues/2241) +* API + * Supported by [Readably](https://play.google.com/store/apps/details?id=com.isaiasmatewos.readably) (client for Android using Fever API) * I18n * Improved Korean [#2242](https://github.com/FreshRSS/FreshRSS/pull/2242) * Improve Occitan [#2253](https://github.com/FreshRSS/FreshRSS/pull/2253) diff --git a/README.fr.md b/README.fr.md index 58647ae4a..157979f93 100644 --- a/README.fr.md +++ b/README.fr.md @@ -196,6 +196,8 @@ Voir notre [documentation sur l’API Fever](https://freshrss.github.io/FreshRSS Tout client supportant une API de type Fever ; Sélection : +* Android + * [Readably](https://play.google.com/store/apps/details?id=com.isaiasmatewos.readably) (Propriétaire) * iOS * [Fiery Feeds](https://itunes.apple.com/app/fiery-feeds-rss-reader/id1158763303) (Propriétaire) * [Unread](https://itunes.apple.com/app/unread-rss-reader/id1252376153) (Propriétaire) diff --git a/README.md b/README.md index 190ee5639..b91571e3e 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,8 @@ See our [Fever API documentation](https://freshrss.github.io/FreshRSS/en/users/0 Supported clients are: +* Android + * [Readably](https://play.google.com/store/apps/details?id=com.isaiasmatewos.readably) (Closed source) * iOS * [Fiery Feeds](https://itunes.apple.com/app/fiery-feeds-rss-reader/id1158763303) (Closed source) * [Unread](https://itunes.apple.com/app/unread-rss-reader/id1252376153) (Closed source) diff --git a/docs/en/users/06_Fever_API.md b/docs/en/users/06_Fever_API.md index 971cf957d..909164516 100644 --- a/docs/en/users/06_Fever_API.md +++ b/docs/en/users/06_Fever_API.md @@ -20,6 +20,9 @@ Then point your mobile application to the URL of `fever.php` (e.g. `https://fres Tested with: +- Android + - [Readably](https://play.google.com/store/apps/details?id=com.isaiasmatewos.readably) + - iOS - [Fiery Feeds](https://itunes.apple.com/app/fiery-feeds-rss-reader/id1158763303) - [Unread](https://itunes.apple.com/app/unread-rss-reader/id1252376153) @@ -28,9 +31,6 @@ Tested with: - MacOS - [Readkit](https://itunes.apple.com/app/readkit/id588726889) -- Android - -Until now, we don't know about compatible Android clients. Please leave your feedback, if you tested the Fever API with Android apps. - - Please note, that *Press* is NOT compatible: it was a popular RSS client with Fever support, but its development stopped a while ago. It uses the Fever API in a wrong way, which we don't support. ## Features diff --git a/docs/fr/users/06_Fever_API.md b/docs/fr/users/06_Fever_API.md index 50650ebcd..fb15e596b 100644 --- a/docs/fr/users/06_Fever_API.md +++ b/docs/fr/users/06_Fever_API.md @@ -7,6 +7,9 @@ et des généralités sur l’accès par API. Testé avec: +- Android + [Readably](https://play.google.com/store/apps/details?id=com.isaiasmatewos.readably) + - iOS - [Fiery Feeds](https://itunes.apple.com/app/fiery-feeds-rss-reader/id1158763303) - [Unread](https://itunes.apple.com/app/unread-rss-reader/id1252376153) -- cgit v1.2.3 From 566799075155546392316b1e4e352bdfc9e3602b Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 9 Mar 2019 15:43:44 +0100 Subject: Change nextGet behaviour Fixes https://github.com/FreshRSS/FreshRSS/issues/2206 Related to https://github.com/FreshRSS/FreshRSS/pull/2255 --- app/Models/Context.php | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/app/Models/Context.php b/app/Models/Context.php index 60ec6ff77..95dc47c8c 100644 --- a/app/Models/Context.php +++ b/app/Models/Context.php @@ -252,37 +252,29 @@ class FreshRSS_Context { $found_current_get = false; switch ($get[0]) { case 'f': - // We search the next feed with at least one unread article in - // same category as the currend feed. + // We search the next unread feed with the following priorities: next in same category, or previous in same category, or next, or previous. foreach (self::$categories as $cat) { - if ($cat->id() != self::$current_get['category']) { - // We look into the category of the current feed! - continue; - } - + $sameCat = false; foreach ($cat->feeds() as $feed) { - if ($feed->id() == self::$current_get['feed']) { - // Here is our current feed! Fine, the next one will - // be a potential candidate. + if ($found_current_get) { + if ($feed->nbNotRead() > 0) { + $another_unread_id = $feed->id(); + break 2; + } + } elseif ($feed->id() == self::$current_get['feed']) { $found_current_get = true; - continue; - } - - if ($feed->nbNotRead() > 0) { + } elseif ($feed->nbNotRead() > 0) { $another_unread_id = $feed->id(); - if ($found_current_get) { - // We have found our current feed and now we - // have an feed with unread articles. Leave the - // loop! - break; - } + $sameCat = true; } } - break; + if ($found_current_get && $sameCat) { + break; + } } - // If no feed have been found, next_get is the current category. - self::$next_get = empty($another_unread_id) ? 'c_' . self::$current_get['category'] : 'f_' . $another_unread_id; + // If there is no more unread feed, show main stream + self::$next_get = $another_unread_id == '' ? 'a' : 'f_' . $another_unread_id; break; case 'c': // We search the next category with at least one unread article. @@ -304,8 +296,8 @@ class FreshRSS_Context { } } - // No unread category? The main stream will be our destination! - self::$next_get = empty($another_unread_id) ? 'a' : 'c_' . $another_unread_id; + // If there is no more unread category, show main stream + self::$next_get = $another_unread_id == '' ? 'a' : 'c_' . $another_unread_id; break; } } -- cgit v1.2.3 From 5b8c3e5bf3d52373ceead2ade79eb724fb3867c8 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 9 Mar 2019 18:25:33 +0100 Subject: Fix base theme border regression https://github.com/FreshRSS/FreshRSS/issues/2254 --- p/themes/base-theme/template.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index 2ea058786..fb62f8d74 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -504,7 +504,10 @@ a.btn { padding: 0px 15px; } .aside_feed .tree-folder-items:not(.active) { + border: none; + margin: 0; max-height: 0; + padding: 0; overflow: hidden; } .aside_feed .tree-folder-items .dropdown { -- cgit v1.2.3 From 54a86990e674a529db028a2240ba73237ae55f09 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 9 Mar 2019 19:15:46 +0100 Subject: Improved auto load more articles Fixed bug + ealier trigger of load more (half of the window height instead of 0) --- p/scripts/main.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/p/scripts/main.js b/p/scripts/main.js index 90a41d767..521adc839 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -592,9 +592,9 @@ function onScroll() { } } if (context.auto_load_more) { - const load_more = document.getElementById('mark-read-pagination'); - if (load_more && box_to_follow.scrollTop > 0 && - box_to_follow.scrollTop + box_to_follow.offsetHeight >= load_more.offsetTop) { + const pagination = document.getElementById('mark-read-pagination'); + if (pagination && box_to_follow.offsetHeight > 0 && + box_to_follow.scrollTop + box_to_follow.offsetHeight + (window.innerHeight / 2) >= pagination.offsetTop) { load_more_posts(); } } -- cgit v1.2.3 From 41e58630f774d54b84f272938b294bb04d51653b Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 9 Mar 2019 19:59:20 +0100 Subject: Changelog 2206 2260 2268 https://github.com/FreshRSS/FreshRSS/issues/2206 https://github.com/FreshRSS/FreshRSS/pull/2258 https://github.com/FreshRSS/FreshRSS/pull/2260 https://github.com/FreshRSS/FreshRSS/pull/2268 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e36f9592..06f2708a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * Rewrite jQuery and keyboard shortcut code as native JavaScript ES6 (except for graphs on the statistics pages) [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) * Batch scroll-as-read for better client-side and server-side performance [#2199](https://github.com/FreshRSS/FreshRSS/pull/2199) * Keyboard-shortcut navigation at end of feed or category continues to the next one [#2255](https://github.com/FreshRSS/FreshRSS/pull/2255) + * Changed jump behaviour after marking articles as read [#2206](https://github.com/FreshRSS/FreshRSS/issues/2206) + * More reactive auto-loading of articles [#2268](https://github.com/FreshRSS/FreshRSS/pull/2268) * Deployment * New default Docker image based on Ubuntu (~3 times faster, but ~2.5 times larger) [#2205](https://github.com/FreshRSS/FreshRSS/pull/2205) * Using Ubuntu 18.10 with PHP 7.2.15 and Apache 2.4.34 @@ -16,6 +18,7 @@ * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) * Fix breaking warning in Fever API [#2239](https://github.com/FreshRSS/FreshRSS/issues/2239) * Fix encoding problem in Fever API [#2241](https://github.com/FreshRSS/FreshRSS/issues/2241) + * Fix the reading of the environment variable `COPY_SYSLOG_TO_STDERR` [#2260](https://github.com/FreshRSS/FreshRSS/pull/2260) * API * Supported by [Readably](https://play.google.com/store/apps/details?id=com.isaiasmatewos.readably) (client for Android using Fever API) * I18n -- cgit v1.2.3 From e91ef155d42f9624ef0e5d553b4e5fad70ba1bb5 Mon Sep 17 00:00:00 2001 From: Quentí <33203663+Quenty31@users.noreply.github.com> Date: Sun, 10 Mar 2019 19:52:27 +0100 Subject: Pitchoun correciou (#2269) --- app/i18n/oc/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/i18n/oc/index.php b/app/i18n/oc/index.php index 5211fd24a..5cc71c9a9 100644 --- a/app/i18n/oc/index.php +++ b/app/i18n/oc/index.php @@ -6,7 +6,7 @@ return array( 'agpl3' => 'AGPL 3', 'bugs_reports' => 'Senhalament de problèmas', 'credits' => 'Crèdits', - 'credits_content' => 'Unes elements de l’estil venon del projècte Bootstrap encara que FreshRSS utilize pas aqueste framework. Lasicònas venon del projècte GNOME. La polissa Open Sans utilizada foguèt creada per en Steve Matteson. FreshRSS es basat sus Minz, un framework PHP.', + 'credits_content' => 'Unes elements de l’estil venon del projècte Bootstrap encara que FreshRSS utilize pas aqueste framework. Las icònas venon del projècte GNOME. La polissa Open Sans utilizada foguèt creada per en Steve Matteson. FreshRSS es basat sus Minz, un framework PHP.', 'freshrss_description' => 'FreshRSS es un agregador de fluxes RSS per l’auto-albergar tal coma Kriss Feed o Leed. Sa tòca es d’èsser leugièr e de bon utilizar de prima abòrd mas tanben d’èsser potent e parametrable.', 'github' => 'on Github', 'license' => 'Licéncia', -- cgit v1.2.3 From bdf9aef2acb7c608f72737402dd6da5668a5ea9b Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sun, 17 Mar 2019 11:08:42 +0100 Subject: [i18n] Update some translation strings (#2277) See #2086 --- app/i18n/en/conf.php | 7 ++----- app/i18n/fr/conf.php | 10 +++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/i18n/en/conf.php b/app/i18n/en/conf.php index b3d4d8a5c..fde78f5b5 100644 --- a/app/i18n/en/conf.php +++ b/app/i18n/en/conf.php @@ -158,15 +158,12 @@ return array( 'javascript' => 'JavaScript must be enabled in order to use shortcuts', 'last_article' => 'Open the last article', 'load_more' => 'Load more articles', - 'mark_favorite' => 'Mark as favourite', - 'mark_read' => 'Mark as read', + 'mark_favorite' => 'Toggle favourite', + 'mark_read' => 'Toggle read', 'navigation' => 'Navigation', 'navigation_help' => 'With the "Shift" modifier, navigation shortcuts apply on feeds.
        With the "Alt" modifier, navigation shortcuts apply on categories.', 'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.', 'next_article' => 'Open the next article', - 'other_action' => 'Other actions', - 'previous_article' => 'Open the previous article', - 'next_article' => 'Open the next article', 'normal_view' => 'Switch to normal view', 'other_action' => 'Other actions', 'previous_article' => 'Open the previous article', diff --git a/app/i18n/fr/conf.php b/app/i18n/fr/conf.php index 5c8e91c89..d0d146c89 100644 --- a/app/i18n/fr/conf.php +++ b/app/i18n/fr/conf.php @@ -158,11 +158,11 @@ return array( 'javascript' => 'Le JavaScript doit être activé pour pouvoir profiter des raccourcis.', 'last_article' => 'Passer au dernier article', 'load_more' => 'Charger plus d’articles', - 'mark_favorite' => 'Mettre en favori', - 'mark_read' => 'Marquer comme lu', + 'mark_favorite' => 'Basculer l’indicateur de favori', + 'mark_read' => 'Basculer l’indicateur de lecture', 'navigation' => 'Navigation', 'navigation_help' => 'Avec le modificateur "Shift", les raccourcis de navigation s’appliquent aux flux.
        Avec le modificateur "Alt", les raccourcis de navigation s’appliquent aux catégories.', - 'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.', //TODO - Translation + 'navigation_no_mod_help' => 'Les raccourcis suivant ne supportent pas les modificateurs.', 'next_article' => 'Passer à l’article suivant', 'normal_view' => 'Basculer vers la vue normale', 'other_action' => 'Autres actions', @@ -171,8 +171,8 @@ return array( 'rss_view' => 'Ouvrir le flux RSS dans un nouvel onglet', 'see_on_website' => 'Voir sur le site d’origine', 'shift_for_all_read' => '+ shift pour marquer tous les articles comme lus', - 'skip_next_article' => 'Focus next without opening', //TODO - Translation - 'skip_previous_article' => 'Focus previous without opening', //TODO - Translation + 'skip_next_article' => 'Passer au suivant sans ouvrir', + 'skip_previous_article' => 'Passer au précédent sans ouvrir', 'title' => 'Raccourcis', 'user_filter' => 'Accéder aux filtres utilisateur', 'user_filter_help' => 'S’il n’y a qu’un filtre utilisateur, celui-ci est utilisé automatiquement. Sinon ils sont accessibles par leur numéro.', -- cgit v1.2.3 From e6888bbf232de5547560ea3af56ed760cb11c4ae Mon Sep 17 00:00:00 2001 From: hoilc Date: Mon, 18 Mar 2019 17:55:50 +0800 Subject: update zh-cn (i18n) (#2280) --- app/i18n/zh-cn/admin.php | 20 ++++++++++---------- app/i18n/zh-cn/conf.php | 26 +++++++++++++------------- app/i18n/zh-cn/feedback.php | 10 +++++----- app/i18n/zh-cn/gen.php | 2 +- app/i18n/zh-cn/index.php | 6 +++--- app/i18n/zh-cn/install.php | 4 ++-- app/i18n/zh-cn/sub.php | 14 +++++++------- cli/i18n/ignore/zh-cn.php | 4 ++++ 8 files changed, 45 insertions(+), 41 deletions(-) diff --git a/app/i18n/zh-cn/admin.php b/app/i18n/zh-cn/admin.php index e34070526..74f57b6e8 100644 --- a/app/i18n/zh-cn/admin.php +++ b/app/i18n/zh-cn/admin.php @@ -64,11 +64,11 @@ return array( 'files' => '文件相关', 'json' => array( 'nok' => '找不到 JSON 扩展 (php-json ) 。', - 'ok' => '已找到 JSON 扩展', + 'ok' => '已找到 JSON 扩展。', ), 'mbstring' => array( - 'nok' => 'Cannot find the recommended library mbstring for Unicode.', //TODO - Translation - 'ok' => 'You have the recommended library mbstring for Unicode.', //TODO - Translation + 'nok' => '找不到推荐的 Unicode 解析库 (mbstring)。', + 'ok' => '已找到推荐的 Unicode 解析库 (mbstring)。', ), 'minz' => array( 'nok' => '找不到 Minz 框架。', @@ -163,8 +163,8 @@ return array( 'max-categories' => '每用户分类限制', 'max-feeds' => '每用户 RSS 源限制', 'cookie-duration' => array( - 'help' => 'in seconds', // @todo translate - 'number' => 'Duration to keep logged in', // @todo translate + 'help' => '单位(秒)', + 'number' => '保持登录的时长', ), 'registration' => array( 'help' => '0 表示无账户数限制', @@ -183,15 +183,15 @@ return array( 'user' => array( 'articles_and_size' => '%s 篇文章 (%s)', 'create' => '创建新用户', - 'delete_users' => 'Delete user', //TODO - Translation + 'delete_users' => '删除用户', 'language' => '语言', - 'number' => '已有 %d 个帐户', - 'numbers' => '已有 %d 个帐户', + 'number' => '已有 %d 个用户', + 'numbers' => '已有 %d 个用户', 'password_form' => '密码
        (用于 Web-form 登录方式)', 'password_format' => '至少 7 个字符', - 'selected' => 'Selected user', //TODO - Translation + 'selected' => '已选中用户', 'title' => '用户管理', - 'update_users' => 'Update user', //TODO - Translation + 'update_users' => '更新用户', 'user_list' => '用户列表', 'username' => '用户名', 'users' => '用户', diff --git a/app/i18n/zh-cn/conf.php b/app/i18n/zh-cn/conf.php index 1216aaaca..535dfd358 100644 --- a/app/i18n/zh-cn/conf.php +++ b/app/i18n/zh-cn/conf.php @@ -28,7 +28,7 @@ return array( 'seconds' => '秒 (0 表示不超时)', 'timeout' => 'HTML5 通知超时时间', ), - 'show_nav_buttons' => 'Show the navigation buttons', //TODO - Translation + 'show_nav_buttons' => '显示导航按钮', 'theme' => '主题', 'title' => '显示', 'width' => array( @@ -53,7 +53,7 @@ return array( 'query' => array( '_' => '自定义查询', 'deprecated' => '此查询不再有效。相关的分类或 RSS 源已被删除。', - 'display' => 'Display user query results', //TODO - Translation + 'display' => '显示查询结果', 'filter' => '生效的过滤器:', 'get_all' => '显示所有文章', 'get_category' => '显示分类 "%s"', @@ -64,7 +64,7 @@ return array( 'number' => '查询 n°%d', 'order_asc' => '由旧到新显示文章', 'order_desc' => '由新到旧显示文章', - 'remove' => 'Remove user query', //TODO - Translation + 'remove' => '删除查询', 'search' => '搜索 "%s"', 'state_0' => '显示所有文章', 'state_1' => '显示已读文章', @@ -128,7 +128,7 @@ return array( ), 'sharing' => array( '_' => '分享', - 'add' => 'Add a sharing method', //TODO - Translation + 'add' => '添加分享方式', 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', 'email' => 'Email', @@ -136,7 +136,7 @@ return array( 'g+' => 'Google+', 'more_information' => '更多信息', 'print' => '打印', - 'remove' => 'Remove sharing method', //TODO - Translation + 'remove' => '删除分享方式', 'shaarli' => 'Shaarli', 'share_name' => '名称', 'share_url' => '地址', @@ -148,31 +148,31 @@ return array( '_' => '快捷键', 'article_action' => '文章操作', 'auto_share' => '分享', - 'auto_share_help' => '如果有多种分享模式,则会按照它们的编号依次访问。', + 'auto_share_help' => '如果有多种分享方式,则会按照它们的编号依次访问。', 'close_dropdown' => '关闭菜单', 'collapse_article' => '收起文章', - 'first_article' => '跳转到第一篇文章', + 'first_article' => '打开第一篇文章', 'focus_search' => '聚焦到搜索框', 'global_view' => '切换到全屏视图', 'help' => '显示帮助文档', 'javascript' => '若要使用快捷键,必须启用 JavaScript', - 'last_article' => '跳转到最后一篇文章', + 'last_article' => '打开最后一篇文章', 'load_more' => '载入更多文章', 'mark_favorite' => '加入收藏', 'mark_read' => '设为已读', 'navigation' => '浏览', 'navigation_help' => '搭配 "Shift" 键,浏览快捷键将生效于 RSS 源。
        搭配 "Alt" 键,浏览快捷键将生效于分类。', - 'navigation_no_mod_help' => 'The following navigation shortcuts do not support modifiers.', //TODO - Translation - 'next_article' => '跳转到下一篇文章', + 'navigation_no_mod_help' => '以下快捷键不支持组合键 (Shift 或 Alt)', + 'next_article' => '打开下一篇文章', 'normal_view' => '切换到普通视图', 'other_action' => '其他操作', - 'previous_article' => '跳转到上一篇文章', + 'previous_article' => '打开上一篇文章', 'reading_view' => '切换到阅读视图', 'rss_view' => '在新标签中打开 RSS 视图', 'see_on_website' => '在原网站上查看', 'shift_for_all_read' => '+ shift 可以将全部文章设为已读', - 'skip_next_article' => 'Focus next without opening', //TODO - Translation - 'skip_previous_article' => 'Focus previous without opening', //TODO - Translation + 'skip_next_article' => '跳转到下一篇文章而不打开', + 'skip_previous_article' => '跳转到上一篇文章而不打开', 'title' => '快捷键', 'user_filter' => '显示自定义查询', 'user_filter_help' => '如果有多个自定义过滤器,则会按照它们的编号依次访问。', diff --git a/app/i18n/zh-cn/feedback.php b/app/i18n/zh-cn/feedback.php index e1778a9f2..e8ee969b0 100644 --- a/app/i18n/zh-cn/feedback.php +++ b/app/i18n/zh-cn/feedback.php @@ -57,8 +57,8 @@ return array( 'sub' => array( 'actualize' => '获取', 'articles' => array( - 'marked_read' => 'The selected articles have been marked as read.', //TODO - Translation - 'marked_unread' => 'The articles have been marked as unread.', //TODO - Translation + 'marked_read' => '选中文章已标记为已读', + 'marked_unread' => '文章已标记为未读', ), 'category' => array( 'created' => '分类 %s 已创建。', @@ -80,7 +80,7 @@ return array( 'already_subscribed' => '你已订阅 %s', 'deleted' => 'RSS 源已删除', 'error' => 'RSS 源更新失败', - 'internal_problem' => 'RSS 源添加失败。检查 FreshRSS 日志 查看详情。', //TODO - Translation + 'internal_problem' => 'RSS 源添加失败。检查 FreshRSS 日志 查看详情。你可以在URL后附加 #force_feed 从而尝试强制添加。', 'invalid_url' => 'URL %s 无效', 'n_actualized' => '%d 个 RSS 源已更新', 'n_entries_deleted' => '%d 篇文章已删除', @@ -109,8 +109,8 @@ return array( 'error' => '用户 %s 删除失败', ), 'updated' => array( - '_' => 'User %s has been updated', //TODO - Translation - 'error' => 'User %s has not been updated', //TODO - Translation + '_' => '用户 %s 已更新', + 'error' => '用户 %s 更新失败', ), ), ); diff --git a/app/i18n/zh-cn/gen.php b/app/i18n/zh-cn/gen.php index 1dcd95233..11d4efdb3 100644 --- a/app/i18n/zh-cn/gen.php +++ b/app/i18n/zh-cn/gen.php @@ -19,7 +19,7 @@ return array( 'see_website' => '查看网站', 'submit' => '提交', 'truncate' => '删除所有文章', - 'update' => 'Update', //TODO - Translation + 'update' => '更新', //TODO - Translation ), 'auth' => array( 'email' => 'Email 地址', diff --git a/app/i18n/zh-cn/index.php b/app/i18n/zh-cn/index.php index 3f6b44701..018813c3e 100644 --- a/app/i18n/zh-cn/index.php +++ b/app/i18n/zh-cn/index.php @@ -40,7 +40,7 @@ return array( 'mark_all_read' => '全部设为已读', 'mark_cat_read' => '此分类设为已读', 'mark_feed_read' => '此源设为已读', - 'mark_selection_unread' => 'Mark selection as unread', //TODO - Translation + 'mark_selection_unread' => '选中设为已读', 'newer_first' => '由新到旧', 'non-starred' => '显示未收藏', 'normal_view' => '普通视图', @@ -53,11 +53,11 @@ return array( 'starred' => '显示收藏', 'stats' => '统计', 'subscription' => '订阅管理', - 'tags' => 'My labels', //TODO - Translation + 'tags' => '我的标签', 'unread' => '显示未读', ), 'share' => '分享', 'tag' => array( - 'related' => '相关标签', //TODO - Translation + 'related' => '文章标签', ), ); diff --git a/app/i18n/zh-cn/install.php b/app/i18n/zh-cn/install.php index 29647932a..da231917b 100644 --- a/app/i18n/zh-cn/install.php +++ b/app/i18n/zh-cn/install.php @@ -69,8 +69,8 @@ return array( 'ok' => '已找到推荐的 JSON 解析库。', ), 'mbstring' => array( - 'nok' => 'Cannot find the recommended library mbstring for Unicode.', //TODO - Translation - 'ok' => 'You have the recommended library mbstring for Unicode.', //TODO - Translation + 'nok' => '找不到推荐的 Unicode 解析库 (mbstring)。', + 'ok' => '已找到推荐的 Unicode 解析库 (mbstring)。', ), 'minz' => array( 'nok' => '找不到 Minz 框架。', diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php index 3a9623468..f84d08cdf 100644 --- a/app/i18n/zh-cn/sub.php +++ b/app/i18n/zh-cn/sub.php @@ -27,7 +27,7 @@ return array( 'password' => 'HTTP 密码', 'username' => 'HTTP 用户名', ), - 'clear_cache' => 'Always clear cache', //TODO - Translation + 'clear_cache' => '总是清除缓存', 'css_help' => '用于获取全文(注意,这将耗费更多时间!)', 'css_path' => '原文的 CSS 选择器', 'description' => '描述', @@ -47,16 +47,16 @@ return array( ), 'websub' => 'WebSub 即时通知', 'show' => array( - 'all' => 'Show all feeds', //TODO - Translation - 'error' => 'Show only feeds with error', //TODO - Translation + 'all' => '显示所有 RSS 源', + 'error' => '仅显示有错误的 RSS 源', ), 'showing' => array( - 'error' => 'Showing only feeds with error', //TODO - Translation + 'error' => '正在显示有错误的 RSS 源', ), - 'ssl_verify' => 'Verify SSL security', //TODO - Translation + 'ssl_verify' => '验证 SSL 安全', 'stats' => '统计', 'think_to_add' => '你可以添加一些 RSS 源。', - 'timeout' => 'Timeout in seconds', //TODO - Translation + 'timeout' => '超时时间(秒)', 'title' => '标题', 'title_add' => '添加 RSS 源', 'ttl' => '最小自动更新时间', @@ -72,7 +72,7 @@ return array( 'export' => '导出', 'export_opml' => '导出 RSS 源列表 (OPML)', 'export_starred' => '导出你的收藏', - 'export_labelled' => 'Export your labelled articles', //TODO + 'export_labelled' => '导出有标签的文章', 'feed_list' => '%s 文章列表', 'file_to_import' => '需要导入的文件
        (OPML, JSON 或 ZIP)', 'file_to_import_no_zip' => '需要导入的文件
        (OPML 或 JSON)', diff --git a/cli/i18n/ignore/zh-cn.php b/cli/i18n/ignore/zh-cn.php index c00ac79d3..d55071d10 100644 --- a/cli/i18n/ignore/zh-cn.php +++ b/cli/i18n/ignore/zh-cn.php @@ -18,6 +18,7 @@ return array( 'gen.lang.it', 'gen.lang.kr', 'gen.lang.nl', + 'gen.lang.oc', 'gen.lang.pt-br', 'gen.lang.ru', 'gen.lang.tr', @@ -29,8 +30,11 @@ return array( 'gen.share.g+', 'gen.share.gnusocial', 'gen.share.jdh', + 'gen.share.linkedin', 'gen.share.mastodon', 'gen.share.movim', + 'gen.share.pinboard', + 'gen.share.pocket', 'gen.share.shaarli', 'gen.share.twitter', 'gen.share.wallabag', -- cgit v1.2.3 From 6323fe5ea011e7f8821b93071c8f40f271a697f0 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 19 Mar 2019 19:52:53 +0100 Subject: Add Authorization header forwarding to the Nginx configuration for Docker (#2282) * Add Authorization header forwarding to the Nginx configuration for Docker * Comment --- Docker/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Docker/README.md b/Docker/README.md index ba6169ea3..bed5e1cce 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -301,6 +301,10 @@ server { proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; proxy_read_timeout 90; + + # Forward the Authorization header for the Google Reader API. + proxy_set_header Authorization $http_authorization; + proxy_pass_header Authorization; } } ``` -- cgit v1.2.3 From cb00eafba02b5dfe9bfefd8a4b4228cccef9a6bf Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 19 Mar 2019 20:08:56 +0100 Subject: Fever remove semicolomn from author (#2283) https://github.com/FreshRSS/FreshRSS/issues/2281 --- p/api/fever.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p/api/fever.php b/p/api/fever.php index 30f9651a3..b81646928 100644 --- a/p/api/fever.php +++ b/p/api/fever.php @@ -536,7 +536,7 @@ class FeverAPI 'id' => $entry->id(), 'feed_id' => $entry->feed(false), 'title' => escapeToUnicodeAlternative($entry->title(), false), - 'author' => escapeToUnicodeAlternative($entry->authors(true), false), + 'author' => escapeToUnicodeAlternative(trim($entry->authors(true), '; '), false), 'html' => $entry->content(), 'url' => htmlspecialchars_decode($entry->link(), ENT_QUOTES), 'is_saved' => $entry->isFavorite() ? 1 : 0, -- cgit v1.2.3 From 834ffacce22ff6a2c0f1459476dc4a45e8ea06f9 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 19 Mar 2019 20:14:31 +0100 Subject: No old ID (#2276) * No old ID https://github.com/FreshRSS/FreshRSS/issues/2273 * PostgreSQL insert or ignore --- app/Controllers/feedController.php | 10 +++------- app/Controllers/importExportController.php | 2 +- app/Models/EntryDAOPGSQL.php | 4 +++- lib/lib_rss.php | 7 +------ 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index d5ae235ad..7f36e0388 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -377,17 +377,13 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $read_upon_reception = $feed->attributes('read_upon_reception') !== null ? ( $feed->attributes('read_upon_reception') ) : FreshRSS_Context::$user_conf->mark_when['reception']; - if ($isNewFeed) { - $id = min(time(), $entry_date) . uSecString(); - $entry->_isRead($read_upon_reception); - } elseif ($entry_date < $date_min) { - $id = min(time(), $entry_date) . uSecString(); + $id = uTimeString(); + $entry->_id($id); + if ($entry_date < $date_min) { $entry->_isRead(true); //Old article that was not in database. Probably an error, so mark as read } else { - $id = uTimeString(); $entry->_isRead($read_upon_reception); } - $entry->_id($id); $entry = Minz_ExtensionManager::callHook('entry_before_insert', $entry); if ($entry === null) { diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php index 80b9868ec..1d7176929 100644 --- a/app/Controllers/importExportController.php +++ b/app/Controllers/importExportController.php @@ -585,7 +585,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController { $feed_id, $item['id'], $item['title'], $author, $content, $url, $published, $is_read, $is_starred ); - $entry->_id(min(time(), $entry->date(true)) . uSecString()); + $entry->_id(uTimeString()); $entry->_tags($tags); if (isset($newGuids[$entry->guid()])) { diff --git a/app/Models/EntryDAOPGSQL.php b/app/Models/EntryDAOPGSQL.php index aef258b6f..e571e457f 100644 --- a/app/Models/EntryDAOPGSQL.php +++ b/app/Models/EntryDAOPGSQL.php @@ -37,7 +37,9 @@ BEGIN INSERT INTO `' . $this->prefix . 'entry` (id, guid, title, author, content, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags) (SELECT rank + row_number() OVER(ORDER BY date) AS id, guid, title, author, content, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags FROM `' . $this->prefix . 'entrytmp` AS etmp - WHERE NOT EXISTS (SELECT 1 FROM `' . $this->prefix . 'entry` AS ereal WHERE etmp.id_feed = ereal.id_feed AND etmp.guid = ereal.guid) + WHERE NOT EXISTS ( + SELECT 1 FROM `' . $this->prefix . 'entry` AS ereal + WHERE (etmp.id = ereal.id) OR (etmp.id_feed = ereal.id_feed AND etmp.guid = ereal.guid)) ORDER BY date); DELETE FROM `' . $this->prefix . 'entrytmp` WHERE id <= maxrank; END $$;'; diff --git a/lib/lib_rss.php b/lib/lib_rss.php index 89e9ddfea..bff59d5cc 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -303,12 +303,7 @@ function lazyimg($content) { function uTimeString() { $t = @gettimeofday(); - return $t['sec'] . str_pad($t['usec'], 6, '0'); -} - -function uSecString() { - $t = @gettimeofday(); - return str_pad($t['usec'], 6, '0'); + return $t['sec'] . str_pad($t['usec'], 6, '0', STR_PAD_LEFT); } function invalidateHttpCache($username = '') { -- cgit v1.2.3 From 71b4226dc721bc0f23cc594760329f29e51defac Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Tue, 19 Mar 2019 20:27:06 +0100 Subject: Add an option validation on cli commands (#2278) If an option used on cli is not recognized, the command aborts and displays an error message. If the typed option is similar to one of the recognized options, a hint is displayed. At the moment, there is a limitation on long options. Short options are not validated at the moment. See #2046 --- cli/_cli.php | 25 +++++++++++++++++++++++++ cli/_update-or-create-user.php | 2 +- cli/actualize-user.php | 10 ++++++---- cli/db-optimize.php | 10 ++++++---- cli/delete-user.php | 10 ++++++---- cli/do-install.php | 6 +++--- cli/export-opml-for-user.php | 10 ++++++---- cli/export-zip-for-user.php | 12 +++++++----- cli/import-for-user.php | 12 +++++++----- cli/reconfigure.php | 8 ++++++++ 10 files changed, 75 insertions(+), 30 deletions(-) diff --git a/cli/_cli.php b/cli/_cli.php index e8fb6ae42..dec244bc3 100644 --- a/cli/_cli.php +++ b/cli/_cli.php @@ -3,6 +3,9 @@ if (php_sapi_name() !== 'cli') { die('FreshRSS error: This PHP script may only be invoked from command line!'); } +const REGEX_INPUT_OPTIONS = '/^--/'; +const REGEX_PARAM_OPTIONS = '/:*$/'; + require(__DIR__ . '/../constants.php'); require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader require(LIB_PATH . '/lib_install.php'); @@ -64,3 +67,25 @@ function performRequirementCheck($databaseType) { fail($message); } } + +function getLongOptions($options, $regex) { + $longOptions = array_filter($options, function($a) use ($regex) { + return preg_match($regex, $a); + }); + return array_map(function($a) use ($regex) { + return preg_replace($regex, '', $a); + }, $longOptions); +} + +function validateOptions($input, $params) { + $sanitizeInput = getLongOptions($input, REGEX_INPUT_OPTIONS); + $sanitizeParams = getLongOptions($params, REGEX_PARAM_OPTIONS); + $unknownOptions = array_diff($sanitizeInput, $sanitizeParams); + + if (0 === count($unknownOptions)) { + return true; + } + + fwrite(STDERR, sprintf("FreshRSS error: unknown options: %s\n", implode (', ', $unknownOptions))); + return false; +} diff --git a/cli/_update-or-create-user.php b/cli/_update-or-create-user.php index a5960b58a..eda597f19 100644 --- a/cli/_update-or-create-user.php +++ b/cli/_update-or-create-user.php @@ -22,7 +22,7 @@ if (!$isUpdate) { $options = getopt('', $params); -if (empty($options['user'])) { +if (!validateOptions($argv, $params) || empty($options['user'])) { fail('Usage: ' . basename($_SERVER['SCRIPT_FILENAME']) . " --user username ( --password 'password' --api_password 'api_password'" . " --language en --email user@example.net --token 'longRandomString'" . diff --git a/cli/actualize-user.php b/cli/actualize-user.php index dd07fc142..08e17de98 100755 --- a/cli/actualize-user.php +++ b/cli/actualize-user.php @@ -2,11 +2,13 @@ /path/to/file.opml.xml"); } diff --git a/cli/export-zip-for-user.php b/cli/export-zip-for-user.php index 86113d9fa..b89a55104 100755 --- a/cli/export-zip-for-user.php +++ b/cli/export-zip-for-user.php @@ -2,12 +2,14 @@ /path/to/file.zip"); } diff --git a/cli/import-for-user.php b/cli/import-for-user.php index 95ff18c8c..7c66fbef2 100755 --- a/cli/import-for-user.php +++ b/cli/import-for-user.php @@ -2,12 +2,14 @@ Date: Tue, 19 Mar 2019 21:48:41 +0100 Subject: Minor docker doc changes (#2284) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Minor docker doc changes Fix Træfik temp volume minor issue * Warning for non x86-64 * Formatting * Minor * Wording --- Docker/README.md | 78 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/Docker/README.md b/Docker/README.md index bed5e1cce..3cfb05c69 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -10,33 +10,6 @@ sh get-docker.sh ``` -## [Docker tags](https://hub.docker.com/r/freshrss/freshrss/tags) -The tags correspond to FreshRSS branches and versions: -* `:latest` (default) is the `master` branch, more stable -* `:dev` is the `dev` branch, rolling release -* `:x.y.z` are specific FreshRSS releases - -### Linux: Ubuntu vs. Alpine -Our default image is based on [Ubuntu](https://www.ubuntu.com/server). We offer an alternative based on [Alpine](https://alpinelinux.org/) (with the `-alpine` tag suffix). -In [our tests](https://github.com/FreshRSS/FreshRSS/pull/2205), Ubuntu is ~3 times faster, -while Alpine is ~2.5 times [smaller on disk](https://hub.docker.com/r/freshrss/freshrss/tags) (and much faster to build). - - -## Optional: Build Docker image of FreshRSS -Optional, as a *less recent* online image can be automatically fetched during the next step (run), -but online images are not available for as many platforms (e.g. Raspberry Pi / ARM) as if you build yourself. - -```sh -# First time only -git clone https://github.com/FreshRSS/FreshRSS.git - -cd ./FreshRSS/ -git pull -sudo docker pull ubuntu:18.10 -sudo docker build --tag freshrss/freshrss -f Docker/Dockerfile . -``` - - ## Create an isolated network ```sh sudo docker network create freshrss-network @@ -48,10 +21,12 @@ Here is the recommended configuration using automatic [Let’s Encrypt](https:// ```sh sudo docker volume create traefik-letsencrypt +sudo docker volume create traefik-tmp # Just change your e-mail address in the command below: sudo docker run -d --restart unless-stopped --log-opt max-size=10m \ -v traefik-letsencrypt:/etc/traefik/acme \ + -v traefik-tmp:/tmp \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ --net freshrss-network \ -p 80:80 \ @@ -71,6 +46,8 @@ See [more information about Docker and Let’s Encrypt in Træfik](https://docs. Example using the built-in refresh cron job (see further below for alternatives). You must first chose a domain (DNS) or sub-domain, e.g. `freshrss.example.net`. +> **N.B.:** For platforms other than x64 (Intel, AMD), such as ARM (e.g. Raspberry Pi), see the section *Build Docker image* further below. + ```sh sudo docker volume create freshrss-data @@ -133,15 +110,6 @@ Browse to your server https://freshrss.example.net/ to complete the installation or use the command line described below. -## Command line - -```sh -sudo docker exec --user apache -it freshrss php ./cli/list-users.php -``` - -See the [CLI documentation](../cli/) for all the other commands. - - ## How to update ```sh @@ -157,6 +125,42 @@ sudo docker rm freshrss_old ``` +## [Docker tags](https://hub.docker.com/r/freshrss/freshrss/tags) +The tags correspond to FreshRSS branches and versions: +* `:latest` (default) is the `master` branch, more stable +* `:dev` is the `dev` branch, rolling release +* `:x.y.z` are specific FreshRSS releases + +### Linux: Ubuntu vs. Alpine +Our default image is based on [Ubuntu](https://www.ubuntu.com/server). We offer an alternative based on [Alpine](https://alpinelinux.org/) (with the `-alpine` tag suffix). +In [our tests](https://github.com/FreshRSS/FreshRSS/pull/2205), Ubuntu is ~3 times faster, +while Alpine is ~2.5 times [smaller on disk](https://hub.docker.com/r/freshrss/freshrss/tags) (and much faster to build). + + +## Optional: Build Docker image of FreshRSS +Building your own Docker image is optional because online images can be fetched automatically. +Note that prebuilt images are less recent and only available for x64 (Intel, AMD) platforms. + +```sh +# First time only +git clone https://github.com/FreshRSS/FreshRSS.git + +cd ./FreshRSS/ +git pull +sudo docker pull ubuntu:18.10 +sudo docker build --tag freshrss/freshrss -f Docker/Dockerfile . +``` + + +## Command line + +```sh +sudo docker exec --user apache -it freshrss php ./cli/list-users.php +``` + +See the [CLI documentation](../cli/) for all the other commands. + + ## Debugging ```sh @@ -301,7 +305,7 @@ server { proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; proxy_read_timeout 90; - + # Forward the Authorization header for the Google Reader API. proxy_set_header Authorization $http_authorization; proxy_pass_header Authorization; -- cgit v1.2.3 From 707388c09334364d085c598f6b483175a51d7d19 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 19 Mar 2019 21:51:16 +0100 Subject: Docker ca-certificates missing (#2285) --- Docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docker/Dockerfile b/Docker/Dockerfile index 8f15bec96..56623b001 100644 --- a/Docker/Dockerfile +++ b/Docker/Dockerfile @@ -5,7 +5,7 @@ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN apt update && \ apt install --no-install-recommends -y \ - cron \ + ca-certificates cron \ apache2 libapache2-mod-php \ php-curl php-intl php-mbstring php-xml php-zip \ php-sqlite3 php-mysql php-pgsql && \ -- cgit v1.2.3 From e84a90943ab1e4a254b2d33c7cabef18b718b456 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 20 Mar 2019 17:52:31 +0100 Subject: Session fix when form + HTTP auth are used (#2286) https://github.com/Alkarex/FreshRSS/commit/bf51c82d55f6bf1af2a6464ca4f148d6c613d28f https://github.com/FreshRSS/FreshRSS/issues/2125#issuecomment-473873922 --- app/Models/Auth.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Models/Auth.php b/app/Models/Auth.php index 513a9cb2f..16a506f00 100644 --- a/app/Models/Auth.php +++ b/app/Models/Auth.php @@ -13,7 +13,7 @@ class FreshRSS_Auth { * This method initializes authentication system. */ public static function init() { - if (Minz_Session::param('REMOTE_USER', '') !== httpAuthUser()) { + if (isset($_SESSION['REMOTE_USER']) && $_SESSION['REMOTE_USER'] !== httpAuthUser()) { //HTTP REMOTE_USER has changed self::removeAccess(); } -- cgit v1.2.3 From ebd8c31c0272f135b1b55f0480d1c8c3875935fe Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 22 Mar 2019 19:05:38 +0100 Subject: Rework CSRF interaction with sessions (#2290) * Rework CSRF interaction with sessions Fix https://github.com/FreshRSS/FreshRSS/issues/2288 Improve security in some edge cases Maybe relevant for https://github.com/FreshRSS/FreshRSS/issues/2125#issuecomment-474992671 * Forgotten mime type --- app/Controllers/authController.php | 6 +++++- app/Controllers/userController.php | 1 + app/FreshRSS.php | 32 ++++++++++++++++++++------------ app/Models/Auth.php | 8 ++++---- p/scripts/main.js | 28 ++++++++++++++++++++++++++-- 5 files changed, 56 insertions(+), 19 deletions(-) diff --git a/app/Controllers/authController.php b/app/Controllers/authController.php index 75d4acae0..ca44b1a96 100644 --- a/app/Controllers/authController.php +++ b/app/Controllers/authController.php @@ -69,7 +69,7 @@ class FreshRSS_auth_Controller extends Minz_ActionController { * the user is already connected. */ public function loginAction() { - if (FreshRSS_Auth::hasAccess()) { + if (FreshRSS_Auth::hasAccess() && Minz_Request::param('u', '') == '') { Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); } @@ -133,6 +133,7 @@ class FreshRSS_auth_Controller extends Minz_ActionController { // Set session parameter to give access to the user. Minz_Session::_param('currentUser', $username); Minz_Session::_param('passwordHash', $conf->passwordHash); + Minz_Session::_param('csrf'); FreshRSS_Auth::giveAccess(); // Set cookie parameter if nedded. @@ -161,6 +162,8 @@ class FreshRSS_auth_Controller extends Minz_ActionController { return; } + FreshRSS_FormAuth::deleteCookie(); + $conf = get_user_configuration($username); if ($conf == null) { return; @@ -176,6 +179,7 @@ class FreshRSS_auth_Controller extends Minz_ActionController { if ($ok) { Minz_Session::_param('currentUser', $username); Minz_Session::_param('passwordHash', $s); + Minz_Session::_param('csrf'); FreshRSS_Auth::giveAccess(); Minz_Request::good(_t('feedback.auth.login.success'), diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php index 71172b9ef..be3787561 100644 --- a/app/Controllers/userController.php +++ b/app/Controllers/userController.php @@ -247,6 +247,7 @@ class FreshRSS_user_Controller extends Minz_ActionController { $user_conf = get_user_configuration($new_user_name); Minz_Session::_param('currentUser', $new_user_name); Minz_Session::_param('passwordHash', $user_conf->passwordHash); + Minz_Session::_param('csrf'); FreshRSS_Auth::giveAccess(); } diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 1dc80718e..ecf13e4cf 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -57,18 +57,26 @@ class FreshRSS extends Minz_FrontController { private static function initAuth() { FreshRSS_Auth::init(); - if (Minz_Request::isPost() && !(is_referer_from_same_domain() && FreshRSS_Auth::isCsrfOk())) { - // Basic protection against XSRF attacks - FreshRSS_Auth::removeAccess(); - $http_referer = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER']; - Minz_Translate::init('en'); //TODO: Better choice of fallback language - Minz_Error::error( - 403, - array('error' => array( - _t('feedback.access.denied'), - ' [HTTP_REFERER=' . htmlspecialchars($http_referer, ENT_NOQUOTES, 'UTF-8') . ']' - )) - ); + if (Minz_Request::isPost()) { + if (!is_referer_from_same_domain()) { + // Basic protection against XSRF attacks + FreshRSS_Auth::removeAccess(); + $http_referer = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER']; + Minz_Translate::init('en'); //TODO: Better choice of fallback language + Minz_Error::error(403, array('error' => array( + _t('feedback.access.denied'), + ' [HTTP_REFERER=' . htmlspecialchars($http_referer, ENT_NOQUOTES, 'UTF-8') . ']' + ))); + } + if ((!FreshRSS_Auth::isCsrfOk()) && + (Minz_Request::controllerName() !== 'auth' || Minz_Request::actionName() !== 'login')) { + // Token-based protection against XSRF attacks, except for the login form itself + Minz_Translate::init('en'); //TODO: Better choice of fallback language + Minz_Error::error(403, array('error' => array( + _t('feedback.access.denied'), + ' [CSRF]' + ))); + } } } diff --git a/app/Models/Auth.php b/app/Models/Auth.php index 16a506f00..6d079a01f 100644 --- a/app/Models/Auth.php +++ b/app/Models/Auth.php @@ -24,6 +24,7 @@ class FreshRSS_Auth { $conf = Minz_Configuration::get('system'); $current_user = $conf->default_user; Minz_Session::_param('currentUser', $current_user); + Minz_Session::_param('csrf'); } if (self::$login_ok) { @@ -56,6 +57,7 @@ class FreshRSS_Auth { $current_user = trim($credentials[0]); Minz_Session::_param('currentUser', $current_user); Minz_Session::_param('passwordHash', trim($credentials[1])); + Minz_Session::_param('csrf'); } return $current_user != ''; case 'http_auth': @@ -63,6 +65,7 @@ class FreshRSS_Auth { $login_ok = $current_user != '' && FreshRSS_UserDAO::exists($current_user); if ($login_ok) { Minz_Session::_param('currentUser', $current_user); + Minz_Session::_param('csrf'); } return $login_ok; case 'none': @@ -196,13 +199,10 @@ class FreshRSS_Auth { } public static function isCsrfOk($token = null) { $csrf = Minz_Session::param('csrf'); - if ($csrf == '') { - return true; //Not logged in yet - } if ($token === null) { $token = Minz_Request::fetchPOST('_csrf'); } - return $token === $csrf; + return $token != '' && $token === $csrf; } } diff --git a/p/scripts/main.js b/p/scripts/main.js index 521adc839..212bf804b 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -44,6 +44,12 @@ var context; }()); // +function badAjax() { + openNotification(context.i18n.notif_request_failed, 'bad'); + location.reload(); + return true; +} + function needsScroll(elem) { const winBottom = document.documentElement.scrollTop + document.documentElement.clientHeight, elemTop = elem.offsetParent.offsetTop + elem.offsetTop, @@ -165,6 +171,9 @@ function send_mark_read_queue(queue, asRead) { for (let i = queue.length - 1; i >= 0; i--) { delete pending_entries['flux_' + queue[i]]; } + if (this.status == 403) { + badAjax(); + } }; req.onload = function (e) { if (this.status != 200) { @@ -269,6 +278,9 @@ function mark_favorite(div) { req.onerror = function (e) { openNotification(context.i18n.notif_request_failed, 'bad'); delete pending_entries[div.id]; + if (this.status == 403) { + badAjax(); + } }; req.onload = function (e) { if (this.status != 200) { @@ -918,6 +930,9 @@ function init_stream(stream) { req.responseType = 'json'; req.onerror = function (e) { checkboxTag.checked = !isChecked; + if (this.status == 403) { + badAjax(); + } }; req.onload = function (e) { if (this.status != 200) { @@ -1008,6 +1023,9 @@ function updateFeed(feeds, feeds_count) { const req = new XMLHttpRequest(); req.open('POST', feed.url, true); req.onloadend = function (e) { + if (this.status != 200) { + return badAjax(); + } feed_processed++; const div = document.getElementById('actualizeProgress'); div.querySelector('.progress').innerHTML = feed_processed + ' / ' + feeds_count; @@ -1045,9 +1063,12 @@ function init_actualize() { context.ajax_loading = true; const req = new XMLHttpRequest(); - req.open('GET', './?c=javascript&a=actualize', true); + req.open('POST', './?c=javascript&a=actualize', true); req.responseType = 'json'; req.onload = function (e) { + if (this.status != 200) { + return badAjax(); + } const json = xmlHttpRequestJson(this); if (auto && json.feeds.length < 1) { auto = false; @@ -1078,7 +1099,10 @@ function init_actualize() { updateFeed(json.feeds, feeds_count); } }; - req.send(); + req.setRequestHeader('Content-Type', 'application/json'); + req.send(JSON.stringify({ + _csrf: context.csrf, + })); return false; }; -- cgit v1.2.3 From e7a57915f9c90c144d95918048d2523418866921 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 23 Mar 2019 12:08:35 +0100 Subject: CLI user-info fixes (#2292) * CLI missing exit codes https://github.com/FreshRSS/FreshRSS/issues/2291 * CLI catch for outdated databases https://github.com/FreshRSS/FreshRSS/issues/2291#issuecomment-475856890 --- app/Models/TagDAO.php | 14 +++++++++++--- cli/list-users.php | 2 ++ cli/user-info.php | 2 ++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php index 0b4428f17..297d24c96 100644 --- a/app/Models/TagDAO.php +++ b/app/Models/TagDAO.php @@ -187,9 +187,17 @@ class FreshRSS_TagDAO extends Minz_ModelPdo implements FreshRSS_Searchable { public function count() { $sql = 'SELECT COUNT(*) AS count FROM `' . $this->prefix . 'tag`'; $stm = $this->bd->prepare($sql); - $stm->execute(); - $res = $stm->fetchAll(PDO::FETCH_ASSOC); - return $res[0]['count']; + if ($stm && $stm->execute()) { + $res = $stm->fetchAll(PDO::FETCH_ASSOC); + return $res[0]['count']; + } else { + $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo(); + if ($this->autoUpdateDb($info)) { + return $this->count(); + } + Minz_Log::error('SQL error TagDAO::count: ' . $info[2]); + return false; + } } public function countEntries($id) { diff --git a/cli/list-users.php b/cli/list-users.php index 758bbdb46..b3ce9936f 100755 --- a/cli/list-users.php +++ b/cli/list-users.php @@ -13,3 +13,5 @@ if (FreshRSS_Context::$system_conf->default_user !== '' foreach ($users as $user) { echo $user, "\n"; } + +done(); diff --git a/cli/user-info.php b/cli/user-info.php index 043bebf7c..125408c10 100755 --- a/cli/user-info.php +++ b/cli/user-info.php @@ -51,3 +51,5 @@ foreach ($users as $username) { "\n"; } } + +done(); -- cgit v1.2.3 From 1804c0e0bc095487b9a1ad13cbc9f55f6cef2a2a Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 23 Mar 2019 22:52:47 +0100 Subject: Filter actions (#2275) * Draft of filter actions * Travis * Implement UI + finish logic * Travis --- app/Controllers/feedController.php | 27 +++---- app/Controllers/subscriptionController.php | 4 +- app/Models/Entry.php | 113 +++++++++++++++++++++++++++++ app/Models/Feed.php | 104 ++++++++++++++++++++++++++ app/Models/FilterAction.php | 45 ++++++++++++ app/i18n/cz/sub.php | 4 + app/i18n/de/sub.php | 4 + app/i18n/en/sub.php | 4 + app/i18n/es/sub.php | 4 + app/i18n/fr/sub.php | 4 + app/i18n/he/sub.php | 4 + app/i18n/it/sub.php | 4 + app/i18n/kr/sub.php | 4 + app/i18n/nl/sub.php | 4 + app/i18n/oc/sub.php | 4 + app/i18n/pt-br/sub.php | 4 + app/i18n/ru/sub.php | 4 + app/i18n/tr/sub.php | 4 + app/i18n/zh-cn/sub.php | 4 + app/views/helpers/feed/update.phtml | 13 ++++ 20 files changed, 345 insertions(+), 17 deletions(-) create mode 100644 app/Models/FilterAction.php diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 7f36e0388..0aed9b0a1 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -289,7 +289,8 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } $ttl = $feed->ttl(); if ((!$simplePiePush) && (!$feed_id) && - ($feed->lastUpdate() + 10 >= time() - ($ttl == FreshRSS_Feed::TTL_DEFAULT ? FreshRSS_Context::$user_conf->ttl_default : $ttl))) { + ($feed->lastUpdate() + 10 >= time() - ( + $ttl == FreshRSS_Feed::TTL_DEFAULT ? FreshRSS_Context::$user_conf->ttl_default : $ttl))) { //Too early to refresh from source, but check whether the feed was updated by another user $mtime = $feed->cacheModifiedTime(); if ($feed->lastUpdate() + 10 >= $mtime) { @@ -347,8 +348,8 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $entry_date = $entry->date(true); if (isset($existingHashForGuids[$entry->guid()])) { $existingHash = $existingHashForGuids[$entry->guid()]; - if (strcasecmp($existingHash, $entry->hash()) === 0 || trim($existingHash, '0') == '') { - //This entry already exists and is unchanged. TODO: Remove the test with the zero'ed hash in FreshRSS v1.3 + if (strcasecmp($existingHash, $entry->hash()) === 0) { + //This entry already exists and is unchanged. $oldGuids[] = $entry->guid(); } else { //This entry already exists but has been updated //Minz_Log::debug('Entry with GUID `' . $entry->guid() . '` updated in feed ' . $feed->url(false) . @@ -374,17 +375,14 @@ class FreshRSS_feed_Controller extends Minz_ActionController { // This entry should not be added considering configuration and date. $oldGuids[] = $entry->guid(); } else { - $read_upon_reception = $feed->attributes('read_upon_reception') !== null ? ( - $feed->attributes('read_upon_reception') - ) : FreshRSS_Context::$user_conf->mark_when['reception']; $id = uTimeString(); $entry->_id($id); if ($entry_date < $date_min) { $entry->_isRead(true); //Old article that was not in database. Probably an error, so mark as read - } else { - $entry->_isRead($read_upon_reception); } + $entry->applyFilterActions(); + $entry = Minz_ExtensionManager::callHook('entry_before_insert', $entry); if ($entry === null) { // An extension has returned a null value, there is nothing to insert. @@ -392,7 +390,8 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } if ($pubSubHubbubEnabled && !$simplePiePush) { //We use push, but have discovered an article by pull! - $text = 'An article was discovered by pull although we use PubSubHubbub!: Feed ' . $url . ' GUID ' . $entry->guid(); + $text = 'An article was discovered by pull although we use PubSubHubbub!: Feed ' . $url . + ' GUID ' . $entry->guid(); Minz_Log::warning($text, PSHB_LOG); Minz_Log::warning($text); $pubSubHubbubEnabled = false; @@ -416,9 +415,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController { $entryDAO->beginTransaction(); } - $nb = $entryDAO->cleanOldEntries($feed->id(), - $date_min, - max($feed_history, count($entries) + 10)); + $nb = $entryDAO->cleanOldEntries($feed->id(), $date_min, max($feed_history, count($entries) + 10)); if ($nb > 0) { $needFeedCacheRefresh = true; Minz_Log::debug($nb . ' old entries cleaned in feed [' . $feed->url(false) . ']'); @@ -598,11 +595,9 @@ class FreshRSS_feed_Controller extends Minz_ActionController { if (self::moveFeed($feed_id, $cat_id)) { // TODO: return something useful // Log a notice to prevent "Empty IF statement" warning in PHP_CodeSniffer - Minz_Log::notice('Moved feed `' . $feed_id . '` ' . - 'in the category `' . $cat_id . '`');; + Minz_Log::notice('Moved feed `' . $feed_id . '` in the category `' . $cat_id . '`'); } else { - Minz_Log::warning('Cannot move feed `' . $feed_id . '` ' . - 'in the category `' . $cat_id . '`'); + Minz_Log::warning('Cannot move feed `' . $feed_id . '` in the category `' . $cat_id . '`'); Minz_Error::error(404); } } diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index 62fb3d384..9cf41ed0b 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -110,6 +110,8 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { $feed->_attributes('timeout', null); } + $feed->_filtersAction('read', preg_split('/[\n\r]+/', Minz_Request::param('filteractions_read', ''))); + $values = array( 'name' => Minz_Request::param('name', ''), 'description' => sanitizeHTML(Minz_Request::param('description', '', true)), @@ -121,7 +123,7 @@ class FreshRSS_subscription_Controller extends Minz_ActionController { 'httpAuth' => $httpAuth, 'keep_history' => intval(Minz_Request::param('keep_history', FreshRSS_Feed::KEEP_HISTORY_DEFAULT)), 'ttl' => $ttl * ($mute ? -1 : 1), - 'attributes' => $feed->attributes() + 'attributes' => $feed->attributes(), ); invalidateHttpCache(); diff --git a/app/Models/Entry.php b/app/Models/Entry.php index f2f3d08fe..3bb977283 100644 --- a/app/Models/Entry.php +++ b/app/Models/Entry.php @@ -185,6 +185,119 @@ class FreshRSS_Entry extends Minz_Model { $this->tags = $value; } + public function matches($booleanSearch) { + if (!$booleanSearch || count($booleanSearch->searches()) <= 0) { + return true; + } + foreach ($booleanSearch->searches() as $filter) { + $ok = true; + if ($ok && $filter->getMinPubdate()) { + $ok &= $this->date >= $filter->getMinPubdate(); + } + if ($ok && $filter->getMaxPubdate()) { + $ok &= $this->date <= $filter->getMaxPubdate(); + } + if ($ok && $filter->getMinDate()) { + $ok &= strnatcmp($this->id, $filter->getMinDate() . '000000') >= 0; + } + if ($ok && $filter->getMaxDate()) { + $ok &= strnatcmp($this->id, $filter->getMaxDate() . '000000') <= 0; + } + if ($ok && $filter->getInurl()) { + foreach ($filter->getInurl() as $url) { + $ok &= stripos($this->link, $url) !== false; + } + } + if ($ok && $filter->getNotInurl()) { + foreach ($filter->getNotInurl() as $url) { + $ok &= stripos($this->link, $url) === false; + } + } + if ($ok && $filter->getAuthor()) { + foreach ($filter->getAuthor() as $author) { + $ok &= stripos($this->authors, $author) !== false; + } + } + if ($ok && $filter->getNotAuthor()) { + foreach ($filter->getNotAuthor() as $author) { + $ok &= stripos($this->authors, $author) === false; + } + } + if ($ok && $filter->getIntitle()) { + foreach ($filter->getIntitle() as $title) { + $ok &= stripos($this->title, $title) !== false; + } + } + if ($ok && $filter->getNotIntitle()) { + foreach ($filter->getNotIntitle() as $title) { + $ok &= stripos($this->title, $title) === false; + } + } + if ($ok && $filter->getTags()) { + foreach ($filter->getTags() as $tag2) { + $found = false; + foreach ($this->tags as $tag1) { + if (strcasecmp($tag1, $tag2) === 0) { + $found = true; + } + } + $ok &= $found; + } + } + if ($ok && $filter->getNotTags()) { + foreach ($filter->getNotTags() as $tag2) { + $found = false; + foreach ($this->tags as $tag1) { + if (strcasecmp($tag1, $tag2) === 0) { + $found = true; + } + } + $ok &= !$found; + } + } + if ($ok && $filter->getSearch()) { + foreach ($filter->getSearch() as $needle) { + $ok &= (stripos($this->title, $needle) !== false || stripos($this->content, $needle) !== false); + } + } + if ($ok && $filter->getNotSearch()) { + foreach ($filter->getNotSearch() as $needle) { + $ok &= (stripos($this->title, $needle) === false && stripos($this->content, $needle) === false); + } + } + if ($ok) { + return true; + } + } + return false; + } + + public function applyFilterActions() { + if ($this->feed != null) { + if ($this->feed->attributes('read_upon_reception') || + ($this->feed->attributes('read_upon_reception') === null && FreshRSS_Context::$user_conf->mark_when['reception'])) { + $this->_isRead(true); + } + foreach ($this->feed->filterActions() as $filterAction) { + if ($this->matches($filterAction->booleanSearch())) { + foreach ($filterAction->actions() as $action => $params) { + switch ($action) { + case 'read': + $this->_isRead(true); + break; + case 'star': + $this->_is_favorite(true); + break; + case 'label': + //TODO: Implement more actions + break; + } + } + } + } + } + } + public function isDay($day, $today) { $date = $this->dateAdded(true); switch ($day) { diff --git a/app/Models/Feed.php b/app/Models/Feed.php index b21a8bbbe..89989236c 100644 --- a/app/Models/Feed.php +++ b/app/Models/Feed.php @@ -32,6 +32,7 @@ class FreshRSS_Feed extends Minz_Model { private $lockPath = ''; private $hubUrl = ''; private $selfUrl = ''; + private $filterActions = null; public function __construct($url, $validate = true) { if ($validate) { @@ -498,6 +499,109 @@ class FreshRSS_Feed extends Minz_Model { @unlink($this->lockPath); } + public function filterActions() { + if ($this->filterActions == null) { + $this->filterActions = array(); + $filters = $this->attributes('filters'); + if (is_array($filters)) { + foreach ($filters as $filter) { + $filterAction = FreshRSS_FilterAction::fromJSON($filter); + if ($filterAction != null) { + $this->filterActions[] = $filterAction; + } + } + } + } + return $this->filterActions; + } + + private function _filterActions($filterActions) { + $this->filterActions = $filterActions; + if (is_array($this->filterActions) && !empty($this->filterActions)) { + $this->_attributes('filters', array_map(function ($af) { + return $af == null ? null : $af->toJSON(); + }, $this->filterActions)); + } else { + $this->_attributes('filters', null); + } + } + + public function filtersAction($action) { + $action = trim($action); + if ($action == '') { + return array(); + } + $filters = array(); + $filterActions = $this->filterActions(); + for ($i = count($filterActions) - 1; $i >= 0; $i--) { + $filterAction = $filterActions[$i]; + if ($filterAction != null && $filterAction->booleanSearch() != null && + $filterAction->actions() != null && in_array($action, $filterAction->actions(), true)) { + $filters[] = $filterAction->booleanSearch(); + } + } + return $filters; + } + + public function _filtersAction($action, $filters) { + $action = trim($action); + if ($action == '' || !is_array($filters)) { + return false; + } + $filters = array_unique(array_map('trim', $filters)); + $filterActions = $this->filterActions(); + + //Check existing filters + for ($i = count($filterActions) - 1; $i >= 0; $i--) { + $filterAction = $filterActions[$i]; + if ($filterAction == null || !is_array($filterAction->actions()) || + $filterAction->booleanSearch() == null || trim($filterAction->booleanSearch()->getRawInput()) == '') { + array_splice($filterAction, $i, 1); + continue; + } + $actions = $filterAction->actions(); + //Remove existing rules with same action + for ($j = count($actions) - 1; $j >= 0; $j--) { + if ($actions[$j] === $action) { + array_splice($actions, $j, 1); + } + } + //Update existing filter with new action + for ($k = count($filters) - 1; $k >= 0; $k --) { + $filter = $filters[$k]; + if ($filter === $filterAction->booleanSearch()->getRawInput()) { + $actions[] = $action; + array_splice($filters, $k, 1); + } + } + //Save result + if (empty($actions)) { + array_splice($filterActions, $i, 1); + } else { + $filterAction->_actions($actions); + } + } + + //Add new filters + for ($k = count($filters) - 1; $k >= 0; $k --) { + $filter = $filters[$k]; + if ($filter != '') { + $filterAction = FreshRSS_FilterAction::fromJSON(array( + 'search' => $filter, + 'actions' => array($action), + )); + if ($filterAction != null) { + $filterActions[] = $filterAction; + } + } + } + + if (empty($filterActions)) { + $filterActions = null; + } + $this->_filterActions($filterActions); + } + // public function pubSubHubbubEnabled() { diff --git a/app/Models/FilterAction.php b/app/Models/FilterAction.php new file mode 100644 index 000000000..23a45d14e --- /dev/null +++ b/app/Models/FilterAction.php @@ -0,0 +1,45 @@ +booleanSearch = $booleanSearch; + $this->_actions($actions); + } + + public function booleanSearch() { + return $this->booleanSearch; + } + + public function actions() { + return $this->actions; + } + + public function _actions($actions) { + if (is_array($actions)) { + $this->actions = array_unique($actions); + } else { + $this->actions = null; + } + } + + public function toJSON() { + if (is_array($this->actions) && $this->booleanSearch != null) { + return array( + 'search' => $this->booleanSearch->getRawInput(), + 'actions' => $this->actions, + ); + } + return ''; + } + + public static function fromJSON($json) { + if (!empty($json['search']) && !empty($json['actions']) && is_array($json['actions'])) { + return new FreshRSS_FilterAction(new FreshRSS_BooleanSearch($json['search']), $json['actions']); + } + return null; + } +} diff --git a/app/i18n/cz/sub.php b/app/i18n/cz/sub.php index 5b5634fed..2e81c928d 100644 --- a/app/i18n/cz/sub.php +++ b/app/i18n/cz/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Popis', 'empty' => 'Kanál je prázdný. Ověřte prosím zda je ještě autorem udržován.', 'error' => 'Vyskytl se problém s kanálem. Ověřte že je vždy dostupný, prosím, a poté jej aktualizujte.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Informace', 'keep_history' => 'Zachovat tento minimální počet článků', 'moved_category_deleted' => 'Po smazání kategorie budou v ní obsažené kanály automaticky přesunuty do %s.', diff --git a/app/i18n/de/sub.php b/app/i18n/de/sub.php index 27e893177..bd050671e 100644 --- a/app/i18n/de/sub.php +++ b/app/i18n/de/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Beschreibung', 'empty' => 'Dieser Feed ist leer. Bitte stellen Sie sicher, dass er noch gepflegt wird.', 'error' => 'Dieser Feed ist auf ein Problem gestoßen. Bitte stellen Sie sicher, dass er immer lesbar ist und aktualisieren Sie ihn dann.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Information', 'keep_history' => 'Minimale Anzahl an Artikeln, die behalten wird', 'moved_category_deleted' => 'Wenn Sie eine Kategorie entfernen, werden deren Feeds automatisch in die Kategorie %s eingefügt.', diff --git a/app/i18n/en/sub.php b/app/i18n/en/sub.php index 4efd81ba4..f11eb9b99 100644 --- a/app/i18n/en/sub.php +++ b/app/i18n/en/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Description', 'empty' => 'This feed is empty. Please verify that it is still maintained.', 'error' => 'This feed has encountered a problem. Please verify that it is always reachable then update it.', + 'filteractions' => array( + '_' => 'Filter actions', + 'help' => 'Write one search filter per line.', + ), 'informations' => 'Information', 'keep_history' => 'Minimum number of articles to keep', 'moved_category_deleted' => 'When you delete a category, its feeds are automatically classified under %s.', diff --git a/app/i18n/es/sub.php b/app/i18n/es/sub.php index 854984891..c0526106f 100755 --- a/app/i18n/es/sub.php +++ b/app/i18n/es/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Descripción', 'empty' => 'La fuente está vacía. Por favor, verifica que siga activa.', 'error' => 'Hay un problema con esta fuente. Por favor, veritica que esté disponible y prueba de nuevo.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Información', 'keep_history' => 'Número mínimo de artículos a conservar', 'moved_category_deleted' => 'Al borrar una categoría todas sus fuentes pasan automáticamente a la categoría %s.', diff --git a/app/i18n/fr/sub.php b/app/i18n/fr/sub.php index d9964ac6e..b71019faa 100644 --- a/app/i18n/fr/sub.php +++ b/app/i18n/fr/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Description', 'empty' => 'Ce flux est vide. Veuillez vérifier qu’il est toujours maintenu.', 'error' => 'Ce flux a rencontré un problème. Veuillez vérifier qu’il est toujours accessible puis actualisez-le.', + 'filteractions' => array( + '_' => 'Filtres d’action', + 'help' => 'Écrivez une recherche par ligne.', + ), 'informations' => 'Informations', 'keep_history' => 'Nombre minimum d’articles à conserver', 'moved_category_deleted' => 'Lors de la suppression d’une catégorie, ses flux seront automatiquement classés dans %s.', diff --git a/app/i18n/he/sub.php b/app/i18n/he/sub.php index 6d824e349..bb2025bc3 100644 --- a/app/i18n/he/sub.php +++ b/app/i18n/he/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'תיאור', 'empty' => 'הזנה זו ריקה. אנא ודאו שהיא עדיין מתוחזקת.', 'error' => 'הזנה זו נתקלה בשגיאה, אנא ודאו שהיא תקינה ואז נסו שנית.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'מידע', 'keep_history' => 'מסםר מינימלי של מאמרים לשמור', 'moved_category_deleted' => 'כאשר הקטגוריה נמחקת ההזנות שבתוכה אוטומטית מקוטלגות תחת %s.', diff --git a/app/i18n/it/sub.php b/app/i18n/it/sub.php index ff7fa6f1d..bf279e059 100644 --- a/app/i18n/it/sub.php +++ b/app/i18n/it/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Descrizione', 'empty' => 'Questo feed non contiene articoli. Per favore verifica il sito direttamente.', 'error' => 'Questo feed ha generato un errore. Per favore verifica se ancora disponibile.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Informazioni', 'keep_history' => 'Numero minimo di articoli da mantenere', 'moved_category_deleted' => 'Cancellando una categoria i feed al suo interno verranno classificati automaticamente come %s.', diff --git a/app/i18n/kr/sub.php b/app/i18n/kr/sub.php index 9edd85818..151775c1c 100644 --- a/app/i18n/kr/sub.php +++ b/app/i18n/kr/sub.php @@ -33,6 +33,10 @@ return array( 'description' => '설명', 'empty' => '이 피드는 비어있습니다. 피드가 계속 운영되고 있는지 확인하세요.', 'error' => '이 피드에 문제가 발생했습니다. 이 피드에 접근 권한이 있는지 확인하세요.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => '정보', 'keep_history' => '최소 유지 글 개수', 'moved_category_deleted' => '카테고리를 삭제하면, 해당 카테고리 아래에 있던 피드들은 자동적으로 %s 아래로 분류됩니다.', diff --git a/app/i18n/nl/sub.php b/app/i18n/nl/sub.php index 1d6c9f806..8ba9c020d 100644 --- a/app/i18n/nl/sub.php +++ b/app/i18n/nl/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Omschrijving', 'empty' => 'Deze feed is leeg. Controleer of deze nog actueel is.', 'error' => 'Deze feed heeft problemen. Verifieer a.u.b het doeladres en actualiseer het.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Informatie', 'keep_history' => 'Minimum aantal artikelen om te houden', 'moved_category_deleted' => 'Als u een categorie verwijderd, worden de feeds automatisch geclassificeerd onder %s.', diff --git a/app/i18n/oc/sub.php b/app/i18n/oc/sub.php index fc5a0cc1f..51ee0d43f 100644 --- a/app/i18n/oc/sub.php +++ b/app/i18n/oc/sub.php @@ -32,6 +32,10 @@ return array( 'description' => 'Descripcion', 'empty' => 'Aqueste flux es void. Assegurats-vos qu’es totjorn mantengut.', 'error' => 'Aqueste flux a rescontrat un problèma. Volgatz verificar que siá totjorn accessible puèi actualizatz-lo.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Informacions', 'keep_history' => 'Nombre minimum d’articles de servar', 'moved_category_deleted' => 'Quand escafatz una categoria, sos fluxes son automaticament classats dins %s.', diff --git a/app/i18n/pt-br/sub.php b/app/i18n/pt-br/sub.php index 58b2fc1f9..fc26e89e7 100644 --- a/app/i18n/pt-br/sub.php +++ b/app/i18n/pt-br/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Descrição', 'empty' => 'Este feed está vazio. Por favor verifique ele ainda é mantido.', 'error' => 'Este feed encontra-se com problema. Por favor verifique se ele ainda está disponível e atualize-o.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Informações', 'keep_history' => 'Número mínimo de artigos para manter', 'moved_category_deleted' => 'Quando você deleta uma categoria, seus feeds são automaticamente classificados como %s.', diff --git a/app/i18n/ru/sub.php b/app/i18n/ru/sub.php index 62f8a8e3a..e125d549e 100644 --- a/app/i18n/ru/sub.php +++ b/app/i18n/ru/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Description', //TODO - Translation 'empty' => 'This feed is empty. Please verify that it is still maintained.', //TODO - Translation 'error' => 'This feed has encountered a problem. Please verify that it is always reachable then actualize it.', //TODO - Translation + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Information', //TODO - Translation 'keep_history' => 'Minimum number of articles to keep', //TODO - Translation 'moved_category_deleted' => 'When you delete a category, its feeds are automatically classified under %s.', //TODO - Translation diff --git a/app/i18n/tr/sub.php b/app/i18n/tr/sub.php index 7f29633be..9f4945c0a 100644 --- a/app/i18n/tr/sub.php +++ b/app/i18n/tr/sub.php @@ -33,6 +33,10 @@ return array( 'description' => 'Tanım', 'empty' => 'Bu akış boş. Lütfen akışın aktif olduğuna emin olun.', 'error' => 'Bu akışda bir hatayla karşılaşıldı. Lütfen akışın sürekli ulaşılabilir olduğuna emin olun.', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => 'Bilgi', 'keep_history' => 'En az tutulacak makale sayısı', 'moved_category_deleted' => 'Bir kategoriyi silerseniz, içerisindeki akışlar %s içerisine yerleşir.', diff --git a/app/i18n/zh-cn/sub.php b/app/i18n/zh-cn/sub.php index f84d08cdf..90f9fd942 100644 --- a/app/i18n/zh-cn/sub.php +++ b/app/i18n/zh-cn/sub.php @@ -33,6 +33,10 @@ return array( 'description' => '描述', 'empty' => '此源为空。请确认它是否正常更新。', 'error' => '此源遇到一些问题。请在确认是否能正常访问后重试。', + 'filteractions' => array( + '_' => 'Filter actions', //TODO - Translation + 'help' => 'Write one search filter per line.', //TODO - Translation + ), 'informations' => '信息', 'keep_history' => '至少保存的文章数', 'moved_category_deleted' => '删除分类时,其中的 RSS 源会自动归类到 %s', diff --git a/app/views/helpers/feed/update.phtml b/app/views/helpers/feed/update.phtml index bc90ba456..be8034c0d 100644 --- a/app/views/helpers/feed/update.phtml +++ b/app/views/helpers/feed/update.phtml @@ -234,6 +234,19 @@
        + +
        + +
        + + +
        +
        +
        -- cgit v1.2.3 From f2925594c7caf2753e1ac44941e029a3c1496117 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 23 Mar 2019 23:17:22 +0100 Subject: Add header to cli (#2296) * Add header to cli Now there is a switch to display the header on user info. While doing that, I've changed how the command is working to display all users by default and to accept more than one user at once. I also changed the display to make it more pleasing. As this command displays all users by default. I wonder if we still need the list user command. See #2294 * Minor format --- cli/user-info.php | 77 ++++++++++++++++++++++++++++++++++--------------------- lib/lib_rss.php | 2 +- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/cli/user-info.php b/cli/user-info.php index 125408c10..aa4db7c2f 100755 --- a/cli/user-info.php +++ b/cli/user-info.php @@ -2,19 +2,46 @@ default_user ? '*' : ' ', "\t"; $catDAO = FreshRSS_Factory::createCategoryDao(); $feedDAO = FreshRSS_Factory::createFeedDao($username); @@ -25,31 +52,23 @@ foreach ($users as $username) { $nbEntries = $entryDAO->countUnreadRead(); $nbFavorites = $entryDAO->countUnreadReadFavorites(); + $data = array( + 'default' => $username === FreshRSS_Context::$system_conf->default_user ? '*' : '', + 'user' => $username, + 'lastUpdate' => FreshRSS_UserDAO::mtime($username), + 'spaceUsed' => $databaseDAO->size(), + 'categories' => $catDAO->count(), + 'feeds' => count($feedDAO->listFeedsIds()), + 'reads' => $nbEntries['read'], + 'unreads' => $nbEntries['unread'], + 'favourites' => $nbFavorites['all'], + 'tags' => $tagDAO->count(), + ); if (isset($options['h'])) { //Human format - echo - $username, "\t", - date('c', FreshRSS_UserDAO::mtime($username)), "\t", - format_bytes($databaseDAO->size()), "\t", - $catDAO->count(), " categories\t", - count($feedDAO->listFeedsIds()), " feeds\t", - $nbEntries['read'], " reads\t", - $nbEntries['unread'], " unreads\t", - $nbFavorites['all'], " favourites\t", - $tagDAO->count(), " tags\t", - "\n"; - } else { - echo - $username, "\t", - FreshRSS_UserDAO::mtime($username), "\t", - $databaseDAO->size(), "\t", - $catDAO->count(), "\t", - count($feedDAO->listFeedsIds()), "\t", - $nbEntries['read'], "\t", - $nbEntries['unread'], "\t", - $nbFavorites['all'], "\t", - $tagDAO->count(), "\t", - "\n"; + $data['lastUpdate'] = date('c', $data['lastUpdate']); + $data['spaceUsed'] = format_bytes($data['spaceUsed']); } + vprintf(DATA_FORMAT, $data); } done(); diff --git a/lib/lib_rss.php b/lib/lib_rss.php index bff59d5cc..3e0033a61 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -170,7 +170,7 @@ function format_bytes($bytes, $precision = 2, $system = 'IEC') { $pow = $bytes === 0 ? 0 : floor(log($bytes) / log($base)); $pow = min($pow, count($units) - 1); $bytes /= pow($base, $pow); - return format_number($bytes, $precision) . ' ' . $units[$pow]; + return format_number($bytes, $precision) . ' ' . $units[$pow]; } function timestamptodate ($t, $hour = true) { -- cgit v1.2.3 From ae1da83b7f0f7efe4a33c660a4445aa3727bb884 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sat, 23 Mar 2019 23:46:59 +0100 Subject: Changelog https://github.com/FreshRSS/FreshRSS/issues/2294 https://github.com/FreshRSS/FreshRSS/pull/2296 https://github.com/FreshRSS/FreshRSS/pull/2278 https://github.com/FreshRSS/FreshRSS/issues/2046 https://github.com/FreshRSS/FreshRSS/issues/2288 https://github.com/FreshRSS/FreshRSS/pull/2290 https://github.com/FreshRSS/FreshRSS/issues/2291 https://github.com/FreshRSS/FreshRSS/pull/2292 https://github.com/FreshRSS/FreshRSS/issues/2273 https://github.com/FreshRSS/FreshRSS/pull/2276 https://github.com/FreshRSS/FreshRSS/pull/2286 https://github.com/FreshRSS/FreshRSS/issues/2281 https://github.com/FreshRSS/FreshRSS/pull/2282 --- CHANGELOG.md | 13 ++++++++++++- CREDITS.md | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06f2708a5..fae9f30c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # FreshRSS changelog -## 2019-0X-XX FreshRSS 1.13.2-dev +## 2019-03-XX FreshRSS 1.14.0-dev +* Features + * *Filter actions* feature, to auto-mark-as-read based on a search query per feed [#2275](https://github.com/FreshRSS/FreshRSS/pull/2275) + * Improve account change when using the *unsafe automatic login* [#2288](https://github.com/FreshRSS/FreshRSS/issues/2288) * UI * New themes *Ansum* and *Mapco* [#2245](https://github.com/FreshRSS/FreshRSS/pull/2245) * Rewrite jQuery and keyboard shortcut code as native JavaScript ES6 (except for graphs on the statistics pages) [#2234](https://github.com/FreshRSS/FreshRSS/pull/2234) @@ -18,14 +21,22 @@ * Fix API HTTP Authorization case-sensitivity issue introduced in FreshRSS 1.13.1 [#2233](https://github.com/FreshRSS/FreshRSS/issues/2233) * Fix breaking warning in Fever API [#2239](https://github.com/FreshRSS/FreshRSS/issues/2239) * Fix encoding problem in Fever API [#2241](https://github.com/FreshRSS/FreshRSS/issues/2241) + * Fix author semi-colon prefix in Fever API [#2281](https://github.com/FreshRSS/FreshRSS/issues/2281) * Fix the reading of the environment variable `COPY_SYSLOG_TO_STDERR` [#2260](https://github.com/FreshRSS/FreshRSS/pull/2260) + * Session fix when form login + HTTP auth are used [#2286](https://github.com/FreshRSS/FreshRSS/pull/2286) + * Fix `cli/user-info.php` for accounts using a version of the database older than 1.12.0 [#2291](https://github.com/FreshRSS/FreshRSS/issues/2291) +* CLI + * Better validation of parameters [#2046](https://github.com/FreshRSS/FreshRSS/issues/2046) + * New option `--header` to `cli/user-info.php` [#2296](https://github.com/FreshRSS/FreshRSS/pull/2296) * API * Supported by [Readably](https://play.google.com/store/apps/details?id=com.isaiasmatewos.readably) (client for Android using Fever API) * I18n * Improved Korean [#2242](https://github.com/FreshRSS/FreshRSS/pull/2242) * Improve Occitan [#2253](https://github.com/FreshRSS/FreshRSS/pull/2253) * Security + * Reworked the CSRF token interaction with the session in some edge cases [#2290](https://github.com/FreshRSS/FreshRSS/pull/2290) * Remove deprecated CSP `child-src` instruction (was already replaced by `frame-src`) [#2250](https://github.com/FreshRSS/FreshRSS/pull/2250) + * Ensure entry IDs are unique and cannot be set by feeds [#2273](https://github.com/FreshRSS/FreshRSS/issues/2273) * Misc. * Remove HHMV from Travis continuous integration [#2249](https://github.com/FreshRSS/FreshRSS/pull/2249) diff --git a/CREDITS.md b/CREDITS.md index ff3f64127..cc3cc57a4 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -13,6 +13,7 @@ People are sorted by name so please keep this order. * [Amaury Carrade](https://github.com/AmauryCarrade): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=AmauryCarrade), [Web](https://amaury.carrade.eu/) * [Anton Smirnov](https://github.com/sandfoxme): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:sandfoxme), [Web](http://sandfox.me/) * [ASMfreaK](https://github.com/ASMfreaK): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=ASMfreaK) +* [Benjamin Bouvier](https://github.com/bnjbvr): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:bnjbvr), [Web](https://benj.me/) * [chemical1979](https://github.com/chemical1979): [contributions](https://github.com/FreshRSS/FreshRSS/commits?author=chemical1979) * [Craig Andrews](https://github.com/candrews): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:candrews), [Web](http://candrews.integralblue.com/) * [Crupuk](https://github.com/Crupuk): [contributions](https://github.com/FreshRSS/FreshRSS/pulls?q=is:pr+author:Crupuk) -- cgit v1.2.3 From b2bc1f95d9f673f79cd7076758856bb19876154f Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 24 Mar 2019 00:01:50 +0100 Subject: Bump to 1.14.0-dev --- constants.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.php b/constants.php index dacbb11aa..73b092849 100644 --- a/constants.php +++ b/constants.php @@ -2,7 +2,7 @@ //NB: Do not edit; use ./constants.local.php instead. // -define('FRESHRSS_VERSION', '1.13.2-dev'); +define('FRESHRSS_VERSION', '1.14.0-dev'); define('FRESHRSS_WEBSITE', 'https://freshrss.org'); define('FRESHRSS_WIKI', 'https://freshrss.github.io/FreshRSS/'); -- cgit v1.2.3 From d3457f9ada962fc02ebc3e1c85dcaa975604826c Mon Sep 17 00:00:00 2001 From: Quentí <33203663+Quenty31@users.noreply.github.com> Date: Sun, 24 Mar 2019 18:38:40 +0100 Subject: [i18n] Update for filter actions (#2299) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mesa a jorn pels filtres d’accion --- app/i18n/oc/sub.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/i18n/oc/sub.php b/app/i18n/oc/sub.php index 51ee0d43f..5a7bb2b57 100644 --- a/app/i18n/oc/sub.php +++ b/app/i18n/oc/sub.php @@ -33,8 +33,8 @@ return array( 'empty' => 'Aqueste flux es void. Assegurats-vos qu’es totjorn mantengut.', 'error' => 'Aqueste flux a rescontrat un problèma. Volgatz verificar que siá totjorn accessible puèi actualizatz-lo.', 'filteractions' => array( - '_' => 'Filter actions', //TODO - Translation - 'help' => 'Write one search filter per line.', //TODO - Translation + '_' => 'Filtre d’accion', + 'help' => 'Escrivètz una recèrca per linha.', ), 'informations' => 'Informacions', 'keep_history' => 'Nombre minimum d’articles de servar', -- cgit v1.2.3 From 580123fdb088223865d5a1326e54907018cf373a Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Mon, 25 Mar 2019 08:46:31 +0100 Subject: Wait for mark-as-read queue before click (#2300) --- p/scripts/main.js | 55 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/p/scripts/main.js b/p/scripts/main.js index 212bf804b..1b417ecb5 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -162,7 +162,7 @@ function incUnreadsTag(tag_id, nb) { var pending_entries = {}, mark_read_queue = []; -function send_mark_read_queue(queue, asRead) { +function send_mark_read_queue(queue, asRead, callback) { const req = new XMLHttpRequest(); req.open('POST', '.?c=entry&a=read' + (asRead ? '' : '&is_read=0'), true); req.responseType = 'json'; @@ -202,21 +202,24 @@ function send_mark_read_queue(queue, asRead) { } let feed_link = div.querySelector('.website > a, a.website'); if (feed_link) { - let feed_url = feed_link.href; - let feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); + const feed_url = feed_link.href, + feed_id = feed_url.substr(feed_url.lastIndexOf('f_')); incUnreadsFeed(div, feed_id, inc); } delete pending_entries['flux_' + queue[i]]; } faviconNbUnread(); if (json.tags) { - let tagIds = Object.keys(json.tags); + const tagIds = Object.keys(json.tags); for (let i = tagIds.length - 1; i >= 0; i--) { let tagId = tagIds[i]; incUnreadsTag(tagId, (asRead ? -1 : 1) * json.tags[tagId].length); } } onScroll(); + if (callback) { + callback(); + } }; req.setRequestHeader('Content-Type', 'application/json'); req.send(JSON.stringify({ @@ -228,6 +231,19 @@ function send_mark_read_queue(queue, asRead) { var send_mark_read_queue_timeout = 0; +function send_mark_queue_tick(callback) { + send_mark_read_queue_timeout = 0; + const queue = mark_read_queue.slice(0); + mark_read_queue = []; + send_mark_read_queue(queue, true, callback); +} + +function delayedClick(a) { + if (a) { + send_mark_queue_tick(function () { a.click(); }); + } +} + function mark_read(div, only_not_read) { if (!div || !div.id || context.anonymous || (only_not_read && !div.classList.contains('not_read'))) { @@ -243,12 +259,7 @@ function mark_read(div, only_not_read) { if (asRead) { mark_read_queue.push(entryId); if (send_mark_read_queue_timeout == 0) { - send_mark_read_queue_timeout = setTimeout(function () { - send_mark_read_queue_timeout = 0; - const queue = mark_read_queue.slice(0); - mark_read_queue = []; - send_mark_read_queue(queue, asRead); - }, 1000); + send_mark_read_queue_timeout = setTimeout(function () { send_mark_queue_tick(null); }, 1000); } } else { const queue = [ entryId ]; @@ -421,7 +432,7 @@ function prev_feed() { for (let i = feeds.length - 1; i >= 0; i--) { const feed = feeds[i]; if (found && getComputedStyle(feed).display !== 'none') { - feed.querySelector('a.item-title').click(); + delayedClick(feed.querySelector('a.item-title')); break; } else if (feed.classList.contains('active')) { found = true; @@ -438,7 +449,7 @@ function next_feed() { for (let i = 0; i < feeds.length; i++) { const feed = feeds[i]; if (found && getComputedStyle(feed).display !== 'none') { - feed.querySelector('a.item-title').click(); + delayedClick(feed.querySelector('a.item-title')); break; } else if (feed.classList.contains('active')) { found = true; @@ -452,14 +463,14 @@ function next_feed() { function first_feed() { const a = document.querySelector('#aside_feed .category.active .feed:not([data-unread="0"]) a.item-title'); if (a) { - a.click(); + delayedClick(a); } } function last_feed() { const links = document.querySelectorAll('#aside_feed .category.active .feed:not([data-unread="0"]) a.item-title'); if (links && links.length > 0) { - links[links.length - 1].click(); + delayedClick(links[links.length - 1]); } } @@ -470,7 +481,7 @@ function prev_category() { do cat = cat.previousElementSibling; while (cat && getComputedStyle(cat).display === 'none'); if (cat) { - cat.querySelector('a.title').click(); + delayedClick(cat.querySelector('a.title')); } } else { last_category(); @@ -484,7 +495,7 @@ function next_category() { do cat = cat.nextElementSibling; while (cat && getComputedStyle(cat).display === 'none'); if (cat) { - cat.querySelector('a.title').click(); + delayedClick(cat.querySelector('a.title')); } } else { first_category(); @@ -494,14 +505,14 @@ function next_category() { function first_category() { const a = document.querySelector('#aside_feed .category:not([data-unread="0"]) a.title'); if (a) { - a.click(); + delayedClick(a); } } function last_category() { const links = document.querySelectorAll('#aside_feed .category:not([data-unread="0"]) a.title'); if (links && links.length > 0) { - links[links.length - 1].click(); + delayedClick(links[links.length - 1]); } } @@ -794,10 +805,10 @@ function init_shortcuts() { if (k === s.close_dropdown) { location.hash = null; return false; } if (k === s.help) { window.open(context.urls.help); return false; } if (k === s.focus_search) { document.getElementById('search').focus(); return false; } - if (k === s.normal_view) { document.querySelector('#nav_menu_views .view-normal').click(); return false; } - if (k === s.reading_view) { document.querySelector('#nav_menu_views .view-reader').click(); return false; } - if (k === s.global_view) { document.querySelector('#nav_menu_views .view-global').click(); return false; } - if (k === s.rss_view) { document.querySelector('#nav_menu_views .view-rss').click(); return false; } + if (k === s.normal_view) { delayedClick(document.querySelector('#nav_menu_views .view-normal')); return false; } + if (k === s.reading_view) { delayedClick(document.querySelector('#nav_menu_views .view-reader')); return false; } + if (k === s.global_view) { delayedClick(document.querySelector('#nav_menu_views .view-global')); return false; } + if (k === s.rss_view) { delayedClick(document.querySelector('#nav_menu_views .view-rss')); return false; } return true; }; } -- cgit v1.2.3 From 09362f15ee707280efed1fcdda1485d050fe09fa Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Wed, 27 Mar 2019 00:08:59 +0100 Subject: Minor code simplification https://github.com/FreshRSS/FreshRSS/pull/2300 --- p/scripts/main.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/p/scripts/main.js b/p/scripts/main.js index 1b417ecb5..f59976b39 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -462,9 +462,7 @@ function next_feed() { function first_feed() { const a = document.querySelector('#aside_feed .category.active .feed:not([data-unread="0"]) a.item-title'); - if (a) { - delayedClick(a); - } + delayedClick(a); } function last_feed() { @@ -504,9 +502,7 @@ function next_category() { function first_category() { const a = document.querySelector('#aside_feed .category:not([data-unread="0"]) a.title'); - if (a) { - delayedClick(a); - } + delayedClick(a); } function last_category() { -- cgit v1.2.3 From 13c13ab46bcd16ae57f95e7fd2ecaa2765667b56 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 31 Mar 2019 13:16:00 +0200 Subject: Release 1.14.0 --- CHANGELOG.md | 2 +- constants.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fae9f30c1..f43d470a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # FreshRSS changelog -## 2019-03-XX FreshRSS 1.14.0-dev +## 2019-03-31 FreshRSS 1.14.0 * Features * *Filter actions* feature, to auto-mark-as-read based on a search query per feed [#2275](https://github.com/FreshRSS/FreshRSS/pull/2275) diff --git a/constants.php b/constants.php index 73b092849..1432ced48 100644 --- a/constants.php +++ b/constants.php @@ -2,7 +2,7 @@ //NB: Do not edit; use ./constants.local.php instead. // -define('FRESHRSS_VERSION', '1.14.0-dev'); +define('FRESHRSS_VERSION', '1.14.0'); define('FRESHRSS_WEBSITE', 'https://freshrss.org'); define('FRESHRSS_WIKI', 'https://freshrss.github.io/FreshRSS/'); -- cgit v1.2.3