mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2026-05-14 02:03:55 -04:00
Closes FreshRSS/FreshRSS#6522. Refresh of FreshRSS/FreshRSS#6590 by @sgzmd, which has been stalled with merge conflicts since 2024. All original commits are preserved as-is in the history (authorship intact); this PR adds a merge with current `edge` plus minor fixes. ## Summary Adds a user setting `show_title_unread` (default `true`, so existing behavior is preserved) that hides the unread article counter from both the tab title and the favicon overlay. A single toggle controls both, matching the request in #6522. ## Screenshots Toggle in display settings: <img width="320" height="127" alt="Display settings with new toggle" src="https://github.com/user-attachments/assets/fc78f825-161d-4b47-9b85-08e39554a4b1" /> Tab title and favicon when **enabled** (current behavior): <img width="253" height="42" alt="Tab title and favicon with unread counter" src="https://github.com/user-attachments/assets/57387600-72e0-4b22-b059-04b5bfea673a" /> Tab title and favicon when **disabled** (new behavior): <img width="254" height="40" alt="Tab title and favicon without unread counter" src="https://github.com/user-attachments/assets/93ac7997-dd4e-49bc-ab4a-74e4f0d2db1b" /> ## Changes on top of #6590 - Resolved merge conflicts with current `edge` (controllers, model, view, `config.default.php`, ~25 i18n files, plus the `zh-tw` -> `zh-TW` rename). - Replaced Czech text mistakenly placed in `de/conf.php` with an English `// TODO` marker so a German speaker can translate later. - Renamed JS context key `show_unread_favicon` -> `show_title_unread` to match the backend property and avoid a confusing dual-name for one setting. - Removed an unused duplicate of `show_title_unread` from `config.default.php` (the setting is read via `userConf()`, never `systemConf()`). - Gated the dynamic title rewrite in `incUnreadsFeed` (`p/scripts/main.js`) on the setting. Without this, marking an article read while the setting was off would re-add the `(N)` prefix to the tab title. - Escaped a stray apostrophe in the Occitan translation that broke parsing. - `make fix-all` re-sorted i18n keys and added `// TODO` placeholders for `fi`, `pt-PT`, `uk` (untranslated by the original PR). ## Test plan - [x] `make test-all` passes (620/620 PHPUnit, phpstan, phpcs, eslint, stylelint, markdownlint clean; `bin/typos` failed locally with a binary arch mismatch on macOS arm64 - unrelated to this change). - [x] Manually tested on a real instance: default behavior unchanged; toggling the setting hides both the tab title `(N) ` prefix and the favicon overlay; toggling back restores both; marking articles read while the setting is off does not bring the counter back; opening and closing an article preserves the user's choice. * Make showing the number of unread items in the title configurable. * Proposed approach to passing show_unread_favicon setting down to client-side code * Fixes and refactoring * Updating default config for the user. When user's config wasn't initialised we are copying it from `config-user.default.php` - if `show_title_unread` is not there, it is assumed to be false, whereas in `config.default.php` it's true by default. This results in inconsistency until user changes the field for the first time in Config->Display. * Adding translations. * fix: gate JS title rewrite + drop dead system config entry The original PR added show_title_unread to both config-user.default.php (read by userConf, the right place) and config.default.php (read by systemConf, never used here). Drop the system-level entry. Also: incUnreadsFeed dynamically rewrites document.title when articles are marked read/unread. That code path was not gated by the setting, so toggling the setting off and then marking an article read would re-add the (N) prefix to the tab title. Skip the document.title / prevTitle write when context.show_title_unread is false. * fix: drop README pollution from local make fix-all `make fix-all` regenerated the README translation tables on macOS, where the case-insensitive filesystem and an untracked local `app/i18n/nb/` directory caused the generator to emit `zh-tw` (lowercase) and an `nb` entry. Reset both README files to upstream/edge so CI can regenerate them cleanly. * fix: restore zh-TW/conf.php from edge (case-insensitive FS damage) The macOS case-insensitive filesystem caused the merge to overwrite upstream/edge's properly-translated zh-TW/conf.php with the older zh-tw/conf.php content from the PR side, regressing translation coverage from 94% to 71%. Reset the file to edge's content and re-add the show_title_unread Traditional Chinese translation. --------- Co-authored-by: sgzmd <sigizmund@gmail.com> Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr> Co-authored-by: Bjørn A. Andersen <polybjorn@users.noreply.github.com>
This commit is contained in:
@@ -74,6 +74,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
|
||||
FreshRSS_Context::userConf()->bottomline_date = Minz_Request::paramBoolean('bottomline_date');
|
||||
FreshRSS_Context::userConf()->bottomline_link = Minz_Request::paramBoolean('bottomline_link');
|
||||
FreshRSS_Context::userConf()->show_nav_buttons = Minz_Request::paramBoolean('show_nav_buttons');
|
||||
FreshRSS_Context::userConf()->show_title_unread = Minz_Request::paramBoolean('show_title_unread');
|
||||
FreshRSS_Context::userConf()->sidebar_hidden_by_default = Minz_Request::paramBoolean('sidebar_hidden_by_default');
|
||||
FreshRSS_Context::userConf()->html5_notif_timeout = max(0, Minz_Request::paramInt('html5_notif_timeout'));
|
||||
FreshRSS_Context::userConf()->html5_enable_notif = Minz_Request::paramBoolean('html5_enable_notif');
|
||||
|
||||
@@ -145,7 +145,7 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
|
||||
if ($search !== '') {
|
||||
$title = '“' . htmlspecialchars($search, ENT_COMPAT, 'UTF-8') . '”';
|
||||
}
|
||||
if (FreshRSS_Context::$get_unread > 0) {
|
||||
if (FreshRSS_Context::userConf()->show_title_unread && FreshRSS_Context::$get_unread > 0) {
|
||||
$title = '(' . FreshRSS_Context::$get_unread . ') ' . $title;
|
||||
}
|
||||
if (strlen($title) > 0) {
|
||||
@@ -224,7 +224,7 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
|
||||
|
||||
$this->view->rss_title = FreshRSS_Context::$name . ' | ' . FreshRSS_View::title();
|
||||
$title = _t('index.feed.title_global');
|
||||
if (FreshRSS_Context::$get_unread > 0) {
|
||||
if (FreshRSS_Context::userConf()->show_title_unread && FreshRSS_Context::$get_unread > 0) {
|
||||
$title = '(' . FreshRSS_Context::$get_unread . ') ' . $title;
|
||||
}
|
||||
FreshRSS_View::prependTitle($title . ' · ');
|
||||
|
||||
@@ -54,6 +54,7 @@ declare(strict_types=1);
|
||||
* @property bool $icons_as_emojis
|
||||
* @property int $simplify_over_n_feeds
|
||||
* @property bool $show_nav_buttons
|
||||
* @property bool $show_title_unread
|
||||
* @property bool $sidebar_hidden_by_default
|
||||
* @property 'big'|'small'|'none' $mark_read_button
|
||||
* @property 'ASC'|'DESC' $sort_order
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Časový limit HTML5 oznámení',
|
||||
),
|
||||
'show_nav_buttons' => 'Zobrazit navigační tlačítka',
|
||||
'show_title_unread' => 'Zobrazit počet nepřečtených článků v názvu',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Motiv',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Zeitüberschreitung für HTML5-Benachrichtigung',
|
||||
),
|
||||
'show_nav_buttons' => 'Navigations-Buttons anzeigen',
|
||||
'show_title_unread' => 'Show number of unread articles in the title', // TODO
|
||||
'sidebar_hidden_by_default' => 'Seitenleiste standardmäßig ausblenden',
|
||||
'theme' => array(
|
||||
'_' => 'Layout',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 notification timeout', // TODO
|
||||
),
|
||||
'show_nav_buttons' => 'Show the navigation buttons', // TODO
|
||||
'show_title_unread' => 'Εμφάνιση αριθμού μη αναγνωσμένων άρθρων στον τίτλο',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Theme', // TODO
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 notification timeout', // IGNORE
|
||||
),
|
||||
'show_nav_buttons' => 'Show the navigation buttons', // IGNORE
|
||||
'show_title_unread' => 'Show number of unread articles in the title', // IGNORE
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // IGNORE
|
||||
'theme' => array(
|
||||
'_' => 'Theme', // IGNORE
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 notification timeout',
|
||||
),
|
||||
'show_nav_buttons' => 'Show the navigation buttons',
|
||||
'show_title_unread' => 'Show number of unread articles in the title',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default',
|
||||
'theme' => array(
|
||||
'_' => 'Theme',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Notificación de fin de espera HTML5',
|
||||
),
|
||||
'show_nav_buttons' => 'Mostrar los botones de navegación',
|
||||
'show_title_unread' => 'Mostrar el número de artículos no leídos en el título',
|
||||
'sidebar_hidden_by_default' => 'Ocultar barra lateral por defecto',
|
||||
'theme' => array(
|
||||
'_' => 'Tema',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => ' وقفه اعلان HTML5',
|
||||
),
|
||||
'show_nav_buttons' => ' دکمه های ناوبری را نشان دهید',
|
||||
'show_title_unread' => 'نمایش تعداد مقالات خوانده نشده در عنوان',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => ' موضوع',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Tauko HTML5-ilmoitusten välissä',
|
||||
),
|
||||
'show_nav_buttons' => 'Näytä siirtymispainikkeet',
|
||||
'show_title_unread' => 'Show number of unread articles in the title', // TODO
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Teema',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Temps d’affichage de la notification HTML5',
|
||||
),
|
||||
'show_nav_buttons' => 'Afficher les boutons de navigation',
|
||||
'show_title_unread' => 'Afficher le nombre d’articles non lus dans le titre',
|
||||
'sidebar_hidden_by_default' => 'Masquer la barre latérale par défaut',
|
||||
'theme' => array(
|
||||
'_' => 'Thème',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 התראה פג תוקף',
|
||||
),
|
||||
'show_nav_buttons' => 'Show the navigation buttons', // TODO
|
||||
'show_title_unread' => 'הצגת מספר המאמרים שלא נקראו בכותרת',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'ערכת נושא',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 értesítés hossza',
|
||||
),
|
||||
'show_nav_buttons' => 'Navigációs gombok megjelenítése',
|
||||
'show_title_unread' => 'A meg nem nyitott cikkek számának megjelenítése a címben',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Téma',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Batas waktu pemberitahuan HTML5',
|
||||
),
|
||||
'show_nav_buttons' => 'Tampilkan tombol navigasi',
|
||||
'show_title_unread' => 'Tampilkan jumlah artikel yang belum dibaca di judul',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Tema',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Notifica timeout HTML5',
|
||||
),
|
||||
'show_nav_buttons' => 'Mostra i pulsanti di navigazione',
|
||||
'show_title_unread' => 'Mostra il numero di articoli non letti nel titolo',
|
||||
'sidebar_hidden_by_default' => 'Nascondi la barra laterale di default',
|
||||
'theme' => array(
|
||||
'_' => 'Tema',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 の通知タイムアウト時間',
|
||||
),
|
||||
'show_nav_buttons' => 'ナビゲーションボタンを表示する',
|
||||
'show_title_unread' => 'タイトルに未読の記事数を表示',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'テーマ',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 알림 타임아웃',
|
||||
),
|
||||
'show_nav_buttons' => '내비게이션 버튼 보이기',
|
||||
'show_title_unread' => '제목에 읽지 않은 기사 수 표시',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => '테마',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 paziņojuma laika ierobežojums',
|
||||
),
|
||||
'show_nav_buttons' => 'Rādīt navigācijas pogas',
|
||||
'show_title_unread' => 'Rādīt nelasīto rakstu skaitu virsrakstā',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Tēma',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 notificatie stop',
|
||||
),
|
||||
'show_nav_buttons' => 'Toon navigatieknoppen',
|
||||
'show_title_unread' => 'Aantal ongelezen artikelen in de titel weergeven',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Thema',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Temps d’afichatge de las notificacions HTML5',
|
||||
),
|
||||
'show_nav_buttons' => 'Mostrar los botons de navigacion',
|
||||
'show_title_unread' => 'Mostra lo nombre d’articles non legits dins lo títol',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Tèma',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Czas wyświetlania powiadomienia HTML5',
|
||||
),
|
||||
'show_nav_buttons' => 'Pokaż przyciski nawigacyjne',
|
||||
'show_title_unread' => 'Pokaż liczbę nieprzeczytanych artykułów w tytule',
|
||||
'sidebar_hidden_by_default' => 'Ukryj pasek boczny domyślnie',
|
||||
'theme' => array(
|
||||
'_' => 'Motyw',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Notificação em HTML5 de timeout',
|
||||
),
|
||||
'show_nav_buttons' => 'Mostrar botões de navegação',
|
||||
'show_title_unread' => 'Mostrar o número de artigos não lidos no título',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Tema',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Notificação em HTML5 de timeout',
|
||||
),
|
||||
'show_nav_buttons' => 'Mostrar botões de navegação',
|
||||
'show_title_unread' => 'Show number of unread articles in the title', // TODO
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Tema',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Таймаут уведомлений HTML5',
|
||||
),
|
||||
'show_nav_buttons' => 'Показать кнопки навигации',
|
||||
'show_title_unread' => 'Показать количество непрочитанных статей в заголовке',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Тема',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Limit HTML5 oznámenia',
|
||||
),
|
||||
'show_nav_buttons' => 'Zobraziť tlačidlá oznámenia',
|
||||
'show_title_unread' => 'Zobraziť počet neprečítaných článkov v názve',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Vzhľad',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 bildirim zaman aşımı',
|
||||
),
|
||||
'show_nav_buttons' => 'Gezinme düğmelerini göster',
|
||||
'show_title_unread' => 'Başlıkta okunmamış makale sayısını göster',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Tema',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'Тайм-аут сповіщення HTML5',
|
||||
),
|
||||
'show_nav_buttons' => 'Показати кнопки навігації',
|
||||
'show_title_unread' => 'Show number of unread articles in the title', // TODO
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => 'Тема',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 通知超时时间',
|
||||
),
|
||||
'show_nav_buttons' => '显示导航按钮',
|
||||
'show_title_unread' => '在标题中显示未读文章的数量',
|
||||
'sidebar_hidden_by_default' => 'Hide sidebar by default', // TODO
|
||||
'theme' => array(
|
||||
'_' => '主题',
|
||||
|
||||
@@ -54,6 +54,7 @@ return array(
|
||||
'timeout' => 'HTML5 通知逾時',
|
||||
),
|
||||
'show_nav_buttons' => '顯示導覽按鈕',
|
||||
'show_title_unread' => '在標題中顯示未讀文章的數量',
|
||||
'sidebar_hidden_by_default' => '預設隱藏側邊欄',
|
||||
'theme' => array(
|
||||
'_' => '主題',
|
||||
|
||||
@@ -275,6 +275,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="group-controls">
|
||||
<label class="checkbox" for="show_title_unread">
|
||||
<input type="checkbox" name="show_title_unread" id="show_title_unread" value="1"<?=
|
||||
FreshRSS_Context::userConf()->show_title_unread ? ' checked="checked"' : '' ?>
|
||||
data-leave-validation="<?= FreshRSS_Context::userConf()->show_title_unread ?>" />
|
||||
<?= _t('conf.display.show_title_unread') ?>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="group-controls">
|
||||
<label class="checkbox" for="sidebar_hidden_by_default">
|
||||
|
||||
@@ -15,6 +15,7 @@ echo json_encode([
|
||||
'display_order' => Minz_Request::paramString('order') ?: FreshRSS_Context::userConf()->sort_order,
|
||||
'sort' => FreshRSS_Context::$sort,
|
||||
'display_categories' => FreshRSS_Context::userConf()->display_categories,
|
||||
'show_title_unread' => FreshRSS_Context::userConf()->show_title_unread,
|
||||
'auto_mark_article' => !!$mark['article'],
|
||||
'auto_mark_site' => !!$mark['site'],
|
||||
'auto_mark_scroll' => !!$mark['scroll'],
|
||||
|
||||
@@ -33,6 +33,7 @@ return array (
|
||||
'default_view' => 'adaptive',
|
||||
'default_state' => FreshRSS_Entry::STATE_NOT_READ,
|
||||
'show_fav_unread' => false,
|
||||
'show_title_unread' => true,
|
||||
'auto_load_more' => true,
|
||||
'display_posts' => false,
|
||||
'display_categories' => 'active', //{ active, remember, all, none }
|
||||
|
||||
@@ -171,10 +171,12 @@ function incUnreadsFeed(article, feed_id, nb) {
|
||||
return p1;
|
||||
}
|
||||
});
|
||||
if (prevTitle) {
|
||||
prevTitle = newTitle;
|
||||
} else {
|
||||
document.title = newTitle;
|
||||
if (context.show_title_unread !== false) {
|
||||
if (prevTitle) {
|
||||
prevTitle = newTitle;
|
||||
} else {
|
||||
document.title = newTitle;
|
||||
}
|
||||
}
|
||||
return isCurrentView;
|
||||
}
|
||||
@@ -2239,6 +2241,10 @@ function init_confirm_action() {
|
||||
}
|
||||
|
||||
function faviconNbUnread(n) {
|
||||
if (context.show_title_unread === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof n === 'undefined') {
|
||||
const t = document.querySelector('.category.all .title');
|
||||
n = t ? str2int(t.getAttribute('data-unread')) : 0;
|
||||
|
||||
Reference in New Issue
Block a user