From 59c17a3c6c26d6b487e2ec5e02caa3fb26f9ff9c Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 27 Sep 2014 08:20:13 -0400 Subject: Fix read all shortcut Before, the read all shortcut raised a javascript exception when we use the confirmation option. The confirmation was not even displayed. The code was failling since there was a missing variable. Now, the shortcut ask for confirmation when the option is selected in the reading configuration page. The definition of the shortcut was buggy since the confirmation was handled properly in an other location. I simplified the code by removing the confirmation code in the shortcut. --- p/scripts/main.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index f6d5d2907..8a45ae896 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -538,14 +538,7 @@ function init_shortcuts() { }); shortcut.add("shift+" + shortcuts.mark_read, function () { // on marque tout comme lu - var btn = $(".nav_menu .read_all"); - if (btn.hasClass('confirm')) { - if (confirm(str_confirmation)) { - btn.click(); - } - } else { - btn.click(); - } + $(".nav_menu .read_all").click(); }, { 'disable_in_input': true }); -- cgit v1.2.3 From 7481887db746fd2d6eefab021776b8abd4076429 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Wed, 1 Oct 2014 10:06:04 +0200 Subject: Load feed configuration on the same page Need improvements See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/Controllers/configureController.php | 4 ++++ app/views/configure/categorize.phtml | 5 ++++- app/views/configure/feed.phtml | 8 ++++++-- p/scripts/main.js | 30 ++++++++++++++++++++++++++++++ p/themes/base-theme/template.css | 5 +++++ 5 files changed, 49 insertions(+), 3 deletions(-) (limited to 'p/scripts/main.js') diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index a7def6d9a..dd7a0a441 100755 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -90,6 +90,10 @@ class FreshRSS_configure_Controller extends Minz_ActionController { * Default values are empty strings unless specified. */ public function feedAction() { + if (Minz_Request::param('ajax')) { + $this->view->_useLayout(false); + } + $catDAO = new FreshRSS_CategoryDAO(); $this->view->categories = $catDAO->listCategories(false); diff --git a/app/views/configure/categorize.phtml b/app/views/configure/categorize.phtml index 8f77f9724..008dc8c98 100644 --- a/app/views/configure/categorize.phtml +++ b/app/views/configure/categorize.phtml @@ -73,7 +73,7 @@ $empty = $feed->nbEntries() == 0 ? ' empty' : ''; ?>
  • - + ✇ name(); ?>
  • + +
    +
    diff --git a/app/views/configure/feed.phtml b/app/views/configure/feed.phtml index e96a28739..f58ac65af 100644 --- a/app/views/configure/feed.phtml +++ b/app/views/configure/feed.phtml @@ -1,8 +1,12 @@ -partial ('aside_feed'); ?> +partial('aside_feed'); + } +?> flux) { ?>
    - +

    flux->name (); ?>

    flux->description (); ?> diff --git a/p/scripts/main.js b/p/scripts/main.js index f6d5d2907..7fed7a819 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1240,6 +1240,35 @@ function faviconNbUnread(n) { } } +function init_slider_observers() { + var slider = $('#slider'); + if (slider.length < 1) { + return; + } + + $('.open-slider').on('click', function() { + if (ajax_loading) { + return false; + } + + ajax_loading = true; + + var url_slide = $(this).attr('href'); + + $.ajax({ + type: 'GET', + url: url_slide, + data : { ajax: true } + }).done(function (data) { + slider.html(data); + slider.show(); + ajax_loading = false; + }); + + return false; + }) +} + function init_all() { if (!(window.$ && window.url_freshrss)) { if (window.console) { @@ -1275,6 +1304,7 @@ function init_all() { init_feed_observers(); init_password_observers(); init_stats_observers(); + init_slider_observers(); } if (window.console) { diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index a5a29ab23..397f943a6 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -645,6 +645,11 @@ br + br + br { display: none; } +/*=== Slider */ +#slider { + min-height: 50px; +} + /*=== DIVERS */ /*===========*/ .nav-login, -- cgit v1.2.3 From 405f23050b18e8388edb6f8be90aa59c17ada421 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Wed, 1 Oct 2014 13:55:30 +0200 Subject: Design of the slider See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/views/subscription/index.phtml | 5 +++-- p/scripts/main.js | 14 ++++++++++---- p/themes/base-theme/template.css | 24 +++++++++++++++++++++++- 3 files changed, 36 insertions(+), 7 deletions(-) (limited to 'p/scripts/main.js') diff --git a/app/views/subscription/index.phtml b/app/views/subscription/index.phtml index 2d55890f7..10578bdd3 100644 --- a/app/views/subscription/index.phtml +++ b/app/views/subscription/index.phtml @@ -134,9 +134,10 @@
    -
    + +
    feed) ? ' class="active"' : ''; ?>> feed) && $this->feed) { + if (isset($this->feed)) { $this->renderHelper('feed/update'); } ?> diff --git a/p/scripts/main.js b/p/scripts/main.js index 7fed7a819..925a93650 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1241,7 +1241,8 @@ function faviconNbUnread(n) { } function init_slider_observers() { - var slider = $('#slider'); + var slider = $('#slider'), + closer = $('#close-slider'); if (slider.length < 1) { return; } @@ -1252,7 +1253,6 @@ function init_slider_observers() { } ajax_loading = true; - var url_slide = $(this).attr('href'); $.ajax({ @@ -1261,12 +1261,18 @@ function init_slider_observers() { data : { ajax: true } }).done(function (data) { slider.html(data); - slider.show(); + closer.addClass('active'); + slider.addClass('active'); ajax_loading = false; }); return false; - }) + }); + + closer.on('click', function() { + closer.removeClass('active'); + slider.removeClass('active'); + }); } function init_all() { diff --git a/p/themes/base-theme/template.css b/p/themes/base-theme/template.css index 397f943a6..e6c832ee4 100644 --- a/p/themes/base-theme/template.css +++ b/p/themes/base-theme/template.css @@ -647,7 +647,29 @@ br + br + br { /*=== Slider */ #slider { - min-height: 50px; + position: fixed; + top: 0; bottom: 0; + left: 100%; right: 0; + overflow: auto; + background: #fff; + border-left: 1px solid #aaa; + transition: left 200ms linear; + -moz-transition: left 200ms linear; + -webkit-transition: left 200ms linear; + -o-transition: left 200ms linear; + -ms-transition: left 200ms linear; +} +#slider.active { + left: 40%; +} +#close-slider { + position: fixed; + top: 0; bottom: 0; + left: 100%; right: 0; + cursor: pointer; +} +#close-slider.active { + left: 0; } /*=== DIVERS */ -- cgit v1.2.3 From fe655e0d9d2fb1173099d77c478bbb2f7ac8b1e1 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Wed, 1 Oct 2014 13:58:09 +0200 Subject: Fix close slider when a feed is selected See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/views/subscription/index.phtml | 5 +++-- p/scripts/main.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'p/scripts/main.js') diff --git a/app/views/subscription/index.phtml b/app/views/subscription/index.phtml index 10578bdd3..577ddd972 100644 --- a/app/views/subscription/index.phtml +++ b/app/views/subscription/index.phtml @@ -134,8 +134,9 @@
    - -
    feed) ? ' class="active"' : ''; ?>> +feed) ? ' class="active"' : ''; ?> +> +
    > feed)) { $this->renderHelper('feed/update'); diff --git a/p/scripts/main.js b/p/scripts/main.js index 925a93650..005dc961b 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1272,6 +1272,7 @@ function init_slider_observers() { closer.on('click', function() { closer.removeClass('active'); slider.removeClass('active'); + return false; }); } -- cgit v1.2.3 From 9b2ad32e98e4720d5ee422fccd3069f086ee8563 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 2 Oct 2014 10:05:26 +0200 Subject: Fix a bug in main.js In global view, there is no ".category.all>a" element so we tried to apply str2int on an undefined value. In consequence, we were not able to mark several articles as read This patch need to apply on 0.8.1 and 0.9.1 See https://github.com/marienfressinaud/FreshRSS/issues/649 --- p/scripts/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index 7cd53c745..c9e8dd299 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -33,7 +33,7 @@ function needsScroll($elem) { } function str2int(str) { - if (str == '') { + if (str == '' || str === undefined) { return 0; } return parseInt(str.replace(/\D/g, ''), 10) || 0; -- cgit v1.2.3 From db4da3babc0864099c5ab48e3583d0546a2759d8 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 2 Oct 2014 11:39:51 +0200 Subject: First draft for drag and drop We can change feed category by drag and drop! Need improvements... See https://github.com/marienfressinaud/FreshRSS/issues/646 --- app/Controllers/feedController.php | 15 ++++++++ app/Controllers/subscriptionController.php | 2 ++ app/views/subscription/index.phtml | 4 +-- p/scripts/category.js | 55 ++++++++++++++++++++++++++++++ p/scripts/main.js | 2 +- p/themes/Origine/origine.css | 9 +++++ 6 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 p/scripts/category.js (limited to 'p/scripts/main.js') diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index e4859b110..315665ef3 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -378,6 +378,21 @@ class FreshRSS_feed_Controller extends Minz_ActionController { } } + public function moveAction() { + if (Minz_Request::isPost()) { + $feed_id = Minz_Request::param('f_id'); + $cat_id = Minz_Request::param('c_id'); + + $feedDAO = FreshRSS_Factory::createFeedDao(); + + $values = array( + 'category' => $cat_id, + ); + + $feedDAO->updateFeed($feed_id, $values); + } + } + public function deleteAction() { if (Minz_Request::isPost()) { $id = Minz_Request::param('id'); diff --git a/app/Controllers/subscriptionController.php b/app/Controllers/subscriptionController.php index aabae7b8f..7cc8179a0 100644 --- a/app/Controllers/subscriptionController.php +++ b/app/Controllers/subscriptionController.php @@ -30,6 +30,8 @@ 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::prependTitle(_t('subscription_management') . ' · '); $id = Minz_Request::param('id'); diff --git a/app/views/subscription/index.phtml b/app/views/subscription/index.phtml index 577ddd972..3a79a34e6 100644 --- a/app/views/subscription/index.phtml +++ b/app/views/subscription/index.phtml @@ -113,14 +113,14 @@
    -
      +
        inError() ? ' error' : ''; $empty = $feed->nbEntries() == 0 ? ' empty' : ''; ?> -
      • +
      • ✇ name(); ?>
      • diff --git a/p/scripts/category.js b/p/scripts/category.js new file mode 100644 index 000000000..fe80c3b22 --- /dev/null +++ b/p/scripts/category.js @@ -0,0 +1,55 @@ +"use strict"; + + +function init_draggable() { + var feeds_draggable = '.box-content > .feed', + box_dropzone = '.box-content'; + + $('.box').on('dragstart', feeds_draggable, function(e) { + e.originalEvent.dataTransfer.effectAllowed = 'move'; + e.originalEvent.dataTransfer.setData('html', e.target.outerHTML); + e.originalEvent.dataTransfer.setData('feed-id', e.target.getAttribute('data-feed-id')); + }); + $('.box').on('dragend', feeds_draggable, function(e) { + var parent = e.target.parentNode; + parent.removeChild(e.target); + }); + + $('.box').on('dragenter', box_dropzone, function(e) { + $(e.target).addClass('drag-hover'); + }); + $('.box').on('dragleave', box_dropzone, function(e) { + $(e.target).removeClass('drag-hover'); + }); + $('.box').on('dragover', box_dropzone, function(e) { + e.originalEvent.dataTransfer.dropEffect = "move"; + + return false; + }); + $('.box').on('drop', box_dropzone, function(e) { + var feed_id = e.originalEvent.dataTransfer.getData('feed-id'), + cat_id = e.target.parentNode.getAttribute('data-cat-id'); + + $.ajax({ + type: 'POST', + url: './?c=feed&a=move', + data : { + f_id: feed_id, + c_id: cat_id + } + }); + + $(e.target).after(e.originalEvent.dataTransfer.getData('html')); + $(e.target).removeClass('drag-hover'); + return false; + }); +} + + +if (document.readyState && document.readyState !== 'loading') { + init_draggable(); +} else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', function () { + init_draggable(); + }, false); +} diff --git a/p/scripts/main.js b/p/scripts/main.js index 005dc961b..e8055e00f 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1247,7 +1247,7 @@ function init_slider_observers() { return; } - $('.open-slider').on('click', function() { + $('.post').on('click', '.open-slider', function() { if (ajax_loading) { return false; } diff --git a/p/themes/Origine/origine.css b/p/themes/Origine/origine.css index e3ae85075..cf6c9a2ef 100644 --- a/p/themes/Origine/origine.css +++ b/p/themes/Origine/origine.css @@ -497,6 +497,15 @@ a.btn { visibility: visible; } +/*=== Draggable */ +.drag-hover { + background: #dfd; + transition: all linear 0.2s; +} +[draggable=true] { + cursor: grab; +} + /*=== STRUCTURE */ /*===============*/ /*=== Header */ -- cgit v1.2.3 From 91cc88209c710e64cd8a10397e56d006d4566624 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 4 Oct 2014 08:45:57 -0400 Subject: Remove debugging code --- p/scripts/main.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index 37281a907..02d16ca64 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -384,8 +384,6 @@ function collapse_entry() { } function user_filter(key) { - console.log('user filter'); - console.warn(key); var filter = $('#dropdown-query'); var filters = filter.siblings('.dropdown-menu').find('.item.query a'); if (typeof key === "undefined") { -- cgit v1.2.3 From 38a6f0c4b29e5a53c21f345dd839a4fa0b2a6f47 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Sat, 4 Oct 2014 09:06:35 -0400 Subject: Add a shortcut to close drop-down lists --- app/Models/Configuration.php | 1 + app/i18n/en.php | 1 + app/i18n/fr.php | 1 + app/views/configure/shortcut.phtml | 7 +++++++ app/views/helpers/javascript_vars.phtml | 3 ++- p/scripts/main.js | 6 ++++++ 6 files changed, 18 insertions(+), 1 deletion(-) (limited to 'p/scripts/main.js') diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php index 95f819779..feba3d2f6 100644 --- a/app/Models/Configuration.php +++ b/app/Models/Configuration.php @@ -47,6 +47,7 @@ class FreshRSS_Configuration { 'focus_search' => 'a', 'user_filter' => 'u', 'help' => 'f1', + 'close_dropdown' => 'escape', ), 'topline_read' => true, 'topline_favorite' => true, diff --git a/app/i18n/en.php b/app/i18n/en.php index 28104196e..0456049a9 100644 --- a/app/i18n/en.php +++ b/app/i18n/en.php @@ -191,6 +191,7 @@ return array ( 'user_filter' => 'Access user filters', 'user_filter_help' => 'If there is only one user filter, it is used. Else filters are accessible by their number.', 'help' => 'Display documentation', + 'close_dropdown' => 'Close drop-down lists', 'file_to_import' => 'File to import
        (OPML, Json or Zip)', 'file_to_import_no_zip' => 'File to import
        (OPML or Json)', diff --git a/app/i18n/fr.php b/app/i18n/fr.php index c72fc3e93..adc79d0e2 100644 --- a/app/i18n/fr.php +++ b/app/i18n/fr.php @@ -191,6 +191,7 @@ return array ( '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.', 'help' => 'Afficher la documentation', + 'close_dropdown' => 'Fermer les listes déroulantes', 'file_to_import' => 'Fichier à importer
        (OPML, Json ou Zip)', 'file_to_import_no_zip' => 'Fichier à importer
        (OPML ou Json)', diff --git a/app/views/configure/shortcut.phtml b/app/views/configure/shortcut.phtml index a4029b676..44727e62b 100644 --- a/app/views/configure/shortcut.phtml +++ b/app/views/configure/shortcut.phtml @@ -111,6 +111,13 @@
    +
    + +
    + +
    +
    +
    diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 71798369d..4f7e3db0c 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -28,7 +28,8 @@ echo ',shortcuts={', 'auto_share:"', $s['auto_share'], '",', 'focus_search:"', $s['focus_search'], '",', 'user_filter:"', $s['user_filter'], '",', - 'help:"', $s['help'], '"', + 'help:"', $s['help'], '",', + 'close_dropdown:"', $s['close_dropdown'], '"', "},\n"; if (Minz_Request::param ('output') === 'global') { diff --git a/p/scripts/main.js b/p/scripts/main.js index 37281a907..0d90d3d39 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -663,6 +663,12 @@ function init_shortcuts() { 'disable_in_input': true }); + shortcut.add(shortcuts.close_dropdown, function () { + window.location.hash = null; + }, { + 'disable_in_input': true + }); + } function init_stream(divStream) { -- cgit v1.2.3 From 6e6d7b3c870975b2981f653b6f53a31f800f56ec Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Sun, 5 Oct 2014 01:43:29 +0200 Subject: Minor JavaScript --- p/scripts/main.js | 2 +- p/scripts/shortcut.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index 79a34ec29..5793bb50b 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -33,7 +33,7 @@ function needsScroll($elem) { } function str2int(str) { - if (str == '' || str === undefined) { + if (!str) { return 0; } return parseInt(str.replace(/\D/g, ''), 10) || 0; diff --git a/p/scripts/shortcut.js b/p/scripts/shortcut.js index 4137172c3..e78cf6f5e 100644 --- a/p/scripts/shortcut.js +++ b/p/scripts/shortcut.js @@ -43,7 +43,7 @@ shortcut = { //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)) { + 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(); } -- cgit v1.2.3 From d8ed718aab99ad47897fb70ea9086fa704bb912b Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Sun, 5 Oct 2014 17:29:09 +0200 Subject: Refactor javascript_vars.phtml Introduce kind of context objectin JavaScript See https://github.com/marienfressinaud/FreshRSS/issues/634 See https://github.com/marienfressinaud/FreshRSS/issues/655 --- app/views/helpers/javascript_vars.phtml | 79 ++++++++++++++++----------------- p/scripts/category.js | 4 +- p/scripts/global_view.js | 2 +- p/scripts/main.js | 66 ++++++++++++--------------- 4 files changed, 70 insertions(+), 81 deletions(-) (limited to 'p/scripts/main.js') diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 011b17b7a..cdbf24eab 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -1,21 +1,30 @@ +"use strict"; conf->mark_when; -echo 'var ', - 'help_url="', FRESHRSS_WIKI, '"', - ',hide_posts=', ($this->conf->display_posts || Minz_Request::param('output') === 'reader') ? 'false' : 'true', - ',display_order="', Minz_Request::param('order', $this->conf->sort_order), '"', - ',auto_mark_article=', $mark['article'] ? 'true' : 'false', - ',auto_mark_site=', $mark['site'] ? 'true' : 'false', - ',auto_mark_scroll=', $mark['scroll'] ? 'true' : 'false', - ',auto_load_more=', $this->conf->auto_load_more ? 'true' : 'false', - ',does_lazyload=', $this->conf->lazyload ? 'true' : 'false', - ',sticky_post=', $this->conf->sticky_post ? 'true' : 'false'; - +$mail = Minz_Session::param ('mail', false); +$auto_actualize = Minz_Session::param('actualize_feeds', false); +$hide_posts = ($this->conf->display_posts || + Minz_Request::param('output') === 'reader'); $s = $this->conf->shortcuts; -echo ',shortcuts={', + +echo 'var context={', + 'hide_posts:', $hide_posts ? 'false' : 'true', ',', + 'display_order:"', Minz_Request::param('order', $this->conf->sort_order), '",', + 'auto_mark_article:', $mark['article'] ? 'true' : 'false', ',', + 'auto_mark_site:', $mark['site'] ? 'true' : 'false', ',', + 'auto_mark_scroll:', $mark['scroll'] ? 'true' : 'false', ',', + 'auto_load_more:', $this->conf->auto_load_more ? 'true' : 'false', ',', + 'auto_actualize_feeds:', $auto_actualize ? 'true' : 'false', ',', + 'does_lazyload:', $this->conf->lazyload ? 'true' : 'false', ',', + 'sticky_post:', $this->conf->sticky_post ? 'true' : 'false', ',', + 'html5_notif_timeout:', $this->conf->html5_notif_timeout, ',', + 'auth_type:"', Minz_Configuration::authType(), '",', + 'current_user_mail:', $mail ? ('"' . $mail . '"') : 'null', ',', + 'current_view:"', Minz_Request::param('output', 'normal'), '"', +"},\n"; + +echo 'shortcuts={', 'mark_read:"', $s['mark_read'], '",', 'mark_favorite:"', $s['mark_favorite'], '",', 'go_website:"', $s['go_website'], '",', @@ -32,32 +41,20 @@ echo ',shortcuts={', 'close_dropdown:"', $s['close_dropdown'], '"', "},\n"; -if (Minz_Request::param ('output') === 'global') { - echo "iconClose='", _i('close'), "',\n"; -} - -$authType = Minz_Configuration::authType(); -if ($authType === 'persona') { - // If user is disconnected, current_user_mail MUST be null - $mail = Minz_Session::param ('mail', false); - if ($mail) { - echo 'current_user_mail="' . $mail . '",'; - } else { - echo 'current_user_mail=null,'; - } -} - -echo 'authType="', $authType, '",', - 'url_freshrss="', _url ('index', 'index'), '",', - 'url_login="', _url ('index', 'login'), '",', - 'url_logout="', _url ('index', 'logout'), '",'; - -echo 'str_confirmation_default="', _t('confirm_action'), '"', ",\n"; -echo 'str_notif_title_articles="', _t('notif_title_new_articles'), '"', ",\n"; -echo 'str_notif_body_articles="', _t('notif_body_new_articles'), '"', ",\n"; -echo 'str_category_empty="', _t('category_empty'), '"', ",\n"; -echo 'html5_notif_timeout=', $this->conf->html5_notif_timeout,",\n"; +echo 'url={', + 'index:"', _url('index', 'index'), '",', + 'login:"', _url('index', 'login'), '",', + 'logout:"', _url('index', 'logout'), '",', + 'help:"', FRESHRSS_WIKI, '"', +"},\n"; +echo 'i18n={', + 'confirmation_default:"', _t('confirm_action'), '",', + 'notif_title_articles:"', _t('notif_title_new_articles'), '",', + 'notif_body_articles:"', _t('notif_body_new_articles'), '",', + 'category_empty:"', _t('category_empty'), '"', +"},\n"; -$autoActualise = Minz_Session::param('actualize_feeds', false); -echo 'auto_actualize_feeds=', $autoActualise ? 'true' : 'false', ";\n"; +echo 'icons={', + 'close:\'', _i('close'), '\'', +"}\n"; \ No newline at end of file diff --git a/p/scripts/category.js b/p/scripts/category.js index dc5df67e4..c33e68528 100644 --- a/p/scripts/category.js +++ b/p/scripts/category.js @@ -20,13 +20,13 @@ function dragend_process(t) { $(t).remove(); if (parent.children().length <= 0) { - parent.append('
  • ' + str_category_empty + '
  • '); + parent.append('
  • ' + i18n['category_empty'] + '
  • '); } } } function init_draggable() { - if (!(window.$ && window.url_freshrss)) { + if (!(window.$ && window.i18n)) { if (window.console) { console.log('FreshRSS waiting for JS…'); } diff --git a/p/scripts/global_view.js b/p/scripts/global_view.js index 7105520a6..6e1f61066 100644 --- a/p/scripts/global_view.js +++ b/p/scripts/global_view.js @@ -40,7 +40,7 @@ function load_panel(link) { function init_close_panel() { $("#panel .close").click(function () { - $("#panel").html('' + window.iconClose + ''); + $("#panel").html('' + icons['close'] + ''); init_close_panel(); $("#panel").slideToggle(); $("#overlay").fadeOut(); diff --git a/p/scripts/main.js b/p/scripts/main.js index 5793bb50b..ad33f6c57 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -4,14 +4,6 @@ var $stream = null, shares = 0, ajax_loading = false; -function is_normal_mode() { - return $stream.hasClass('normal'); -} - -function is_global_mode() { - return $stream.hasClass('global'); -} - function redirect(url, new_tab) { if (url) { if (new_tab) { @@ -226,7 +218,7 @@ function toggleContent(new_active, old_active) { return; } - if (does_lazyload) { + if (context['does_lazyload']) { new_active.find('img[data-original], iframe[data-original]').each(function () { this.setAttribute('src', this.getAttribute('data-original')); this.removeAttribute('data-original'); @@ -245,12 +237,12 @@ function toggleContent(new_active, old_active) { var box_to_move = "html,body", relative_move = false; - if (is_global_mode()) { + if (context['current_view'] == 'global') { box_to_move = "#panel"; relative_move = true; } - if (sticky_post) { + if (context['sticky_post']) { var prev_article = new_active.prevAll('.flux'), new_pos = new_active.position().top, old_scroll = $(box_to_move).scrollTop(); @@ -259,7 +251,7 @@ function toggleContent(new_active, old_active) { new_pos = prev_article.position().top; } - if (hide_posts) { + if (context['hide_posts']) { if (relative_move) { new_pos += old_scroll; } @@ -278,7 +270,7 @@ function toggleContent(new_active, old_active) { } } - if (auto_mark_article && new_active.hasClass('active')) { + if (context['auto_mark_article'] && new_active.hasClass('active')) { mark_read(new_active, true); } } @@ -378,7 +370,7 @@ function collapse_entry() { var flux_current = $(".flux.current"); flux_current.toggleClass("active"); - if (isCollapsed && auto_mark_article) { + if (isCollapsed && context['auto_mark_article']) { mark_read(flux_current, true); } } @@ -457,12 +449,12 @@ function inMarkViewport(flux, box_to_follow, relative_follow) { function init_posts() { var box_to_follow = $(window), relative_follow = false; - if (is_global_mode()) { + if (context['current_view'] == 'global') { box_to_follow = $("#panel"); relative_follow = true; } - if (auto_mark_scroll) { + if (context['auto_mark_scroll']) { box_to_follow.scroll(function () { $('.not_read:visible').each(function () { if ($(this).children(".flux_content").is(':visible') && inMarkViewport($(this), box_to_follow, relative_follow)) { @@ -472,7 +464,7 @@ function init_posts() { }); } - if (auto_load_more) { + if (context['auto_load_more']) { box_to_follow.scroll(function () { var load_more = $("#load_more"); if (!load_more.is(':visible')) { @@ -492,7 +484,7 @@ function init_posts() { } function init_column_categories() { - if (!is_normal_mode()) { + if (context['current_view'] !== 'normal') { return; } $('#aside_flux').on('click', '.category>a.dropdown-toggle', function () { @@ -632,7 +624,7 @@ function init_shortcuts() { shortcut.add(shortcuts.go_website, function () { var url_website = $('.flux.current > .flux_header > .title > a').attr("href"); - if (auto_mark_site) { + if (context['auto_mark_site']) { $(".flux.current").each(function () { mark_read($(this), true); }); @@ -656,7 +648,7 @@ function init_shortcuts() { }); shortcut.add(shortcuts.help, function () { - redirect(help_url, true); + redirect(url['help'], true); }, { 'disable_in_input': true }); @@ -678,7 +670,7 @@ function init_stream(divStream) { new_active = $(this).parent(); isCollapsed = true; if (e.target.tagName.toUpperCase() === 'A') { //Leave real links alone - if (auto_mark_article) { + if (context['auto_mark_article']) { mark_read(new_active, true); } return true; @@ -724,7 +716,7 @@ function init_stream(divStream) { $(this).attr('target', '_blank'); }); - if (auto_mark_site) { + 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) { @@ -784,7 +776,7 @@ function init_actualize() { return false; }); - if (auto_actualize_feeds) { + if (context['auto_actualize_feeds']) { auto = true; $("#actualize").click(); } @@ -855,9 +847,9 @@ function notifs_html5_show(nb) { return } - var notification = new window.Notification(str_notif_title_articles, { + var notification = new window.Notification(i18n['notif_title_articles'], { icon: "../themes/icons/favicon-256.png", - body: str_notif_body_articles.replace("\d", nb), + body: i18n['notif_body_articles.replace("\d", nb)'], tag: "freshRssNewArticles" }); @@ -865,10 +857,10 @@ function notifs_html5_show(nb) { window.location.reload(); } - if (html5_notif_timeout !== 0){ + if (context['html5_notif_timeout'] !== 0){ setTimeout(function() { notification.close(); - }, html5_notif_timeout * 1000); + }, context['html5_notif_timeout'] * 1000); } } @@ -922,7 +914,7 @@ function load_more_posts() { $.get(url_load_more, function (data) { box_load_more.children('.flux:last').after($('#stream', data).children('.flux, .day')); $('.pagination').replaceWith($('.pagination', data)); - if (display_order === 'ASC') { + if (context['display_order'] === 'ASC') { $('#nav_menu_read_all > .read_all').attr( 'formaction', $('#bigMarkAsRead').attr('formaction') ); @@ -953,7 +945,7 @@ function focus_search() { function init_load_more(box) { box_load_more = box; - if (!does_lazyload) { + if (!context['does_lazyload']) { $('img[postpone], audio[postpone], iframe[postpone], video[postpone]').each(function () { this.removeAttribute('postpone'); }); @@ -1062,7 +1054,7 @@ function init_persona() { }); navigator.id.watch({ - loggedInUser: current_user_mail, + loggedInUser: context['current_user_mail'], onlogin: function(assertion) { // A user has logged in! Here you need to: @@ -1070,13 +1062,13 @@ function init_persona() { // 2. Update your UI. $.ajax ({ type: 'POST', - url: url_login, + url: url['login'], data: {assertion: assertion}, success: function(res, status, xhr) { /*if (res.status === 'failure') { alert (res_obj.reason); } else*/ if (res.status === 'okay') { - location.href = url_freshrss; + location.href = url['index']; } }, error: function(res, status, xhr) { @@ -1091,9 +1083,9 @@ function init_persona() { // (That's a literal JavaScript null. Not false, 0, or undefined. null.) $.ajax ({ type: 'POST', - url: url_logout, + url: url['logout'], success: function(res, status, xhr) { - location.href = url_freshrss; + location.href = url['index']; }, error: function(res, status, xhr) { //alert("logout failure" + res); @@ -1108,7 +1100,7 @@ function init_confirm_action() { $('body').on('click', '.confirm', function () { var str_confirmation = $(this).attr('data-str-confirm'); if (!str_confirmation) { - str_confirmation = str_confirmation_default; + str_confirmation = i18n['confirmation_default']; } return confirm(str_confirmation); @@ -1274,7 +1266,7 @@ function init_slider_observers() { } function init_all() { - if (!(window.$ && window.url_freshrss)) { + if (!(window.$ && window.context)) { if (window.console) { console.log('FreshRSS waiting for JS…'); } @@ -1282,7 +1274,7 @@ function init_all() { return; } init_notifications(); - switch (authType) { + switch (context['auth_type']) { case 'persona': init_persona(); break; -- cgit v1.2.3 From 3831961b2e515ff7d8d352c0f7b6a15b3a613c25 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Sun, 5 Oct 2014 18:03:32 +0200 Subject: Fix bug of i18n in JavaScript See https://github.com/marienfressinaud/FreshRSS/issues/655 --- p/scripts/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index ad33f6c57..b01a3a34d 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -849,7 +849,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)'], + body: i18n['notif_body_articles'].replace("\d", nb), tag: "freshRssNewArticles" }); -- cgit v1.2.3 From 1252b3dd867e59917cf303f0c39c7da938b8ce32 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Tue, 7 Oct 2014 16:37:10 +0200 Subject: Authentication system moved + Persona comes back! AuthController is dedicated to auhentication. Persona is back, greater than ever! See https://github.com/marienfressinaud/FreshRSS/issues/655 --- app/Controllers/authController.php | 182 ++++++++++++++++++++++++++++++++ app/Controllers/indexController.php | 90 +--------------- app/FreshRSS.php | 8 ++ app/Models/Auth.php | 21 +++- app/layout/header.phtml | 23 ++-- app/views/auth/formLogin.phtml | 28 +++++ app/views/auth/logout.phtml | 0 app/views/auth/personaLogin.phtml | 24 +++++ app/views/helpers/javascript_vars.phtml | 13 ++- app/views/index/formLogin.phtml | 46 -------- p/scripts/main.js | 65 ------------ p/scripts/persona.js | 76 +++++++++++++ 12 files changed, 356 insertions(+), 220 deletions(-) create mode 100644 app/Controllers/authController.php create mode 100644 app/views/auth/formLogin.phtml create mode 100644 app/views/auth/logout.phtml create mode 100644 app/views/auth/personaLogin.phtml delete mode 100644 app/views/index/formLogin.phtml create mode 100644 p/scripts/persona.js (limited to 'p/scripts/main.js') diff --git a/app/Controllers/authController.php b/app/Controllers/authController.php new file mode 100644 index 000000000..2b67e34b8 --- /dev/null +++ b/app/Controllers/authController.php @@ -0,0 +1,182 @@ + 'index', 'a' => 'index'), true); + } + + $auth_type = Minz_Configuration::authType(); + switch ($auth_type) { + case 'form': + Minz_Request::forward(array('c' => 'auth', 'a' => 'formLogin')); + break; + case 'persona': + Minz_Request::forward(array('c' => 'auth', 'a' => 'personaLogin')); + break; + case 'http_auth': + case 'none': + // It should not happened! + Minz_Error::error(404); + default: + // TODO load plugin instead + Minz_Error::error(404); + } + } + + /** + * This action handles form login page. + * + * If this action is reached through a POST request, username and password + * are compared to login the current user. + * + * Parameters are: + * - nonce (default: false) + * - username (default: '') + * - challenge (default: '') + * - keep_logged_in (default: false) + */ + 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)); + + if (Minz_Request::isPost()) { + $nonce = Minz_Session::param('nonce'); + $username = Minz_Request::param('username', ''); + $challenge = Minz_Request::param('challenge', ''); + try { + $conf = new FreshRSS_Configuration($username); + } catch(Minz_Exception $e) { + // $username is not a valid user, nor the configuration file! + Minz_Log::warning('Login failure: ' . $e->getMessage()); + Minz_Request::bad(_t('invalid_login'), + array('c' => 'auth', 'a' => 'login')); + } + + $ok = FreshRSS_FormAuth::checkCredentials( + $username, $conf->passwordHash, $nonce, $challenge + ); + if ($ok) { + // Set session parameter to give access to the user. + Minz_Session::_param('currentUser', $username); + Minz_Session::_param('passwordHash', $conf->passwordHash); + FreshRSS_Auth::giveAccess(); + + // Set cookie parameter if nedded. + if (Minz_Request::param('keep_logged_in')) { + FreshRSS_FormAuth::makeCookie($username, $conf->passwordHash); + } else { + FreshRSS_FormAuth::deleteCookie(); + } + + // All is good, go back to the index. + Minz_Request::good(_t('login'), + array('c' => 'index', 'a' => 'index')); + } else { + Minz_Log::warning('Password mismatch for' . + ' user=' . $username . + ', nonce=' . $nonce . + ', c=' . $challenge); + Minz_Request::bad(_t('invalid_login'), + array('c' => 'auth', 'a' => 'login')); + } + } + } + + /** + * This action handles Persona login page. + * + * If this action is reached through a POST request, assertion from Persona + * is verificated and user connected if all is ok. + * + * Parameter is: + * - assertion (default: false) + * + * @todo: Persona system should be moved to a plugin + */ + public function personaLoginAction() { + $this->view->res = false; + + if (Minz_Request::isPost()) { + $this->view->_useLayout(false); + + $assert = Minz_Request::param('assertion'); + $url = 'https://verifier.login.persona.org/verify'; + $params = 'assertion=' . $assert . '&audience=' . + urlencode(Minz_Url::display(null, 'php', true)); + $ch = curl_init(); + $options = array( + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => TRUE, + CURLOPT_POST => 2, + CURLOPT_POSTFIELDS => $params + ); + curl_setopt_array($ch, $options); + $result = curl_exec($ch); + curl_close($ch); + + $res = json_decode($result, true); + + $login_ok = false; + $reason = ''; + if ($res['status'] === 'okay') { + $email = filter_var($res['email'], FILTER_VALIDATE_EMAIL); + if ($email != '') { + $persona_file = DATA_PATH . '/persona/' . $email . '.txt'; + if (($current_user = @file_get_contents($persona_file)) !== false) { + $current_user = trim($current_user); + try { + $conf = new FreshRSS_Configuration($current_user); + $login_ok = strcasecmp($email, $conf->mail_login) === 0; + } catch (Minz_Exception $e) { + //Permission denied or conf file does not exist + $reason = 'Invalid configuration for user ' . + '[' . $current_user . '] ' . $e->getMessage(); + } + } + } else { + $reason = 'Invalid email format [' . $res['email'] . ']'; + } + } else { + $reason = $res['reason']; + } + + if ($login_ok) { + Minz_Session::_param('currentUser', $current_user); + Minz_Session::_param('mail', $email); + FreshRSS_Auth::giveAccess(); + invalidateHttpCache(); + } else { + Minz_Log::error($reason); + + $res = array(); + $res['status'] = 'failure'; + $res['reason'] = _t('invalid_login'); + } + + header('Content-Type: application/json; charset=UTF-8'); + $this->view->res = $res; + } + } + + /** + * This action removes all accesses of the current user. + */ + public function logoutAction() { + invalidateHttpCache(); + FreshRSS_Auth::removeAccess(); + Minz_Request::good(_t('disconnected'), + array('c' => 'index', 'a' => 'index')); + } +} diff --git a/app/Controllers/indexController.php b/app/Controllers/indexController.php index 3006480f9..5b490e672 100755 --- a/app/Controllers/indexController.php +++ b/app/Controllers/indexController.php @@ -20,7 +20,7 @@ class FreshRSS_index_Controller extends Minz_ActionController { } elseif ($output !== 'rss') { // "hard" redirection is not required, just ask dispatcher to // forward to the login form without 302 redirection - Minz_Request::forward(array('c' => 'index', 'a' => 'login')); + Minz_Request::forward(array('c' => 'auth', 'a' => 'login')); return; } } @@ -228,92 +228,4 @@ class FreshRSS_index_Controller extends Minz_ActionController { $this->view->logsPaginator->_nbItemsPerPage(50); $this->view->logsPaginator->_currentPage($page); } - - /** - * This action handles the login page. - */ - public function loginAction() { - if (FreshRSS_Auth::hasAccess()) { - Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); - } - - invalidateHttpCache(); - - $auth_type = Minz_Configuration::authType(); - switch ($auth_type) { - case 'form': - Minz_Request::forward(array('c' => 'index', 'a' => 'formLogin')); - break; - case 'http_auth': - case 'none': - // It should not happened! - Minz_Error::error(404); - default: - // TODO load plugin instead - Minz_Error::error(404); - } - } - - /** - * - */ - public function formLoginAction() { - if (FreshRSS_Auth::hasAccess()) { - Minz_Request::forward(array('c' => 'index', 'a' => 'index'), true); - } - - invalidateHttpCache(); - - $file_mtime = @filemtime(PUBLIC_PATH . '/scripts/bcrypt.min.js'); - Minz_View::appendScript(Minz_Url::display('/scripts/bcrypt.min.js?' . $file_mtime)); - - if (Minz_Request::isPost()) { - $nonce = Minz_Session::param('nonce'); - $username = Minz_Request::param('username', ''); - $challenge = Minz_Request::param('challenge', ''); - try { - $conf = new FreshRSS_Configuration($username); - } catch(Minz_Exception $e) { - // $username is not a valid user, nor the configuration file! - Minz_Log::warning('Login failure: ' . $e->getMessage()); - Minz_Request::bad(_t('invalid_login'), - array('c' => 'index', 'a' => 'login')); - } - - $ok = FreshRSS_FormAuth::checkCredentials( - $username, $conf->passwordHash, $nonce, $challenge - ); - if ($ok) { - // Set session parameter to give access to the user. - Minz_Session::_param('currentUser', $username); - Minz_Session::_param('passwordHash', $conf->passwordHash); - FreshRSS_Auth::giveAccess(); - - // Set cookie parameter if nedded. - if (Minz_Request::param('keep_logged_in', false)) { - FreshRSS_FormAuth::makeCookie($username, $conf->passwordHash); - } else { - FreshRSS_FormAuth::deleteCookie(); - } - - // All is good, go back to the index. - Minz_Request::good(_t('login'), - array('c' => 'index', 'a' => 'index')); - } else { - Minz_Log::warning('Password mismatch for' . - ' user=' . $username . - ', nonce=' . $nonce . - ', c=' . $challenge); - Minz_Request::bad(_t('invalid_login'), - array('c' => 'index', 'a' => 'login')); - } - } - } - - public function logoutAction() { - invalidateHttpCache(); - FreshRSS_Auth::removeAccess(); - Minz_Request::good(_t('disconnected'), - array('c' => 'index', 'a' => 'index')); - } } diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 35a37b887..6b7a813bf 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -64,6 +64,14 @@ class FreshRSS extends Minz_FrontController { Minz_View::appendScript(Minz_Url::display('/scripts/jquery.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/jquery.min.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/shortcut.js?' . @filemtime(PUBLIC_PATH . '/scripts/shortcut.js'))); Minz_View::appendScript(Minz_Url::display('/scripts/main.js?' . @filemtime(PUBLIC_PATH . '/scripts/main.js'))); + + if (Minz_Configuration::authType() === 'persona') { + // TODO move it in a plugin + // Needed for login AND logout with Persona. + Minz_View::appendScript('https://login.persona.org/include.js'); + $file_mtime = @filemtime(PUBLIC_PATH . '/scripts/persona.js'); + Minz_View::appendScript(Minz_Url::display('/scripts/persona.js?' . $file_mtime)); + } } private function loadNotifications() { diff --git a/app/Models/Auth.php b/app/Models/Auth.php index 992b444a5..cc23d7974 100644 --- a/app/Models/Auth.php +++ b/app/Models/Auth.php @@ -20,7 +20,7 @@ class FreshRSS_Auth { Minz_Session::_param('currentUser', $current_user); } - $access_ok = self::accessControl($current_user); + $access_ok = self::accessControl(); if ($access_ok) { self::giveAccess(); @@ -36,10 +36,9 @@ class FreshRSS_Auth { * Required session parameters are also set in this method (such as * currentUser). * - * @param string $username username of the user to check access. * @return boolean true if user can be connected, false else. */ - public static function accessControl($username) { + public static function accessControl() { if (self::$login_ok) { return true; } @@ -61,6 +60,16 @@ class FreshRSS_Auth { Minz_Session::_param('currentUser', $current_user); } return $login_ok; + case 'persona': + $email = filter_var(Minz_Session::param('mail'), FILTER_VALIDATE_EMAIL); + $persona_file = DATA_PATH . '/persona/' . $email . '.txt'; + if (($current_user = @file_get_contents($persona_file)) !== false) { + $current_user = trim($current_user); + Minz_Session::_param('currentUser', $current_user); + Minz_Session::_param('mail', $email); + return true; + } + return false; case 'none': return true; default: @@ -87,6 +96,9 @@ class FreshRSS_Auth { case 'http_auth': self::$login_ok = strcasecmp($current_user, httpAuthUser()) === 0; break; + case 'persona': + self::$login_ok = strcasecmp(Minz_Session::param('mail'), $conf->mail_login) === 0; + break; case 'none': self::$login_ok = true; break; @@ -131,6 +143,9 @@ class FreshRSS_Auth { Minz_Session::_param('passwordHash'); FreshRSS_FormAuth::deleteCookie(); break; + case 'persona': + Minz_Session::_param('mail'); + break; case 'http_auth': case 'none': // Nothing to do... diff --git a/app/layout/header.phtml b/app/layout/header.phtml index 12c86d61d..deb21edc9 100644 --- a/app/layout/header.phtml +++ b/app/layout/header.phtml @@ -2,9 +2,9 @@ if (Minz_Configuration::canLogIn()) { ?>
  • -
  • -
    + +
    + +
    + diff --git a/app/views/auth/formLogin.phtml b/app/views/auth/formLogin.phtml new file mode 100644 index 000000000..0194a11a5 --- /dev/null +++ b/app/views/auth/formLogin.phtml @@ -0,0 +1,28 @@ +
    +

    + +
    +
    + + +
    +
    + + +
    + +
    +
    + +
    +
    +
    + +
    +
    + +

    +
    diff --git a/app/views/auth/logout.phtml b/app/views/auth/logout.phtml new file mode 100644 index 000000000..e69de29bb diff --git a/app/views/auth/personaLogin.phtml b/app/views/auth/personaLogin.phtml new file mode 100644 index 000000000..d62fe5818 --- /dev/null +++ b/app/views/auth/personaLogin.phtml @@ -0,0 +1,24 @@ +res === false) { ?> +
    +

    + +

    + + +

    + + + + + +

    + +

    +
    +res); +} +?> diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 8f615ed87..3bbcc3848 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -8,6 +8,15 @@ $hide_posts = ($this->conf->display_posts || Minz_Request::param('output') === 'reader'); $s = $this->conf->shortcuts; +$url_login = Minz_Url::display(array( + 'c' => 'auth', + 'a' => 'login' +), 'php'); +$url_logout = Minz_Url::display(array( + 'c' => 'auth', + 'a' => 'logout' +), 'php'); + echo 'var context={', 'hide_posts:', $hide_posts ? 'false' : 'true', ',', 'display_order:"', Minz_Request::param('order', $this->conf->sort_order), '",', @@ -43,8 +52,8 @@ echo 'shortcuts={', echo 'url={', 'index:"', _url('index', 'index'), '",', - 'login:"', _url('index', 'login'), '",', - 'logout:"', _url('index', 'logout'), '",', + 'login:"', $url_login, '",', + 'logout:"', $url_logout, '",', 'help:"', FRESHRSS_WIKI, '"', "},\n"; diff --git a/app/views/index/formLogin.phtml b/app/views/index/formLogin.phtml deleted file mode 100644 index b05cdced4..000000000 --- a/app/views/index/formLogin.phtml +++ /dev/null @@ -1,46 +0,0 @@ -
    -

    -
    - - -
    -
    - - -
    - -
    -
    - -
    -
    -
    - -
    -

    -

    - - - - - -

    - -

    -
    diff --git a/p/scripts/main.js b/p/scripts/main.js index b01a3a34d..77e1e3f77 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1034,67 +1034,7 @@ function init_crypto_form() { } // -// -function init_persona() { - if (!(navigator.id)) { - if (window.console) { - console.log('FreshRSS waiting for Persona…'); - } - window.setTimeout(init_persona, 100); - return; - } - $('a.signin').click(function() { - navigator.id.request(); - return false; - }); - - $('a.signout').click(function() { - navigator.id.logout(); - return false; - }); - navigator.id.watch({ - loggedInUser: context['current_user_mail'], - - onlogin: function(assertion) { - // A user has logged in! Here you need to: - // 1. Send the assertion to your backend for verification and to create a session. - // 2. Update your UI. - $.ajax ({ - type: 'POST', - url: url['login'], - data: {assertion: assertion}, - success: function(res, status, xhr) { - /*if (res.status === 'failure') { - alert (res_obj.reason); - } else*/ if (res.status === 'okay') { - location.href = url['index']; - } - }, - error: function(res, status, xhr) { - alert("Login failure: " + res); - } - }); - }, - onlogout: function() { - // A user has logged out! Here you need to: - // Tear down the user's session by redirecting the user or making a call to your backend. - // Also, make sure loggedInUser will get set to null on the next page load. - // (That's a literal JavaScript null. Not false, 0, or undefined. null.) - $.ajax ({ - type: 'POST', - url: url['logout'], - success: function(res, status, xhr) { - location.href = url['index']; - }, - error: function(res, status, xhr) { - //alert("logout failure" + res); - } - }); - } - }); -} -// function init_confirm_action() { $('body').on('click', '.confirm', function () { @@ -1274,11 +1214,6 @@ function init_all() { return; } init_notifications(); - switch (context['auth_type']) { - case 'persona': - init_persona(); - break; - } init_confirm_action(); $stream = $('#stream'); if ($stream.length > 0) { diff --git a/p/scripts/persona.js b/p/scripts/persona.js new file mode 100644 index 000000000..36aeeaf56 --- /dev/null +++ b/p/scripts/persona.js @@ -0,0 +1,76 @@ +"use strict"; + +function init_persona() { + if (!(navigator.id && window.$)) { + if (window.console) { + console.log('FreshRSS (Persona) waiting for JS…'); + } + window.setTimeout(init_persona, 100); + return; + } + + $('a.signin').click(function() { + navigator.id.request(); + return false; + }); + + $('a.signout').click(function() { + navigator.id.logout(); + return false; + }); + + navigator.id.watch({ + loggedInUser: context['current_user_mail'], + + onlogin: function(assertion) { + // A user has logged in! Here you need to: + // 1. Send the assertion to your backend for verification and to create a session. + // 2. Update your UI. + $.ajax ({ + type: 'POST', + url: url['login'], + data: {assertion: assertion}, + success: function(res, status, xhr) { + if (res.status === 'failure') { + openNotification(res.reason, 'bad'); + } else if (res.status === 'okay') { + location.href = url['index']; + } + }, + error: function(res, status, xhr) { + // alert(res); + } + }); + }, + onlogout: function() { + // A user has logged out! Here you need to: + // Tear down the user's session by redirecting the user or making a call to your backend. + // Also, make sure loggedInUser will get set to null on the next page load. + // (That's a literal JavaScript null. Not false, 0, or undefined. null.) + $.ajax ({ + type: 'POST', + url: url['logout'], + success: function(res, status, xhr) { + location.href = url['index']; + }, + error: function(res, status, xhr) { + // alert(res); + } + }); + } + }); +} + +if (document.readyState && document.readyState !== 'loading') { + if (window.console) { + console.log('FreshRSS (Persona) immediate init…'); + } + init_persona(); +} else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', function () { + if (window.console) { + console.log('FreshRSS (Persona) waiting for DOMContentLoaded…'); + } + init_persona(); + }, false); +} -- cgit v1.2.3 From 2796cc9ae559842a90fa15cba65c94a11b29195e Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 16 Oct 2014 16:43:37 +0200 Subject: User list load a new page Beginning of more options for administrator! --- app/Controllers/userController.php | 4 ++++ app/views/stats/repartition.phtml | 2 +- app/views/user/manage.phtml | 41 +++++++++++++++++++------------------- p/scripts/main.js | 2 +- 4 files changed, 26 insertions(+), 23 deletions(-) (limited to 'p/scripts/main.js') diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php index c516246c9..00b51cc3d 100644 --- a/app/Controllers/userController.php +++ b/app/Controllers/userController.php @@ -88,6 +88,10 @@ class FreshRSS_user_Controller extends Minz_ActionController { */ public function manageAction() { Minz_View::prependTitle(_t('users.manage') . ' · '); + + $this->view->current_user = Minz_Request::param( + 'u', Minz_Session::param('currentUser', '_') + ); } public function createAction() { diff --git a/app/views/stats/repartition.phtml b/app/views/stats/repartition.phtml index 670714707..32268a546 100644 --- a/app/views/stats/repartition.phtml +++ b/app/views/stats/repartition.phtml @@ -5,7 +5,7 @@

    - categories as $category) { $feeds = $category->feeds(); diff --git a/app/views/user/manage.phtml b/app/views/user/manage.phtml index 03746cabb..fb569872b 100644 --- a/app/views/user/manage.phtml +++ b/app/views/user/manage.phtml @@ -3,27 +3,6 @@
    -
    - - -
    - -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    @@ -71,6 +50,26 @@
    + + +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    diff --git a/p/scripts/main.js b/p/scripts/main.js index 77e1e3f77..1e13ff16a 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -1086,7 +1086,7 @@ function init_share_observers() { } function init_stats_observers() { - $('#feed_select').on('change', function(e) { + $('.select-change').on('change', function(e) { redirect($(this).find(':selected').data('url')); }); } -- cgit v1.2.3 From 8769931a68d0dddb134674c86a43dec75b39bf83 Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Thu, 23 Oct 2014 09:32:02 +0200 Subject: Rename aside_flux in aside_feed. --- app/layout/aside_feed.phtml | 95 ++++++++++++++++++++++++++++++++++++++++ app/layout/aside_flux.phtml | 95 ---------------------------------------- app/layout/nav_menu.phtml | 2 +- app/views/index/normal.phtml | 2 +- p/scripts/main.js | 26 +++++------ p/themes/Origine/origine.css | 8 ++-- p/themes/base-theme/base.css | 8 ++-- p/themes/base-theme/template.css | 22 +++++----- 8 files changed, 129 insertions(+), 129 deletions(-) create mode 100644 app/layout/aside_feed.phtml delete mode 100644 app/layout/aside_flux.phtml (limited to 'p/scripts/main.js') diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml new file mode 100644 index 000000000..66b7b51af --- /dev/null +++ b/app/layout/aside_feed.phtml @@ -0,0 +1,95 @@ +hide_read_feeds && + FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_READ) && + !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ)) { + $class = ' state_unread'; + } +?> + +
    + + + +
    + + +
    + + + + + + +
      +
    • +
      + +
      +
    • + +
    • +
      + +
      +
    • + + categories as $cat) { + $feeds = $cat->feeds(); + if (!empty($feeds)) { + $c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id()); + $c_show = $c_active && (!FreshRSS_Context::$conf->display_categories || + FreshRSS_Context::$current_get['feed']); + ?> +
    • + + + +
    • + +
    +
    + + diff --git a/app/layout/aside_flux.phtml b/app/layout/aside_flux.phtml deleted file mode 100644 index 30f362348..000000000 --- a/app/layout/aside_flux.phtml +++ /dev/null @@ -1,95 +0,0 @@ -hide_read_feeds && - FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_READ) && - !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ)) { - $class = ' state_unread'; - } -?> - -
    - - - -
    - - -
    - - - - - - -
      -
    • -
      - -
      -
    • - -
    • -
      - -
      -
    • - - categories as $cat) { - $feeds = $cat->feeds(); - if (!empty($feeds)) { - $c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id()); - $c_show = $c_active && (!FreshRSS_Context::$conf->display_categories || - FreshRSS_Context::$current_get['feed']); - ?> -
    • - - - -
    • - -
    -
    - - diff --git a/app/layout/nav_menu.phtml b/app/layout/nav_menu.phtml index 2c9f8724d..6f555c3d0 100644 --- a/app/layout/nav_menu.phtml +++ b/app/layout/nav_menu.phtml @@ -2,7 +2,7 @@ +
    +
    + +
    +
    +
    diff --git a/app/views/helpers/javascript_vars.phtml b/app/views/helpers/javascript_vars.phtml index 8e9141d4e..6424d8d04 100644 --- a/app/views/helpers/javascript_vars.phtml +++ b/app/views/helpers/javascript_vars.phtml @@ -18,6 +18,7 @@ $url_logout = Minz_Url::display(array( ), 'php'); echo 'var context={', + 'auto_remove_article:', FreshRSS_Context::isAutoRemoveAvailable() ? 'true' : 'false', ',', 'hide_posts:', $hide_posts ? 'false' : 'true', ',', 'display_order:"', Minz_Request::param('order', FreshRSS_Context::$conf->sort_order), '",', 'auto_mark_article:', $mark['article'] ? 'true' : 'false', ',', diff --git a/p/scripts/main.js b/p/scripts/main.js index dc5428048..d1d31c801 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -231,6 +231,14 @@ function toggleContent(new_active, old_active) { } old_active.removeClass("active current"); new_active.addClass("current"); + if (context['auto_remove_article'] && !old_active.hasClass('not_read')) { + var p = old_active.prev(); + var n = old_active.next(); + if (p.hasClass('day') && n.hasClass('day')) { + p.remove(); + } + old_active.remove(); + } } else { new_active.toggleClass('active'); } -- cgit v1.2.3 From adaec6176ca04ee38306bd348eba9a8350f19405 Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Tue, 2 Dec 2014 23:34:31 -0500 Subject: Add article auto-remove after clicking on the read link --- p/scripts/main.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index d1d31c801..19eba206d 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -690,6 +690,9 @@ function init_stream(divStream) { divStream.on('click', '.flux a.read', function () { var active = $(this).parents(".flux"); mark_read(active, false); + if (context['auto_remove_article']) { + active.remove(); + } return false; }); -- cgit v1.2.3 From 93af0cf61e6e9368888eedb2d2e36397da3f87bd Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Wed, 3 Dec 2014 18:13:59 -0500 Subject: Fix behavior when marking an article as unread --- p/scripts/main.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index 19eba206d..32cf55a3c 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -144,6 +144,7 @@ function mark_read(active, only_not_read) { inc = 0; if (active.hasClass("not_read")) { active.removeClass("not_read"); + hide_article(active); inc--; } else if (only_not_read !== true || active.hasClass("not_read")) { active.addClass("not_read"); @@ -231,14 +232,7 @@ function toggleContent(new_active, old_active) { } old_active.removeClass("active current"); new_active.addClass("current"); - if (context['auto_remove_article'] && !old_active.hasClass('not_read')) { - var p = old_active.prev(); - var n = old_active.next(); - if (p.hasClass('day') && n.hasClass('day')) { - p.remove(); - } - old_active.remove(); - } + hide_article(old_active); } else { new_active.toggleClass('active'); } @@ -283,6 +277,17 @@ function toggleContent(new_active, old_active) { } } +function hide_article(article) { + if (context['auto_remove_article'] && !article.hasClass('not_read')) { + var p = article.prev(); + var n = article.next(); + if (p.hasClass('day') && n.hasClass('day')) { + p.remove(); + } + article.remove(); + } +} + function prev_entry() { var old_active = $(".flux.current"), new_active = old_active.length === 0 ? $(".flux:last") : old_active.prevAll(".flux:first"); @@ -690,9 +695,6 @@ function init_stream(divStream) { divStream.on('click', '.flux a.read', function () { var active = $(this).parents(".flux"); mark_read(active, false); - if (context['auto_remove_article']) { - active.remove(); - } return false; }); -- cgit v1.2.3 From 5617911644bf85718430bb096c4ae9a0a0e8c75c Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Wed, 3 Dec 2014 18:35:42 -0500 Subject: Revert "Fix behavior when marking an article as unread" This reverts commit 93af0cf61e6e9368888eedb2d2e36397da3f87bd. --- p/scripts/main.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index 32cf55a3c..19eba206d 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -144,7 +144,6 @@ function mark_read(active, only_not_read) { inc = 0; if (active.hasClass("not_read")) { active.removeClass("not_read"); - hide_article(active); inc--; } else if (only_not_read !== true || active.hasClass("not_read")) { active.addClass("not_read"); @@ -232,7 +231,14 @@ function toggleContent(new_active, old_active) { } old_active.removeClass("active current"); new_active.addClass("current"); - hide_article(old_active); + if (context['auto_remove_article'] && !old_active.hasClass('not_read')) { + var p = old_active.prev(); + var n = old_active.next(); + if (p.hasClass('day') && n.hasClass('day')) { + p.remove(); + } + old_active.remove(); + } } else { new_active.toggleClass('active'); } @@ -277,17 +283,6 @@ function toggleContent(new_active, old_active) { } } -function hide_article(article) { - if (context['auto_remove_article'] && !article.hasClass('not_read')) { - var p = article.prev(); - var n = article.next(); - if (p.hasClass('day') && n.hasClass('day')) { - p.remove(); - } - article.remove(); - } -} - function prev_entry() { var old_active = $(".flux.current"), new_active = old_active.length === 0 ? $(".flux:last") : old_active.prevAll(".flux:first"); @@ -695,6 +690,9 @@ function init_stream(divStream) { divStream.on('click', '.flux a.read', function () { var active = $(this).parents(".flux"); mark_read(active, false); + if (context['auto_remove_article']) { + active.remove(); + } return false; }); -- cgit v1.2.3 From 53410887c94157f3d11f2c30d92ff5d3d8a3a9bd Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Wed, 3 Dec 2014 18:57:53 -0500 Subject: Fix behavior to hide articles I do not like it since it is partly duplicated. We need to find something better. --- p/scripts/main.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'p/scripts/main.js') diff --git a/p/scripts/main.js b/p/scripts/main.js index 19eba206d..e48630d89 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -689,10 +689,15 @@ function init_stream(divStream) { divStream.on('click', '.flux a.read', function () { var active = $(this).parents(".flux"); - mark_read(active, false); - if (context['auto_remove_article']) { + if (context['auto_remove_article'] && active.hasClass('not_read')) { + var p = active.prev(); + var n = active.next(); + if (p.hasClass('day') && n.hasClass('day')) { + p.remove(); + } active.remove(); } + mark_read(active, false); return false; }); -- cgit v1.2.3 From 0140448a562b97859be0b9a6e480e1f6aa4d1b1d Mon Sep 17 00:00:00 2001 From: Marien Fressinaud Date: Wed, 7 Jan 2015 14:59:18 +0100 Subject: Refactor FreshRSS_Share object to be more usable - FreshRSS_Share is the only object we manipulate - Add a way to register new share options easily - Move some i18n keys from index.php to gen.php See https://github.com/FreshRSS/FreshRSS/issues/730 --- app/FreshRSS.php | 3 + app/Models/Share.php | 232 +++++++++++++++++++++++++++++++++++--- app/i18n/en/gen.php | 11 ++ app/i18n/en/index.php | 13 +-- app/i18n/fr/conf.php | 2 +- app/i18n/fr/gen.php | 11 ++ app/i18n/fr/index.php | 13 +-- app/views/configure/sharing.phtml | 27 +++-- app/views/index/normal.phtml | 28 +++-- p/scripts/main.js | 2 +- 10 files changed, 272 insertions(+), 70 deletions(-) (limited to 'p/scripts/main.js') diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 06976c88b..254e35fee 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -32,6 +32,9 @@ class FreshRSS extends Minz_FrontController { FreshRSS_Context::init(); $this->initI18n(); + + FreshRSS_Share::load(join_path(DATA_PATH, 'shares.php')); + $this->loadStylesAndScripts(); $this->loadNotifications(); $this->loadExtensions(); diff --git a/app/Models/Share.php b/app/Models/Share.php index b146db722..db6feda19 100644 --- a/app/Models/Share.php +++ b/app/Models/Share.php @@ -1,44 +1,240 @@ $share_options) { + $share_options['type'] = $share_type; + self::register($share_options); + } + } + + /** + * Return the list of sharing options. + * @return an array of FreshRSS_Share objects. + */ + public static function enum() { + return self::$list_sharing; + } + + /** + * Return FreshRSS_Share object related to the given type. + * @param $type the share type, null if $type is not registered. + */ + public static function get($type) { + if (!isset(self::$list_sharing[$type])) { + return null; + } + + return self::$list_sharing[$type]; + } + + /** + * + */ + private $type = ''; + private $name = ''; + private $url_transform = ''; + private $transform = array(); + private $form_type = 'simple'; + private $help_url = ''; + private $custom_name = null; + private $base_url = null; + private $title = null; + private $link = null; + + /** + * Create a FreshRSS_Share object. + * @param $type is a unique string defining the kind of share option. + * @param $url_transform defines the url format to use in order to share. + * @param $transform is an array of transformations to apply on link and title. + * @param $form_type defines which form we have to use to complete. "simple" + * is typically for a centralized service while "advanced" is for + * decentralized ones. + * @param $help_url is an optional url to give help on this option. + */ + private function __construct($type, $url_transform, $transform = array(), + $form_type, $help_url = '') { + $this->type = $type; + $this->name = _t('gen.share.' . $type); + $this->url_transform = $url_transform; + $this->help_url = $help_url; + + if (!is_array($transform)) { + $transform = array(); + } + $this->transform = $transform; + + if (!in_array($form_type, array('simple', 'advanced'))) { + $form_type = 'simple'; + } + $this->form_type = $form_type; + } + + /** + * Update a FreshRSS_Share object with information from an array. + * @param $options is a list of informations to update where keys should be + * in this list: name, url, title, link. + */ + public function update($options) { + $available_options = array( + 'name' => 'custom_name', + 'url' => 'base_url', + 'title' => 'title', + 'link' => 'link', + ); + + foreach ($options as $key => $value) { + if (!isset($available_options[$key])) { + continue; + } + + $this->$available_options[$key] = $value; + } + } + + /** + * Return the current type of the share option. + */ + public function type() { + return $this->type; + } + + /** + * Return the current form type of the share option. + */ + public function formType() { + return $this->form_type; + } + + /** + * Return the current help url of the share option. + */ + public function help() { + return $this->help_url; + } + + /** + * Return the current name of the share option. + */ + public function name($real = false) { + if ($real || is_null($this->custom_name)) { + return $this->name; + } else { + return $this->custom_name; + } + } + + /** + * Return the current base url of the share option. + */ + public function baseUrl() { + return $this->base_url; + } + + /** + * Return the current url by merging url_transform and base_url. + */ + public function url() { $matches = array( '~URL~', '~TITLE~', '~LINK~', ); $replaces = array( - $selected['url'], - self::transformData($title, self::getTransform($share, 'title')), - self::transformData($link, self::getTransform($share, 'link')), + $this->base_url, + $this->title(), + $this->link(), ); - $url = str_replace($matches, $replaces, $share['url']); - return $url; + return str_replace($matches, $replaces, $this->url_transform); } - static private function transformData($data, $transform) { - if (!is_array($transform)) { - return $data; + /** + * Return the title. + * @param $raw true if we should get the title without transformations. + */ + public function title($raw = false) { + if ($raw) { + return $this->title; } - if (count($transform) === 0) { + + return $this->transform($this->title, $this->getTransform('title')); + } + + /** + * Return the link. + * @param $raw true if we should get the link without transformations. + */ + public function link($raw = false) { + if ($raw) { + return $this->link; + } + + return $this->transform($this->link, $this->getTransform('link')); + } + + /** + * Transform a data with the given functions. + * @param $data the data to transform. + * @param $tranform an array containing a list of functions to apply. + * @return the transformed data. + */ + private static function transform($data, $transform) { + if (!is_array($transform) || empty($transform)) { return $data; } + foreach ($transform as $action) { $data = call_user_func($action, $data); } + return $data; } - static private function getTransform($options, $type) { - $transform = $options['transform']; - - if (array_key_exists($type, $transform)) { - return $transform[$type]; + /** + * Get the list of transformations for the given attribute. + * @param $attr the attribute of which we want the transformations. + * @return an array containing a list of transformations to apply. + */ + private function getTransform($attr) { + if (array_key_exists($attr, $this->transform)) { + return $this->transform[$attr]; } - return $transform; + return $this->transform; } - } diff --git a/app/i18n/en/gen.php b/app/i18n/en/gen.php index 43f94f1bc..4a6f8a71b 100644 --- a/app/i18n/en/gen.php +++ b/app/i18n/en/gen.php @@ -128,6 +128,17 @@ return array( 'nothing_to_load' => 'There are no more articles', 'previous' => 'Previous', ), + 'share' => array( + 'blogotext' => 'Blogotext', + 'diaspora' => 'Diaspora*', + 'email' => 'Email', + 'facebook' => 'Facebook', + 'g+' => 'Google+', + 'print' => 'Print', + 'shaarli' => 'Shaarli', + 'twitter' => 'Twitter', + 'wallabag' => 'wallabag', + ), 'short' => array( 'attention' => 'Attention!', 'blank_to_disable' => 'Leave blank to disable', diff --git a/app/i18n/en/index.php b/app/i18n/en/index.php index 941388b68..8e7d81db8 100644 --- a/app/i18n/en/index.php +++ b/app/i18n/en/index.php @@ -55,18 +55,7 @@ return array( 'subscription' => 'Subscriptions management', 'unread' => 'Show only unread', ), - 'share' => array( - '_' => 'Share', - 'blogotext' => 'Blogotext', - 'diaspora' => 'Diaspora*', - 'email' => 'Email', - 'facebook' => 'Facebook', - 'g+' => 'Google+', - 'print' => 'Print', - 'shaarli' => 'Shaarli', - 'twitter' => 'Twitter', - 'wallabag' => 'wallabag', - ), + 'share' => 'Share', 'tag' => array( 'related' => 'Related tags', ), diff --git a/app/i18n/fr/conf.php b/app/i18n/fr/conf.php index 62d6342e9..e91aeb66a 100644 --- a/app/i18n/fr/conf.php +++ b/app/i18n/fr/conf.php @@ -121,7 +121,7 @@ return array( '_' => 'Partage', 'blogotext' => 'Blogotext', 'diaspora' => 'Diaspora*', - 'email' => 'Email', + 'email' => 'Courriel', 'facebook' => 'Facebook', 'g+' => 'Google+', 'more_information' => 'Plus d’informations', diff --git a/app/i18n/fr/gen.php b/app/i18n/fr/gen.php index bb4478360..d990dad4a 100644 --- a/app/i18n/fr/gen.php +++ b/app/i18n/fr/gen.php @@ -128,6 +128,17 @@ return array( 'nothing_to_load' => 'Fin des articles', 'previous' => 'Précédent', ), + 'share' => array( + 'blogotext' => 'Blogotext', + 'diaspora' => 'Diaspora*', + 'email' => 'Courriel', + 'facebook' => 'Facebook', + 'g+' => 'Google+', + 'print' => 'Imprimer', + 'shaarli' => 'Shaarli', + 'twitter' => 'Twitter', + 'wallabag' => 'wallabag', + ), 'short' => array( 'attention' => 'Attention !', 'blank_to_disable' => 'Laissez vide pour désactiver', diff --git a/app/i18n/fr/index.php b/app/i18n/fr/index.php index 3279543bd..f9975c593 100644 --- a/app/i18n/fr/index.php +++ b/app/i18n/fr/index.php @@ -55,18 +55,7 @@ return array( 'subscription' => 'Gestion des abonnements', 'unread' => 'Afficher les non lus', ), - 'share' => array( - '_' => 'Partager', - 'blogotext' => 'Blogotext', - 'diaspora' => 'Diaspora*', - 'email' => 'Courriel', - 'facebook' => 'Facebook', - 'g+' => 'Google+', - 'print' => 'Imprimer', - 'shaarli' => 'Shaarli', - 'twitter' => 'Twitter', - 'wallabag' => 'wallabag', - ), + 'share' => 'Partager', 'tag' => array( 'related' => 'Tags associés', ), diff --git a/app/views/configure/sharing.phtml b/app/views/configure/sharing.phtml index f5c133f07..da7557480 100644 --- a/app/views/configure/sharing.phtml +++ b/app/views/configure/sharing.phtml @@ -15,22 +15,25 @@
    '> - sharing as $key => $sharing) { ?> - shares[$sharing['type']]; ?> -
    + sharing as $key => $share_options) { + $share = FreshRSS_Share::get($share_options['type']); + $share->update($share_options); + ?> +
    - ' /> - + + formType() === 'advanced') { ?>
    - - + +
    - + @@ -41,8 +44,10 @@
    diff --git a/app/views/index/normal.phtml b/app/views/index/normal.phtml index c2cf7c887..8c6ddd1ee 100644 --- a/app/views/index/normal.phtml +++ b/app/views/index/normal.phtml @@ -129,8 +129,6 @@ if (!empty($this->entries)) { } ?>
  • link()); - $title = urlencode($item->title() . ' · ' . $feed->name()); ?>
  • link(); + $title = $item->title() . ' · ' . $feed->name(); + foreach (FreshRSS_Context::$user_conf->sharing as $share_options) { + $share = FreshRSS_Share::get($share_options['type']); + $share_options['link'] = $link; + $share_options['title'] = $title; + $share->update($share_options); + ?>
    Date: Tue, 13 Jan 2015 11:16:13 +0100 Subject: Fix user interaction with showing password feature Before, the password was hidden again after 2 seconds. Now, the password is hidden when the mouse is released Fix https://github.com/FreshRSS/FreshRSS/issues/734 --- app/install.php | 17 ++++++++++------- app/views/user/manage.phtml | 2 +- app/views/user/profile.phtml | 4 ++-- p/scripts/main.js | 15 ++++++++------- 4 files changed, 21 insertions(+), 17 deletions(-) (limited to 'p/scripts/main.js') diff --git a/app/install.php b/app/install.php index a79b0d318..eb2f764f9 100644 --- a/app/install.php +++ b/app/install.php @@ -611,23 +611,26 @@ function printStep2() {