Преглед на файлове

Added ability to mark articles as read on focus. (#5812)

* Added ability to mark entries as read on focus.

Feature proposed in issue #5723.

* make-fix-all + i18n fr

* Use batch to save resources and increase performance

* Use "keep_unread"

* typo

---------

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Ben Passmore преди 2 години
родител
ревизия
b9939bdaac

+ 2 - 1
CHANGELOG.md

@@ -4,7 +4,8 @@
 
 * Features
 	* New *Important feeds* group in the main view, with corresponding new priority level for feeds [#5782](https://github.com/FreshRSS/FreshRSS/pull/5782)
-		* Entries from important feeds are not marked as read during scroll, nor during *Mark all as read*
+		* Entries from important feeds are not marked as read during *scroll*, during *focus*, nor during *Mark all as read*
+	* New option to mark entries as read when focused from keyboard shortcut [5812](https://github.com/FreshRSS/FreshRSS/pull/5812)
 	* Add support for more thumbnail types [#5806](https://github.com/FreshRSS/FreshRSS/pull/5806)
 	* Increase SQL (`VARCHAR`) text fields length to maximum possible [#5788](https://github.com/FreshRSS/FreshRSS/pull/5788)
 	* Increase SQL date fields to 64-bit to be ready for year 2038+ [#5570](https://github.com/FreshRSS/FreshRSS/pull/5570)

+ 2 - 0
app/Controllers/configureController.php

@@ -103,6 +103,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
 	 *       - opened on site
 	 *       - scrolled
 	 *       - received
+	 *       - focus
 	 * Default values are false unless specified.
 	 */
 	public function readingAction(): void {
@@ -136,6 +137,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
 					Minz_Request::paramBoolean('enable_read_when_same_title_in_feed') && Minz_Request::paramBoolean('read_when_same_title_in_feed'),
 				'scroll' => Minz_Request::paramBoolean('mark_scroll'),
 				'site' => Minz_Request::paramBoolean('mark_open_site'),
+				'focus' => Minz_Request::paramBoolean('mark_focus'),
 			];
 			FreshRSS_Context::$user_conf->save();
 			invalidateHttpCache();

+ 1 - 0
app/i18n/cz/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'když je článek otevřen na své původní webové stránce',
 			'article_viewed' => 'když je článek zobrazen',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Maximální počet článků, které ponechat jako nepřečtené',
 			'scroll' => 'během posouvání (except for important feeds)',	// DIRTY
 			'upon_gone' => 'když se již nenachází v upstreamu zpráv.',

+ 1 - 0
app/i18n/de/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'wenn der Artikel auf der Original-Webseite geöffnet wird',
 			'article_viewed' => 'wenn der Artikel angesehen wird',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Max. Anzahl von ungelesenen Artikeln',
 			'scroll' => 'beim Scrollen bzw. Überspringen (except for important feeds)',	// DIRTY
 			'upon_gone' => 'wenn der Artikel nicht mehr im Feed enthalten ist',

+ 1 - 0
app/i18n/el/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'when the article is opened on its original website',	// TODO
 			'article_viewed' => 'when the article is viewed',	// TODO
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO
 			'scroll' => 'while scrolling (except for important feeds)',	// TODO
 			'upon_gone' => 'when it is no longer in the upstream news feed',	// TODO

+ 1 - 0
app/i18n/en-us/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'when the article is opened on its original website',	// IGNORE
 			'article_viewed' => 'when the article is viewed',	// IGNORE
+			'focus' => 'when focused (except for important feeds)',	// IGNORE
 			'keep_max_n_unread' => 'Max number of articles to keep unread',	// IGNORE
 			'scroll' => 'while scrolling (except for important feeds)',	// IGNORE
 			'upon_gone' => 'when it is no longer in the upstream news feed',	// IGNORE

+ 1 - 0
app/i18n/en/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'when the article is opened on its original website',
 			'article_viewed' => 'when the article is viewed',
+			'focus' => 'when focused (except for important feeds)',
 			'keep_max_n_unread' => 'Max number of articles to keep unread',
 			'scroll' => 'while scrolling (except for important feeds)',
 			'upon_gone' => 'when it is no longer in the upstream news feed',

+ 1 - 0
app/i18n/es/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'cuando el artículo se abra en su web original',
 			'article_viewed' => 'cuando se muestre el artículo',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Número máximo de artículos para mantener sin leer',
 			'scroll' => 'durante el desplazamiento (except for important feeds)',	// DIRTY
 			'upon_gone' => 'cuando ya no está disponible en el feed de noticias previo',

+ 1 - 0
app/i18n/fa/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => ' هنگامی که مقاله در وب سایت اصلی خود باز می شود',
 			'article_viewed' => ' هنگام مشاهده مقاله',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => ' حداکثر تعداد مقالات خوانده نشده',
 			'scroll' => '(except for important feeds) در حین پیمایش',	// DIRTY
 			'upon_gone' => ' زمانی که دیگر در فید اخبار بالادستی نیست',

+ 1 - 0
app/i18n/fr/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'lorsque l’article est ouvert sur le site d’origine',
 			'article_viewed' => 'lorsque l’article est affiché',
+			'focus' => 'lorsque l’article est selectionné (sauf pour les flux importants)',
 			'keep_max_n_unread' => 'Nombre maximum d’articles conservés non lus',
 			'scroll' => 'au défilement de la page (sauf pour les flux importants)',
 			'upon_gone' => 'lorsqu’il n’est plus dans le flux d’actualités en amont',

+ 1 - 0
app/i18n/he/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'כאשר מאמר נפתח באתר המקורי',
 			'article_viewed' => 'כאשר מאמר נצפה',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO
 			'scroll' => '(except for important feeds) כאשר גוללים',	// DIRTY
 			'upon_gone' => 'when it is no longer in the upstream news feed',	// TODO

+ 1 - 0
app/i18n/hu/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'ha a cikk megnyitásra került az eredeti weblapon',
 			'article_viewed' => 'ha a cikk megtekintésre került',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Cikkek maximális száma olvasatlanként tartva',
 			'scroll' => 'görgetés közben (except for important feeds)',	// DIRTY
 			'upon_gone' => 'ha már nincs benne a hírforrásban',

+ 1 - 0
app/i18n/id/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'when the article is opened on its original website',	// TODO
 			'article_viewed' => 'when the article is viewed',	// TODO
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Max number of articles to keep unread',	// TODO
 			'scroll' => 'while scrolling (except for important feeds)',	// TODO
 			'upon_gone' => 'when it is no longer in the upstream news feed',	// TODO

+ 1 - 0
app/i18n/it/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'Quando un articolo è aperto nel suo sito di origine',
 			'article_viewed' => 'Quando un articolo viene letto',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Massimo numero di articoli da mantenere come non letti',
 			'scroll' => 'Scorrendo la pagina (except for important feeds)',	// DIRTY
 			'upon_gone' => 'quando non si trova più nel feed di notizie in alto',

+ 1 - 0
app/i18n/ja/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => '記事を元のwebサイトで開いたとき',
 			'article_viewed' => '記事を読んだとき',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => '未読の記事として残す最大数',
 			'scroll' => 'スクロールしているとき (except for important feeds)',	// DIRTY
 			'upon_gone' => 'ニュースフィードの提供元がなくなったとき',

+ 1 - 0
app/i18n/ko/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => '글이 게재된 웹사이트를 방문했을 때',
 			'article_viewed' => '글을 읽었을 때',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => '읽지 않은 상태로 유지할 최대 글 개수',
 			'scroll' => '스크롤을 하며 지나갈 때 (except for important feeds)',	// DIRTY
 			'upon_gone' => '원본 뉴스 피드에서 글 삭제 되었을 때',

+ 1 - 0
app/i18n/lv/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'kad raksts tiek atvērts tā sākotnējā mājaslapā',
 			'article_viewed' => 'kad raksts tiek skatīts',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Maksimālais nelasīto rakstu skaits',
 			'scroll' => 'ritināšanas laikā (except for important feeds)',	// DIRTY
 			'upon_gone' => 'kad tas vairs nav augšupējā ziņu barotnē',

+ 1 - 0
app/i18n/nl/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'als het artikel wordt geopend op de originele website',
 			'article_viewed' => 'als het artikel wordt bekeken',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Max aantal artikelen ongelezen houden',
 			'scroll' => 'tijdens het scrollen (except for important feeds)',	// DIRTY
 			'upon_gone' => 'als het niet langer in de nieuwsfeed staat',

+ 1 - 0
app/i18n/oc/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'quand l’article es dobèrt sul site d’origina',
 			'article_viewed' => 'quand l’article es mostrat',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Nombre max d’articles a gardar pas legits',
 			'scroll' => 'en davalant la pagina (except for important feeds)',	// DIRTY
 			'upon_gone' => 'quand es pas mai dins lo flux de novèla font',

+ 1 - 0
app/i18n/pl/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'gdy wiadomość jest otworzona na pierwotnej stronie',
 			'article_viewed' => 'gdy wiadomość jest otworzona',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Maksymalna liczba nieprzeczytanych wiadomości',
 			'scroll' => 'podczas przewijania (except for important feeds)',	// DIRTY
 			'upon_gone' => 'gdy nie jest już listowana w źródle kanału',

+ 1 - 0
app/i18n/pt-br/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'quando o artigo é aberto no site original',
 			'article_viewed' => 'Quando o artigo é visualizado',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Número máximo de artigos para manter como não lido',
 			'scroll' => 'enquanto scrolling (except for important feeds)',	// DIRTY
 			'upon_gone' => 'QUuando não estiver mais no feed de noticiais principais',

+ 1 - 0
app/i18n/ru/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'когда статья открывается на её сайте',
 			'article_viewed' => 'когда статья просматривается',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Максимальное количество непрочитанных статей',
 			'scroll' => 'во время прокрутки (except for important feeds)',	// DIRTY
 			'upon_gone' => 'когда это больше не в новостной ленте',

+ 1 - 0
app/i18n/sk/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'keď je článok otvorený na svojej webovej stránke',
 			'article_viewed' => 'keď je článok zobrazený',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Maximálny počet článkov ponechať ako neprečítané',
 			'scroll' => 'počas skrolovania (except for important feeds)',	// DIRTY
 			'upon_gone' => 'keď už nie je v hlavnom kanály noviniek',

+ 1 - 0
app/i18n/tr/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => 'orijinal makale sitesi açıldığında',
 			'article_viewed' => 'makale görüntülendiğinde',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => 'Okunmadı tutulacak maksimum metin sayısı',
 			'scroll' => 'kaydırma yapılırken (except for important feeds)',	// DIRTY
 			'upon_gone' => 'Yeni akışta üst sıralarda değilken',

+ 1 - 0
app/i18n/zh-cn/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => '在打开原文章后',
 			'article_viewed' => '在文章被浏览后',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => '未读最多保留 n 条',
 			'scroll' => '在滚动浏览后 (except for important feeds)',	// DIRTY
 			'upon_gone' => '在被原订阅源被移除后',

+ 1 - 0
app/i18n/zh-tw/conf.php

@@ -204,6 +204,7 @@ return array(
 		'read' => array(
 			'article_open_on_website' => '在打開原文章後',
 			'article_viewed' => '在文章被瀏覽後',
+			'focus' => 'when focused (except for important feeds)',	// TODO
 			'keep_max_n_unread' => '未讀最多保留 n 條',
 			'scroll' => '在滾動瀏覽後 (except for important feeds)',	// DIRTY
 			'upon_gone' => '在被原訂閱源移除後',

+ 12 - 0
app/views/configure/reading.phtml

@@ -280,6 +280,18 @@
 				</div>
 			</div>
 
+			<div class="form-group">
+				<label class="group-name" for="check_focus"><?= _t('conf.reading.read.when') ?></label>
+				<div class="group-controls">
+					<label class="checkbox" for="check_focus">
+						<input type="checkbox" name="mark_focus" id="check_focus" value="1"<?=
+							FreshRSS_Context::$user_conf->mark_when['focus'] ? ' checked="checked"' : '' ?>
+							data-leave-validation="<?= FreshRSS_Context::$user_conf->mark_when['focus'] ?>" />
+						<?= _t('conf.reading.read.focus') ?>
+					</label>
+				</div>
+			</div>
+
 			<div class="form-group">
 				<label class="group-name" for="enable_read_when_same_title_in_feed"><?= _t('conf.reading.read.when') ?></label>
 				<div class="group-controls">

+ 1 - 0
app/views/helpers/javascript_vars.phtml

@@ -13,6 +13,7 @@ echo htmlspecialchars(json_encode(array(
 		'auto_mark_article' => !!$mark['article'],
 		'auto_mark_site' => !!$mark['site'],
 		'auto_mark_scroll' => !!$mark['scroll'],
+		'auto_mark_focus' => !!$mark['focus'],
 		'auto_load_more' => !!FreshRSS_Context::$user_conf->auto_load_more,
 		'auto_actualize_feeds' => !!Minz_Session::param('actualize_feeds', false),
 		'does_lazyload' => !!FreshRSS_Context::$user_conf->lazyload ,

+ 1 - 0
config-user.default.php

@@ -61,6 +61,7 @@ return array (
 		'reception' => false,
 		'same_title_in_feed' => false,
 		'scroll' => false,
+		'focus' => false,
 		'site' => true,
 	),
 	'theme' => 'Origine',

+ 9 - 0
p/scripts/main.js

@@ -481,6 +481,9 @@ function prev_entry(skipping) {
 	} else {
 		new_active = document.querySelector('.flux');
 	}
+	if (context.auto_mark_focus && !new_active.classList.contains('keep_unread')) {
+		mark_read(new_active, true, true);
+	}
 	toggleContent(new_active, old_active, skipping);
 }
 
@@ -496,6 +499,9 @@ function next_entry(skipping) {
 	} else {
 		new_active = document.querySelector('.flux');
 	}
+	if (context.auto_mark_focus && !new_active.classList.contains('keep_unread')) {
+		mark_read(new_active, true, true);
+	}
 	toggleContent(new_active, old_active, skipping);
 }
 
@@ -511,6 +517,9 @@ function next_unread_entry(skipping) {
 	} else {
 		new_active = document.querySelector('.not_read');
 	}
+	if (context.auto_mark_focus && !new_active.classList.contains('keep_unread')) {
+		mark_read(new_active, true, true);
+	}
 	toggleContent(new_active, old_active, skipping);
 }