Quellcode durchsuchen

New option mark article as read if identical title in category (#6922)

* New mark articles as read if identical title in category
fix https://github.com/FreshRSS/FreshRSS/issues/6143

* i18n todo forgotten
Alexandre Alapetite vor 1 Jahr
Ursprung
Commit
aea9ba0d62

+ 6 - 0
app/Controllers/categoryController.php

@@ -100,6 +100,12 @@ class FreshRSS_category_Controller extends FreshRSS_ActionController {
 		FreshRSS_View::prependTitle($category->name() . ' · ' . _t('sub.title') . ' · ');
 
 		if (Minz_Request::isPost()) {
+			if (Minz_Request::paramBoolean('enable_read_when_same_title_in_category')) {
+				$category->_attribute('read_when_same_title_in_category', Minz_Request::paramInt('read_when_same_title_in_category'));
+			} else {
+				$category->_attribute('read_when_same_title_in_category', null);
+			}
+
 			$category->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read'));
 
 			if (Minz_Request::paramBoolean('use_default_purge_options')) {

+ 18 - 2
app/Controllers/feedController.php

@@ -409,6 +409,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 			$maxFeeds = PHP_INT_MAX;
 		}
 
+		$catDAO = FreshRSS_Factory::createCategoryDao();
 		$feedDAO = FreshRSS_Factory::createFeedDao();
 		$entryDAO = FreshRSS_Factory::createEntryDao();
 
@@ -425,7 +426,6 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 
 			// Hydrate category for each feed to avoid that each feed has to make an SQL request
 			$categories = [];
-			$catDAO = FreshRSS_Factory::createCategoryDao();
 			foreach ($catDAO->listCategories(false, false) as $category) {
 				$categories[$category->id()] = $category;
 			}
@@ -444,6 +444,8 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 		$nbUpdatedFeeds = 0;
 		$nbNewArticles = 0;
 		$feedsCacheToRefresh = [];
+		/** @var array<int,array<string,true>> */
+		$categoriesEntriesTitle = [];
 
 		foreach ($feeds as $feed) {
 			$feed = Minz_ExtensionManager::callHook('feed_before_actualize', $feed);
@@ -563,6 +565,14 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 					$titlesAsRead = [];
 				}
 
+				$category = $feed->category();
+				if (!isset($categoriesEntriesTitle[$feed->categoryId()]) && $category !== null && $category->hasAttribute('read_when_same_title_in_category')) {
+					$categoriesEntriesTitle[$feed->categoryId()] = array_fill_keys(
+						$catDAO->listTitles($feed->categoryId(), $category->attributeInt('read_when_same_title_in_category') ?? 0),
+						true
+					);
+				}
+
 				$mark_updated_article_unread = $feed->attributeBoolean('mark_updated_article_unread') ?? FreshRSS_Context::userConf()->mark_updated_article_unread;
 
 				// For this feed, check existing GUIDs already in database.
@@ -603,6 +613,9 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 							if ($readWhenSameTitleInFeed > 0) {
 								$titlesAsRead[$entry->title()] = true;
 							}
+							if (isset($categoriesEntriesTitle[$feed->categoryId()])) {
+								$categoriesEntriesTitle[$feed->categoryId()][$entry->title()] = true;
+							}
 
 							if (!$entry->isRead()) {
 								$needFeedCacheRefresh = true;	//Maybe
@@ -625,10 +638,13 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 							continue;
 						}
 
-						$entry->applyFilterActions($titlesAsRead);
+						$entry->applyFilterActions(array_merge($titlesAsRead, $categoriesEntriesTitle[$feed->categoryId()] ?? []));
 						if ($readWhenSameTitleInFeed > 0) {
 							$titlesAsRead[$entry->title()] = true;
 						}
+						if (isset($categoriesEntriesTitle[$feed->categoryId()])) {
+							$categoriesEntriesTitle[$feed->categoryId()][$entry->title()] = true;
+						}
 
 						$needFeedCacheRefresh = true;
 

+ 14 - 0
app/Models/CategoryDAO.php

@@ -388,6 +388,20 @@ SQL;
 		return isset($res[0]) ? (int)$res[0] : -1;
 	}
 
+	/** @return array<int,string> */
+	public function listTitles(int $id, int $limit = 0): array {
+		$sql = <<<'SQL'
+			SELECT e.title FROM `_entry` e
+			INNER JOIN `_feed` f ON e.id_feed=f.id
+			WHERE f.category=:id_category
+			ORDER BY e.id DESC
+		SQL;
+		$sql .= ($limit < 1 ? '' : ' LIMIT ' . intval($limit));
+		$res = $this->fetchColumn($sql, 0, [':id_category' => $id]) ?? [];
+		/** @var array<int,string> $res */
+		return $res;
+	}
+
 	/**
 	 * @param array<array{'c_name':string,'c_id':int,'c_kind':int,'c_last_update':int,'c_error':int|bool,'c_attributes'?:string,
 	 * 	'id'?:int,'name'?:string,'url'?:string,'kind'?:int,'website'?:string,'priority'?:int,

+ 2 - 1
app/i18n/cs/conf.php

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'když se již nenachází v upstreamu zpráv.',
 			'upon_reception' => 'po obdržení článku',
 			'when' => 'Označit článek jako přečtený…',
-			'when_same_title' => 'když shodný název již existuje v top <i>n</i> nejnovějších článcích',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'když shodný název již existuje v top <i>n</i> nejnovějších článcích (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Počet zobrazených článků',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'wenn der Artikel nicht mehr im Feed enthalten ist',
 			'upon_reception' => 'beim Empfang des Artikels',
 			'when' => 'Artikel als gelesen markieren…',
-			'when_same_title' => 'falls der identische Titel bereit in den <i>n</i> neusten Artikel vorhanden ist.',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'falls der identische Titel bereit in den <i>n</i> neusten Artikel vorhanden ist. (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Artikel zum Anzeigen',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'when it is no longer in the upstream news feed',	// TODO
 			'upon_reception' => 'upon receiving the article',	// TODO
 			'when' => 'Mark an article as read…',	// TODO
-			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// TODO
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'if an identical title already exists in the top <i>n</i> newest articles of the feed',	// TODO
 		),
 		'show' => array(
 			'_' => 'Articles to display',	// TODO

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'when it is no longer in the upstream news feed',	// IGNORE
 			'upon_reception' => 'upon receiving the article',	// IGNORE
 			'when' => 'Mark an article as read…',	// IGNORE
-			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// IGNORE
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// IGNORE
+			'when_same_title_in_feed' => 'if an identical title already exists in the top <i>n</i> newest articles of the feed',	// IGNORE
 		),
 		'show' => array(
 			'_' => 'Articles to display',	// IGNORE

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'when it is no longer in the upstream news feed',
 			'upon_reception' => 'upon receiving the article',
 			'when' => 'Mark an article as read…',
-			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',
+			'when_same_title_in_feed' => 'if an identical title already exists in the top <i>n</i> newest articles of the feed',
 		),
 		'show' => array(
 			'_' => 'Articles to display',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'cuando ya no está disponible en la fuente de noticias previa',
 			'upon_reception' => 'al recibir el artículo',
 			'when' => 'Marcar el artículo como leído…',
-			'when_same_title' => 'Si ya existe un título idéntico en la parte superior <i>n</i> artículos más recientes',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'Si ya existe un título idéntico en la parte superior <i>n</i> artículos más recientes (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Artículos a mostrar',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => ' زمانی که دیگر در فید اخبار بالادستی نیست',
 			'upon_reception' => ' پس از دریافت مقاله',
 			'when' => ' علامت گذاری یک مقاله به عنوان خوانده شده…',
-			'when_same_title' => ' اگر عنوان یکسانی از قبل در <i>n</i> جدیدترین مقالات بالا وجود داشته باشد',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => ' اگر عنوان یکسانی از قبل در <i>n</i> جدیدترین مقالات بالا وجود داشته باشد (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => ' مقالات برای نمایش',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'lorsqu’il n’est plus dans le flux d’actualités en amont',
 			'upon_reception' => 'dès la réception du nouvel article',
 			'when' => 'Marquer un article comme lu…',
-			'when_same_title' => 'si un même titre existe déjà dans les <i>n</i> articles plus récents',
+			'when_same_title_in_category' => 'si un même titre existe déjà dans les <i>n</i> articles plus récents de la catégorie',
+			'when_same_title_in_feed' => 'si un même titre existe déjà dans les <i>n</i> articles plus récents du flux',
 		),
 		'show' => array(
 			'_' => 'Articles à afficher',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'when it is no longer in the upstream news feed',	// TODO
 			'upon_reception' => 'כאשר המאמר מתקבל',
 			'when' => 'סימון מאמרים כנקראו…',
-			'when_same_title' => 'if an identical title already exists in the top <i>n</i> newest articles',	// TODO
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'if an identical title already exists in the top <i>n</i> newest articles of the feed',	// TODO
 		),
 		'show' => array(
 			'_' => 'מאמרים להצגה',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'ha már nincs benne a hírforrásban',
 			'upon_reception' => 'a cikk beérkezésekor',
 			'when' => 'Jelöljön meg egy cikket olvasottként…',
-			'when_same_title' => 'ha egy azonos című cikk már létezik a legújabb <i>n</i> számú cikk között',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'ha egy azonos című cikk már létezik a legújabb <i>n</i> számú cikk között (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Megjelenített cikkek',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'saat tidak lagi ada di feed berita atas',
 			'upon_reception' => 'saat menerima artikel',
 			'when' => 'Tandai artikel sebagai telah dibaca…',
-			'when_same_title' => 'jika judul identik sudah ada di <i>n</i> artikel terbaru',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'jika judul identik sudah ada di <i>n</i> artikel terbaru (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Artikel untuk ditampilkan',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'quando non si trova più nel feed di notizie in alto',
 			'upon_reception' => 'Alla ricezione del contenuto',
 			'when' => 'Segna articoli come letti…',
-			'when_same_title' => 'se un titolo identico esiste già tra i <i>n</i> articoli più recenti',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'se un titolo identico esiste già tra i <i>n</i> articoli più recenti (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Articoli da visualizzare',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'ニュースフィードの提供元がなくなったとき',
 			'upon_reception' => '記事を受け取ったとき',
 			'when' => '記事を既読にする…',
-			'when_same_title' => 'すでに同一タイトルが上位n件の最新記事に存在するとき',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'すでに同一タイトルが上位n件の最新記事に存在するとき (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => '記事を表示する',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => '원본 뉴스 피드에서 글 삭제 되었을 때',
 			'upon_reception' => '글을 가져오자마자',
 			'when' => '읽음으로 표시…',
-			'when_same_title' => '상위 <i>n</i>개의 최신 글에 동일한 제목이 이미 있는 경우',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => '상위 <i>n</i>개의 최신 글에 동일한 제목이 이미 있는 경우 (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => '글 표시 방식',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'kad tas vairs nav augšupējā ziņu barotnē',
 			'upon_reception' => 'pēc raksta saņemšanas',
 			'when' => 'Atzīmēt rakstu kā izlasītu…',
-			'when_same_title' => 'ja identisks virsraksts jau ir jaunākajos <i>n</i> rakstos',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'ja identisks virsraksts jau ir jaunākajos <i>n</i> rakstos (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Rādāmie raksti',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'als het niet langer in de nieuwsfeed staat',
 			'upon_reception' => 'bij ontvangst van het artikel',
 			'when' => 'Markeer artikel als gelezen…',
-			'when_same_title' => 'als een zelfde titel al voorkomt in de top <i>n</i> nieuwste artikelen',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'als een zelfde titel al voorkomt in de top <i>n</i> nieuwste artikelen (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Artikelen om te tonen',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'quand es pas mai dins lo flux de novèla font',
 			'upon_reception' => 'en recebre un article novèl',
 			'when' => 'Marcar un article coma legit…',
-			'when_same_title' => 'se un títol identic existís ja demest lo <i>n</i> articles mai recents',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'se un títol identic existís ja demest lo <i>n</i> articles mai recents (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Articles de mostrar',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'gdy nie jest już listowana w źródle kanału',
 			'upon_reception' => 'po otrzymaniu wiadomości',
 			'when' => 'Oznacz wiadomość jako przeczytaną…',
-			'when_same_title' => 'gdy identyczny tytuł już istnieje w <i>n</i> najnowszych wiadomościach',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'gdy identyczny tytuł już istnieje w <i>n</i> najnowszych wiadomościach (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Wiadomości do wyświetlenia',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'Quando não estiver mais no feed de notícias principais',
 			'upon_reception' => 'ao receber um artigo',
 			'when' => 'Marcar artigo como lido…',
-			'when_same_title' => 'Se um título idêntico já existir nos últimos <i>n</i> artigos mais novos',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'Se um título idêntico já existir nos últimos <i>n</i> artigos mais novos (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Artigos para exibir',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'когда это больше не в новостной ленте',
 			'upon_reception' => 'по получении статьи',
 			'when' => 'Отмечать статью прочитанной…',
-			'when_same_title' => 'если идентичный заголовок уже существует в верхних <i>n</i> новейших статьях',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'если идентичный заголовок уже существует в верхних <i>n</i> новейших статьях (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Какие статьи отображать',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'keď už nie je v hlavnom kanály noviniek',
 			'upon_reception' => 'po načítaní článku',
 			'when' => 'Označiť článok ako prečítaný…',
-			'when_same_title' => 'ak rovnaký nadpis už existuje v TOP <i>n</i> najnovších článkoch',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'ak rovnaký nadpis už existuje v TOP <i>n</i> najnovších článkoch (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Článkov na zobrazenie',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => 'Yeni akışta üst sıralarda değilken',
 			'upon_reception' => 'makale üzerinde gelince',
 			'when' => 'Makaleyi okundu olarak işaretle…',
-			'when_same_title' => 'Aynı başlığa sahip daha yeni bir makale en popüler <i>n</i> yeni metinlerdeyse',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => 'Aynı başlığa sahip daha yeni bir makale en popüler <i>n</i> yeni metinlerdeyse (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => 'Gösterilecek makaleler',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => '在被原订阅源被移除后',
 			'upon_reception' => '在接收文章后',
 			'when' => '何时将文章标记为已读',
-			'when_same_title' => '已存在 n 条相同标题文章',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => '已存在 n 条相同标题文章 (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => '文章显示',

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

@@ -237,7 +237,8 @@ return array(
 			'upon_gone' => '在被原訂閱源移除後',
 			'upon_reception' => '在接收文章後',
 			'when' => '何時將文章標記為已讀',
-			'when_same_title' => '已存在 n 條相同標題文章',
+			'when_same_title_in_category' => 'if an identical title already exists in the top <i>n</i> newest articles of the category',	// TODO
+			'when_same_title_in_feed' => '已存在 n 條相同標題文章 (of the feed)',	// DIRTY
 		),
 		'show' => array(
 			'_' => '文章顯示',

+ 1 - 1
app/views/configure/reading.phtml

@@ -312,7 +312,7 @@
 						<input type="checkbox" name="enable_read_when_same_title_in_feed" id="enable_read_when_same_title_in_feed" value="1"<?=
 							empty(FreshRSS_Context::userConf()->mark_when['same_title_in_feed']) ? '' : ' checked="checked"' ?>
 							data-leave-validation="<?= empty(FreshRSS_Context::userConf()->mark_when['same_title_in_feed']) ? 0 : 1 ?>"/>
-						<?= _t('conf.reading.read.when_same_title') ?>
+						<?= _t('conf.reading.read.when_same_title_in_feed') ?>
 						<?php $read_when_same_title_in_feed = empty(FreshRSS_Context::userConf()->mark_when['same_title_in_feed']) ? 25 : FreshRSS_Context::userConf()->mark_when['same_title_in_feed']; ?>
 						<input type="number" id="read_when_same_title_in_feed" name="read_when_same_title_in_feed" min="0"
 							value="<?= $read_when_same_title_in_feed ?>" data-leave-validation="<?= $read_when_same_title_in_feed ?>" />

+ 16 - 0
app/views/helpers/category/update.phtml

@@ -76,6 +76,22 @@
 
 		<fieldset>
 			<legend><?= _t('sub.feed.filteractions') ?></legend>
+
+			<div class="form-group">
+				<label class="group-name" for="enable_read_when_same_title_in_category"><?= _t('conf.reading.read.when') ?></label>
+				<div class="group-controls">
+					<label class="checkbox" for="enable_read_when_same_title_in_category">
+						<input type="checkbox" name="enable_read_when_same_title_in_category" id="enable_read_when_same_title_in_category" value="1"<?=
+							$this->category->hasAttribute('read_when_same_title_in_category') ? ' checked="checked"' : '' ?>
+							data-leave-validation="<?= $this->category->hasAttribute('read_when_same_title_in_category') ? 1 : 0 ?>"/>
+						<?= _t('conf.reading.read.when_same_title_in_category') ?>
+						<?php $read_when_same_title_in_category = $this->category->hasAttribute('read_when_same_title_in_category') ? $this->category->attributeInt('read_when_same_title_in_category') : 25; ?>
+						<input type="number" id="read_when_same_title_in_category" name="read_when_same_title_in_category" min="0"
+							value="<?= $read_when_same_title_in_category ?>" data-leave-validation="<?= $read_when_same_title_in_category ?>" />
+					</label>
+				</div>
+			</div>
+
 			<div class="form-group">
 				<label class="group-name" for="filteractions_read"><?= _t('conf.reading.read.when') ?></label>
 				<div class="group-controls">

+ 1 - 1
app/views/helpers/feed/update.phtml

@@ -234,7 +234,7 @@
 						<option value="100"<?= $this->feed->attributeInt('read_when_same_title_in_feed') == 100 ? ' selected="selected"' : '' ?>>100</option>
 						<option value="1000"<?= $this->feed->attributeInt('read_when_same_title_in_feed') == 1000 ? ' selected="selected"' : '' ?>>1 000</option>
 					</select>
-					<?= _t('conf.reading.read.when_same_title') ?>
+					<?= _t('conf.reading.read.when_same_title_in_feed') ?>
 				</div>
 			</div>