Files
FreshRSS/app/Models/View.php
Gerard Alvear Porras 36d973a3bd Filter global view feed list by state and search (#9132)
* Filter global feed list by favorites

Fixes #4564.

The global view now filters its category/feed list when the Favorites filter is active, using the same article state and search criteria used when a feed is opened. Empty categories are omitted rather than showing feeds that would open to no matching articles.

* Fix favorite feed state query typing

* Rework logic, including searches

After reflection, I have revised the logic so that in the global view, the categories and feeds shown are always filtered by the search query (if any) and the states (if consequential):

<img width="2012" height="846" alt="image" src="https://github.com/user-attachments/assets/1fd693fa-9184-4601-85ed-2579e3b7299c" />


This makes the global view more useful and distinct in my opinion (this was otherwise not a view I was using myself, but now it will be).

Note that this behaviour would be challenging to port to the normal view for performance reasons.

* Show the matching counts in the global view UI instead of number of unreads

* Spelling

* Fix case of STATE_ALL

* Minor: more explicit logic

---------

Co-authored-by: Gerard Alvear <gerard.alvear@logiqd.me>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
2026-07-29 16:36:06 +02:00

157 lines
4.7 KiB
PHP

<?php
declare(strict_types=1);
/**
* @phpstan-import-type ExtensionFullMetadata from FreshRSS_extension_Controller
*/
class FreshRSS_View extends Minz_View {
// Main views
/** @var callable */
public $callbackBeforeEntries;
/** @var callable|null */
public $callbackBeforeFeeds;
/** @var callable */
public $callbackBeforePagination;
/** @var array<int,FreshRSS_Category> where the key is the category ID */
public array $categories;
public ?FreshRSS_Category $category = null;
public ?FreshRSS_Tag $tag = null;
public string $current_user;
/** @var iterable<FreshRSS_Entry> */
public $entries;
public ?FreshRSS_Entry $entry = null;
public ?FreshRSS_Feed $feed = null;
/** @var array<int,FreshRSS_Feed> where the key is the feed ID */
public array $feeds;
/**
* The keys are the feed IDs that have entries matching the current state and search filters (global view).
* @var array<int,int>|null
*/
public ?array $feedIdsMatching = null;
public int $nbUnreadTags;
/** @var array<int,FreshRSS_Tag> where the key is the label ID */
public array $tags;
/** @var list<array{id:int,name:string,checked:bool}> */
public array $tagsForEntry;
/** @var array<string,array<string>> */
public array $tagsForEntries;
public bool $excludeMutedFeeds;
public bool $includeSensitiveCurlParams = false;
// Search
/** @var array<int,FreshRSS_Tag> where the key is the label ID */
public array $labels;
// Subscriptions
public string $cfrom = '';
public bool $displaySlider = false;
public bool $load_ok;
public bool $onlyFeedsWithError;
public bool $signalError;
// Manage users
/** @var array{feed_count:?int,article_count:?int,database_size:?int,language:string,mail_login:string,enabled:bool,is_admin:bool,last_user_activity:string,is_default:bool} */
public array $details;
public bool $disable_aside;
public bool $show_email_field;
public string $username;
/** @var array<array{language:string,enabled:bool,is_admin:bool,enabled:bool,article_count:?int,database_size:?int,last_user_activity:string,mail_login:string,feed_count:?int,is_default:bool}> */
public array $users;
// Updates
public string $last_update_time;
/** @var array<string,'ok'|'ko'|'warn'> */
public array $status_files;
/** @var array<string,'ok'|'ko'|'warn'> */
public array $status_php;
public bool $update_to_apply;
/** @var array<string,array<string, bool>|bool> */
public array $status_database;
public bool $is_release_channel_stable;
// Archiving
public int $nb_total;
public int $size_total;
public int $size_user;
// Display
/** @var array<string,array{id:string,name:string,author:string,description:string,version:float|string,files:array<string>,theme-color?:string|array{dark?:string,light?:string,default?:string}}> */
public array $themes;
// Shortcuts
/** @var array<int, string> */
public array $list_keys;
// User queries
/** @var array<int,FreshRSS_UserQuery> where the key is the query ID */
public array $queries;
/** @var FreshRSS_UserQuery|null */
public ?FreshRSS_UserQuery $query = null;
// Export / Import
public string $content;
/** @var array<string,array<string>> */
public array $entryIdsTagNames = [];
public string $list_title;
public int $queryId;
public string $type;
/** @var null|array<array{name:string,size:int,mtime:int}> */
public ?array $sqliteArchives = null;
public string $sqlitePath;
public string $sqliteName;
// Form login
public int $cookie_days;
// Registration
public bool $can_register;
public string $preferred_language;
public bool $show_tos_checkbox;
public string $terms_of_service;
public string $site_title;
public string $validation_url;
// Logs
public int $currentPage;
public Minz_Paginator $logsPaginator;
public int $nbPage;
public string $logSearch = '';
// RSS view
public FreshRSS_UserQuery $userQuery;
public string $html_url = '';
public string $rss_title = '';
public string $rss_url = '';
public string $rss_base = '';
public bool $internal_rendering = false;
public string $description = '';
public string $image_url = '';
public bool $publishLabelsInsteadOfTags = false;
// Content preview
public string $fatalError;
public string $htmlContent;
public bool $selectorSuccess;
// Extensions
/** @var list<ExtensionFullMetadata> */
public array $available_extensions;
public ?Minz_Extension $ext_details = null;
/** @var array{system:array<Minz_Extension>,user:array<Minz_Extension>} */
public array $extension_list;
public ?Minz_Extension $extension = null;
/** @var array<string,string> */
public array $extensions_installed;
// Errors
public string $code;
public string $errorMessage;
/** @var array<string,string> */
public array $message;
// View modes
/** @var array<FreshRSS_ViewMode> */
public array $viewModes;
}