Add new visibility priority *Show in its feed* (#7972)

* Add new visibility priority *Show in its feed*
fix https://github.com/FreshRSS/FreshRSS/pull/7970#issuecomment-3293917428 (you can't directly filter a hidden feed, it just shows a 404 page)
And add a new visibility *Show in its feed* to show the feed in the list but not its articles.
Ensure that visibility *hidden* is not shown to API.

* TODO for later

* Update app/i18n/pl/sub.php

Co-authored-by: Inverle <inverle@proton.me>
This commit is contained in:
Alexandre Alapetite
2025-09-30 10:05:17 +02:00
committed by GitHub
parent 11e6e0394c
commit 34532c0dd4
46 changed files with 72 additions and 19 deletions

View File

@@ -302,12 +302,10 @@ SQL;
. ($details ? 'f.* ' : 'f.id, f.name, f.url, f.kind, f.website, f.priority, f.error, f.attributes, f.`cache_nbEntries`, f.`cache_nbUnreads`, f.ttl ')
. 'FROM `_category` c '
. 'LEFT OUTER JOIN `_feed` f ON f.category=c.id '
. 'WHERE f.priority >= :priority '
. 'GROUP BY f.id, c_id '
. 'ORDER BY c.name, f.name';
$stm = $this->pdo->prepare($sql);
$values = [ ':priority' => FreshRSS_Feed::PRIORITY_CATEGORY ];
if ($stm !== false && $stm->execute($values) && ($res = $stm->fetchAll(PDO::FETCH_ASSOC)) !== false) {
if ($stm !== false && $stm->execute() && ($res = $stm->fetchAll(PDO::FETCH_ASSOC)) !== false) {
/** @var list<array{c_name:string,c_id:int,c_kind:int,c_last_update:int,c_error:int,c_attributes?:string,
* id?:int,name?:string,url?:string,kind?:int,category?:int,website?:string,priority?:int,error?:int,attributes?:string,cache_nbEntries?:int,cache_nbUnreads?:int,ttl?:int}> $res */
return self::daoToCategoriesPrepopulated($res);

View File

@@ -400,11 +400,12 @@ final class FreshRSS_Context {
* @throws Minz_ConfigurationNamespaceException
* @throws Minz_PDOConnectionException
*/
public static function _get(string $get): void {
private static function _get(string $get): void {
$type = $get[0];
$id = (int)substr($get, 2);
if (empty(self::$categories)) {
// TODO: Check whether this section is used
$catDAO = FreshRSS_Factory::createCategoryDao();
$details = $type === 'f'; // Load additional feed details in the case of feed view
self::$categories = $catDAO->listCategories(prePopulateFeeds: true, details: $details);

View File

@@ -571,9 +571,9 @@ SQL;
UPDATE `_entry`
SET is_read = ?
WHERE is_read <> ? AND id <= ?
AND id_feed IN (SELECT f.id FROM `_feed` f WHERE f.category=?)
AND id_feed IN (SELECT f.id FROM `_feed` f WHERE f.category=? AND f.priority >= ?)
SQL;
$values = [$is_read ? 1 : 0, $is_read ? 1 : 0, $idMax, $id];
$values = [$is_read ? 1 : 0, $is_read ? 1 : 0, $idMax, $id, FreshRSS_Feed::PRIORITY_CATEGORY];
[$searchValues, $search] = $this->sqlListEntriesWhere(alias: '', state: $state, filters: $filters);
@@ -1340,7 +1340,7 @@ SQL;
$where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_MAIN_STREAM . ' ';
break;
case 'A': // All except PRIORITY_HIDDEN
$where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_CATEGORY . ' ';
$where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_FEED . ' ';
break;
case 'Z': // All including PRIORITY_HIDDEN
$where .= 'f.priority >= ' . FreshRSS_Feed::PRIORITY_HIDDEN . ' ';

View File

@@ -38,6 +38,7 @@ class FreshRSS_Feed extends Minz_Model {
public const PRIORITY_IMPORTANT = 20;
public const PRIORITY_MAIN_STREAM = 10;
public const PRIORITY_CATEGORY = 0;
public const PRIORITY_FEED = -5;
public const PRIORITY_HIDDEN = -10;
/** @deprecated use PRIORITY_HIDDEN instead */
public const PRIORITY_ARCHIVED = -10;

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Viditelnost',
'category' => 'Zobrazit v jeho kategorii',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Nezobrazovat',
'important' => 'Zobrazit v důležitých kanálech',
'main_stream' => 'Zobrazit ve hlavním kanálu',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Sichtbarkeit',
'category' => 'Zeige in eigener Kategorie',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Nicht anzeigen',
'important' => 'Zeige in "Wichtige Feeds"',
'main_stream' => 'In Haupt-Feeds zeigen',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibility', // TODO
'category' => 'Show in its category', // TODO
'feed' => 'Show in its feed', // TODO
'hidden' => 'Do not show', // TODO
'important' => 'Show in important feeds', // TODO
'main_stream' => 'Show in main stream', // TODO

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibility', // IGNORE
'category' => 'Show in its category', // IGNORE
'feed' => 'Show in its feed', // IGNORE
'hidden' => 'Do not show', // IGNORE
'important' => 'Show in important feeds', // IGNORE
'main_stream' => 'Show in main stream', // IGNORE

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibility',
'category' => 'Show in its category',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Do not show',
'important' => 'Show in important feeds',
'main_stream' => 'Show in main stream',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibilidad',
'category' => 'Mostrar en su categoría',
'feed' => 'Show in its feed', // TODO
'hidden' => 'No mostrar',
'important' => 'Mostrar en fuentes importantes',
'main_stream' => 'Mostrar en salida principal',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => ' دید',
'category' => ' نمایش در دسته بندی خود',
'feed' => 'Show in its feed', // TODO
'hidden' => 'نشان ندهید.',
'important' => 'نمایش در فیدهای مهم',
'main_stream' => ' نمایش در جریان اصلی',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Näkyvyys',
'category' => 'Näytä luokassaan',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Älä näytä',
'important' => 'Näytä tärkeissä syötteissä',
'main_stream' => 'Näytä pääsyötevirrassa',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibilité',
'category' => 'Afficher dans sa catégorie',
'feed' => 'Afficher dans son flux',
'hidden' => 'Ne pas afficher',
'important' => 'Afficher dans les flux importants',
'main_stream' => 'Afficher dans les flux principaux',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibility', // TODO
'category' => 'Show in its category', // TODO
'feed' => 'Show in its feed', // TODO
'hidden' => 'Do not show', // TODO
'important' => 'Show in important feeds', // TODO
'main_stream' => 'הצגה בזרם המרכזי',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Láthatóság',
'category' => 'Jelenjen meg a saját kategóriájában',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Ne jelenjen meg',
'important' => 'Megjelenítés a fontos hírforrásokban',
'main_stream' => 'Megjelenítés a Minden cikk között',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Ketampakan',
'category' => 'Tampilkan hanya di kategorinya saja',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Jangan tampilkan',
'important' => 'Tampilkan di umpan penting',
'main_stream' => 'Tampilkan di bagian utama',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibilità',
'category' => 'Mostra nella sua categoria',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Non mostrare',
'important' => 'Mostra nei feed importanti',
'main_stream' => 'Mostra in homepage',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => '表示する場所',
'category' => 'カテゴリで表示する',
'feed' => 'Show in its feed', // TODO
'hidden' => '非表示にする',
'important' => '重要なフィードに表示する',
'main_stream' => 'メインストリームで表示する',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => '표시',
'category' => '피드가 속한 카테고리에만 표시하기',
'feed' => 'Show in its feed', // TODO
'hidden' => '표시하지 않음',
'important' => '중요 피드에서 표시',
'main_stream' => '메인 스트림에 표시하기',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Prioritāte',
'category' => 'Rādīt kategorijā',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Nerādīt',
'important' => 'Show in important feeds', // TODO
'main_stream' => 'Rādīt galvenajā plūsmā',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Zichtbaarheid',
'category' => 'Toon in categorie',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Niet weergeven',
'important' => 'In belangrijke feeds tonen',
'main_stream' => 'Zichtbaar in het overzicht',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibilitat',
'category' => 'Mostar dins sa categoria',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Mostrar pas',
'important' => 'Show in important feeds', // TODO
'main_stream' => 'Mostar al flux màger',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Widoczność',
'category' => 'Pokaż w kategorii kanału',
'feed' => 'Pokaż w kanale',
'hidden' => 'Nie pokazuj',
'important' => 'Pokaż w ważnych kanałach',
'main_stream' => 'Pokaż w kanale głównym',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibilidade',
'category' => 'Mostrar na sua categoria',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Não exibir',
'important' => 'Mostrar feeds importantes',
'main_stream' => 'Mostrar na tela principal',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Visibilidade',
'category' => 'Mostrar na sua categoria',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Não exibir',
'important' => 'Mostrar feeds importantes',
'main_stream' => 'Mostrar na tela principal',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Видимость',
'category' => 'Показывать в категории ленты',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Не показывать',
'important' => 'Показывать в важных лентах',
'main_stream' => 'Показывать в основном потоке',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Viditeľnosť',
'category' => 'Zobraziť vo svojej kategórii',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Nezobrazovať',
'important' => 'Zobraziť v dôležitých kanáloch',
'main_stream' => 'Zobraziť v prehľade kanálov',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Görünürlük',
'category' => 'Kategorisinde göster',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Gösterilmesin',
'important' => 'Önemli beslemelerde göster',
'main_stream' => 'Ana akışta göster',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => 'Видимість',
'category' => 'Показати в категорії',
'feed' => 'Show in its feed', // TODO
'hidden' => 'Не показувати',
'important' => 'Показати у важливих стрічках',
'main_stream' => 'Показати в головному потоці',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => '可见性',
'category' => '在分类中显示',
'feed' => 'Show in its feed', // TODO
'hidden' => '不显示',
'important' => '在“重要的订阅”中显示',
'main_stream' => '在首页中显示',

View File

@@ -210,6 +210,7 @@ return array(
'priority' => array(
'_' => '可見性',
'category' => '在分類中顯示',
'feed' => 'Show in its feed', // TODO
'hidden' => '不顯示',
'important' => '顯示在重要的源',
'main_stream' => '在首頁中顯示',

View File

@@ -111,6 +111,9 @@
foreach ($feeds as $feed):
$f_active = FreshRSS_Context::isCurrentGet('f_' . $feed->id());
if (!$f_active && $feed->priority() < FreshRSS_Feed::PRIORITY_FEED) {
continue;
}
$f_active_class = $f_active ? ' active' : '';
$error_class = '';

View File

@@ -121,6 +121,8 @@
FreshRSS_Feed::PRIORITY_MAIN_STREAM === $this->feed->priority() ? 'selected="selected"' : '' ?>><?= _t('sub.feed.priority.main_stream') ?></option>
<option value="<?= FreshRSS_Feed::PRIORITY_CATEGORY ?>" <?=
FreshRSS_Feed::PRIORITY_CATEGORY === $this->feed->priority() ? 'selected="selected"' : '' ?>><?= _t('sub.feed.priority.category') ?></option>
<option value="<?= FreshRSS_Feed::PRIORITY_FEED ?>" <?=
FreshRSS_Feed::PRIORITY_FEED === $this->feed->priority() ? 'selected="selected"' : '' ?>><?= _t('sub.feed.priority.feed') ?></option>
<option value="<?= FreshRSS_Feed::PRIORITY_HIDDEN ?>" <?=
FreshRSS_Feed::PRIORITY_HIDDEN === $this->feed->priority() ? 'selected="selected"' : '' ?>><?= _t('sub.feed.priority.hidden') ?></option>
</select>

View File

@@ -64,6 +64,9 @@
<ul class="box-content scrollbar-thin">
<?php
foreach ($feeds as $feed) {
if ($feed->priority() < FreshRSS_Feed::PRIORITY_FEED) {
continue;
}
$nb_not_read = $feed->nbNotRead();
$error_class = '';

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="gold" />
<text x="34" y="14">🇨🇿 89%</text>
<text x="34" y="14">🇨🇿 88%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 327 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="green" />
<text x="34" y="14">🇩🇪 100%</text>
<text x="34" y="14">🇩🇪 99%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="green" />
<text x="34" y="14">🇭🇺 100%</text>
<text x="34" y="14">🇭🇺 99%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="green" />
<text x="34" y="14">🇮🇹 97%</text>
<text x="34" y="14">🇮🇹 96%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 328 B

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="gold" />
<text x="34" y="14">🇰🇷 89%</text>
<text x="34" y="14">🇰🇷 88%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 327 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="green" />
<text x="34" y="14">🇳🇱 100%</text>
<text x="34" y="14">🇳🇱 99%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="gold" />
<text x="34" y="14">🇷🇺 89%</text>
<text x="34" y="14">🇷🇺 88%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 327 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="green" />
<text x="34" y="14">🇹🇷 97%</text>
<text x="34" y="14">🇹🇷 96%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 328 B

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="green" />
<text x="34" y="14">🇺🇦 100%</text>
<text x="34" y="14">🇺🇦 99%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -2,6 +2,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="70" height="20">
<g fill="white" font-size="12" font-family="Verdana" text-anchor="middle">
<rect rx="3" width="70" height="20" fill="gold" />
<text x="34" y="14">🇹🇼 89%</text>
<text x="34" y="14">🇹🇼 88%</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 327 B

View File

@@ -317,6 +317,9 @@ final class FeverAPI
/** @var FreshRSS_Feed $feed */
foreach ($myFeeds as $feed) {
if ($feed->priority() <= FreshRSS_Feed::PRIORITY_HIDDEN) {
continue;
}
$feeds[] = [
'id' => $feed->id(),
'favicon_id' => $feed->id(),
@@ -362,6 +365,9 @@ final class FeverAPI
$myFeeds = $this->feedDAO->listFeeds();
foreach ($myFeeds as $feed) {
if ($feed->priority() <= FreshRSS_Feed::PRIORITY_HIDDEN) {
continue;
}
$id = $feed->hashFavicon();
$filename = DATA_PATH . '/favicons/' . $id . '.ico';
if (!file_exists($filename)) {
@@ -390,6 +396,9 @@ final class FeverAPI
$myFeeds = $this->feedDAO->listFeeds();
foreach ($myFeeds as $feed) {
if ($feed->priority() <= FreshRSS_Feed::PRIORITY_HIDDEN) {
continue;
}
$ids[$feed->categoryId()][] = $feed->id();
}
@@ -471,10 +480,13 @@ final class FeverAPI
$feeds = [];
foreach ($group_ids as $id) {
$category = $categoryDAO->searchById((int)$id); //TODO: Transform to SQL query without loop! Consider FreshRSS_CategoryDAO::listCategories(true)
if ($category == null) {
if ($category === null) {
continue;
}
foreach ($category->feeds() as $feed) {
if ($feed->priority() <= FreshRSS_Feed::PRIORITY_HIDDEN) {
continue;
}
$feeds[] = $feed->id();
}
}

View File

@@ -340,6 +340,9 @@ final class GReaderAPI {
$categoryDAO = FreshRSS_Factory::createCategoryDao();
foreach ($categoryDAO->listCategories(prePopulateFeeds: true, details: true) as $cat) {
foreach ($cat->feeds() as $feed) {
if ($feed->priority() <= FreshRSS_Feed::PRIORITY_HIDDEN) {
continue;
}
$subscriptions[] = [
'id' => 'feed/' . $feed->id(),
'title' => escapeToUnicodeAlternative($feed->name(), true),
@@ -502,6 +505,9 @@ final class GReaderAPI {
foreach ($categoryDAO->listCategories(prePopulateFeeds: true, details: true) as $cat) {
$catLastUpdate = 0;
foreach ($cat->feeds() as $feed) {
if ($feed->priority() <= FreshRSS_Feed::PRIORITY_HIDDEN) {
continue;
}
$lastUpdate = $feedsNewestItemUsec['f_' . $feed->id()] ?? 0;
$unreadcounts[] = [
'id' => 'feed/' . $feed->id(),
@@ -662,7 +668,7 @@ final class GReaderAPI {
'starred' => 's',
'feed' => 'f',
'label' => 'c',
'reading-list' => 'A',
'reading-list' => 'A', // All except PRIORITY_HIDDEN
default => 'A',
};