aside_feed.phtml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. declare(strict_types=1);
  3. /** @var FreshRSS_View $this */
  4. $actual_view = Minz_Request::actionName();
  5. $class = '';
  6. if (FreshRSS_Context::userConf()->hide_read_feeds &&
  7. (FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_NOT_READ) || FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_OR_NOT_READ)) &&
  8. !FreshRSS_Context::isStateEnabled(FreshRSS_Entry::STATE_READ)) {
  9. $class = ' state_unread';
  10. }
  11. $state_filter_manual = '';
  12. if (($s = Minz_Request::paramString('state', plaintext: true)) !== '' && ctype_digit($s)) {
  13. $state_filter_manual .= '&state=' . $s;
  14. }
  15. if (FreshRSS_Context::userConf()->sticky_sort) {
  16. if (($s = Minz_Request::paramString('sort', plaintext: true)) !== '' && preg_match('/^[a-z.]+$/', $s)) {
  17. $state_filter_manual .= '&sort=' . $s;
  18. }
  19. if (($s = Minz_Request::paramString('order', plaintext: true)) !== '' && ctype_alpha($s)) {
  20. $state_filter_manual .= '&order=' . $s;
  21. }
  22. }
  23. $hideSucGlobal = FreshRSS_Context::userConf()->show_unread_count !== 'all' ? ' data-unread-hide="1"' : '';
  24. $hideSucImportant = FreshRSS_Context::userConf()->show_unread_count !== 'none' ? '' : ' data-unread-hide="1"';
  25. ?>
  26. <nav class="nav aside aside_feed<?= $class ?>" id="aside_feed">
  27. <a class="toggle_aside" href="#close"><?= _i('close') ?></a>
  28. <?php if (FreshRSS_Auth::hasAccess()) { ?>
  29. <div class="stick configure-feeds">
  30. <a id="btn-subscription" class="btn btn-important" href="<?= _url('subscription', 'index') ?>"><?= _t('index.menu.subscription') ?></a>
  31. <a id="btn-add" class="btn btn-important" href="<?= _url('subscription', 'add') ?>"><?= _i('add') ?></a>
  32. </div>
  33. <?php } elseif (FreshRSS_Auth::accessNeedsLogin()) { ?>
  34. <a href="<?= _url('index', 'about') ?>" class="about"><?= _t('index.menu.about') ?></a>
  35. <?php } ?>
  36. <form id="mark-read-aside" method="post">
  37. <input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
  38. <ul id="sidebar" class="tree scrollbar-thin">
  39. <li class="tree-folder category all<?= FreshRSS_Context::isCurrentGet('a') || FreshRSS_Context::isCurrentGet('A') || FreshRSS_Context::isCurrentGet('Z') ? ' active' : '' ?>">
  40. <a class="tree-folder-title" data-unread="<?= format_number(FreshRSS_Context::$total_unread) ?>"<?=
  41. $hideSucGlobal ?> href="<?= _url('index', $actual_view) . $state_filter_manual ?>">
  42. <?= _i('all') ?><span class="title" data-unread="<?= format_number(FreshRSS_Context::$total_unread) ?>"<?=
  43. $hideSucGlobal ?>><?= _t('index.menu.main_stream') ?></span>
  44. </a>
  45. </li>
  46. <li class="tree-folder category important<?= FreshRSS_Context::isCurrentGet('i') ? ' active' : '' ?>">
  47. <a class="tree-folder-title" data-unread="<?= format_number(FreshRSS_Context::$total_important_unread) ?>"<?=
  48. $hideSucImportant ?> href="<?= _url('index', $actual_view, 'get', 'i') . $state_filter_manual ?>">
  49. <?= _i('important') ?><span class="title" data-unread="<?= format_number(FreshRSS_Context::$total_important_unread) ?>"<?=
  50. $hideSucImportant ?>><?= _t('index.menu.important') ?></span>
  51. </a>
  52. </li>
  53. <li class="tree-folder category favorites<?= FreshRSS_Context::isCurrentGet('s') ? ' active' : '' ?>">
  54. <a class="tree-folder-title" data-unread="<?= format_number(FreshRSS_Context::$total_starred['unread']) ?>"<?=
  55. $hideSucGlobal ?> href="<?= _url('index', $actual_view, 'get', 's') . $state_filter_manual ?>">
  56. <?= _i('starred') ?><span class="title" data-unread="<?= format_number(FreshRSS_Context::$total_starred['unread']) ?>"<?=
  57. $hideSucGlobal ?>><?= _t('index.menu.favorites', format_number(FreshRSS_Context::$total_starred['all'])) ?></span>
  58. </a>
  59. </li>
  60. <?php
  61. $t_active = FreshRSS_Context::isCurrentGet('T');
  62. $t_show = ($t_active && in_array(FreshRSS_Context::userConf()->display_categories, ['active', 'remember'], true)) || FreshRSS_Context::userConf()->display_categories === 'all';
  63. ?>
  64. <li id="tags" class="tree-folder category tags<?= $t_active ? ' active' : '' ?>" data-unread="<?= format_number($this->nbUnreadTags) ?>"<?= $hideSucGlobal ?>>
  65. <a href="<?= _url('index', $actual_view, 'get', 'T') . $state_filter_manual ?>" class="tree-folder-title">
  66. <button class="dropdown-toggle" title="<?= _t('sub.category.expand') ?>"><?= _i($t_show ? 'up' : 'down') ?></button><span class="title" title="<?=
  67. _t('sub.category.open') ?>" data-unread="<?= format_number($this->nbUnreadTags) ?>"<?= $hideSucGlobal ?>><?= _t('index.menu.mylabels') ?></span>
  68. </a>
  69. <ul class="tree-folder-items<?= $t_show ? ' active' : '' ?>">
  70. <?php
  71. foreach ($this->tags as $tag):
  72. ?>
  73. <li id="t_<?= $tag->id() ?>" class="item feed<?= FreshRSS_Context::isCurrentGet('t_' . $tag->id()) ? ' active' : ''
  74. ?>" data-unread="<?= $tag->nbUnread() ?>"<?= $hideSucGlobal ?>>
  75. <?php if (FreshRSS_Auth::hasAccess()) { ?>
  76. <div class="dropdown no-mobile">
  77. <div id="dropdown-t-<?= $tag->id() ?>" class="dropdown-target"></div>
  78. <a class="dropdown-toggle" href="#dropdown-t-<?= $tag->id() ?>"><?= _i('configure') ?></a>
  79. <?php /* tag_config_template */ ?>
  80. </div>
  81. <?php } else { ?>
  82. <div class="no-dropdown-toggle"></div>
  83. <?php } ?>
  84. <a class="item-title" data-unread="<?= format_number($tag->nbUnread()) ?>"<?= $hideSucGlobal ?> href="<?=
  85. _url('index', $actual_view, 'get', 't_' . $tag->id()) . $state_filter_manual ?>"><?= _i('label') ?> <?= $tag->name() ?></a>
  86. </li>
  87. <?php endforeach; ?>
  88. </ul>
  89. </li>
  90. <?php
  91. $nbFeedsTotal = 0;
  92. foreach ($this->categories as $cat) {
  93. $nbFeedsTotal += $cat->nbFeeds();
  94. }
  95. foreach ($this->categories as $cat):
  96. $feeds = $cat->feeds();
  97. $position = $cat->attributeInt('position');
  98. if (!empty($feeds)) {
  99. $c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id());
  100. $c_show = ($c_active && in_array(FreshRSS_Context::userConf()->display_categories, ['active', 'remember'], true))
  101. || FreshRSS_Context::userConf()->display_categories === 'all';
  102. $hideSucCat = $cat->showUnreadCount() ? '' : ' data-unread-hide="1"';
  103. ?>
  104. <li id="c_<?= $cat->id() ?>" class="tree-folder category<?= $c_active ? ' active' : '' ?>"<?=
  105. null === $position ? '' : " data-position='$position'" ?> data-unread="<?= $cat->nbNotRead() ?>"<?= $hideSucCat ?>>
  106. <a href="<?= _url('index', $actual_view, 'get', 'c_' . $cat->id()) . $state_filter_manual ?>" class="tree-folder-title">
  107. <button class="dropdown-toggle" title="<?= _t('sub.category.expand') ?>"><?= _i($c_show ? 'up' : 'down') ?></button><?php
  108. ?><span title="<?= $cat->inError() ? _t('sub.category.error') : _t('sub.category.open') ?>" class="title<?=
  109. $cat->hasFeedsWithError() || $cat->inError() ? ' error' : ''
  110. ?>" data-unread="<?= format_number($cat->nbNotRead()) ?>"<?= $hideSucCat ?>><?=
  111. $cat->name() ?><?= $cat->kind() === FreshRSS_Category::KIND_DYNAMIC_OPML ? ' ' . _i('opml-dyn') : ''
  112. ?></span>
  113. </a>
  114. <ul class="tree-folder-items<?= $c_show ? ' active' : '' ?>">
  115. <?php
  116. // NB: Reduce whitespace in that loop
  117. $show_favicon = FreshRSS_Context::userConf()->show_favicons && $nbFeedsTotal < FreshRSS_Context::userConf()->simplify_over_n_feeds;
  118. foreach ($feeds as $feed):
  119. $f_active = FreshRSS_Context::isCurrentGet('f_' . $feed->id());
  120. if (!$f_active && $feed->priority() < FreshRSS_Feed::PRIORITY_FEED) {
  121. continue;
  122. }
  123. $f_active_class = $f_active ? ' active' : '';
  124. $error_class = '';
  125. $error_title = '';
  126. if ($feed->inError()) {
  127. $error_class = ' error';
  128. $error_title = _t('sub.feed.error');
  129. }
  130. $empty_class = '';
  131. $empty_title = '';
  132. if ($feed->nbEntries() <= 0) {
  133. $empty_class = ' empty';
  134. $empty_title = _t('sub.feed.empty');
  135. }
  136. $mute_class = $feed->mute() ? ' mute' : '';
  137. $hideSucFeed = $feed->showUnreadCount() ? '' : ' data-unread-hide="1"';
  138. ?>
  139. <li id="f_<?= $feed->id() ?>" class="item feed<?= $f_active_class, $mute_class, $error_class, $empty_class ?>"
  140. data-unread="<?= $feed->nbNotRead() ?>"<?= $hideSucFeed ?> data-priority="<?= $feed->priority() ?>"><?php
  141. if ($f_active || $nbFeedsTotal < FreshRSS_Context::userConf()->simplify_over_n_feeds):
  142. ?><div class="dropdown no-mobile">
  143. <div id="dropdown-<?= $feed->id() ?>" class="dropdown-target"></div><a href="#dropdown-<?= $feed->id() ?>" class="dropdown-toggle" title="<?=
  144. _t('gen.action.menu.open') ?>" data-fweb="<?= $feed->website() ?>"><?= _i('configure') ?></a><?php /* feed_config_template */ ?>
  145. </div><?php
  146. endif;
  147. $title = _t('sub.feed.open_feed', $feed->name());
  148. $title .= $error_title !== '' ? '&#13;⚠ ' . $error_title : '';
  149. $title .= $empty_title !== '' ? '&#13;' . $empty_title : '';
  150. $title .= $feed->mute() ? '&#13;🔇 ' . _t('sub.feed.mute.state_is_muted') : '';
  151. ?><a class="item-title" title="<?= $title ?>" data-unread="<?=
  152. format_number($feed->nbNotRead()) ?>"<?= $hideSucFeed ?> href="<?=
  153. _url('index', $actual_view, 'get', 'f_' . $feed->id()) . $state_filter_manual ?>">
  154. <?php
  155. if ($show_favicon || $f_active) { ?><img class="favicon" src="<?= $feed->favicon() ?>" alt="✇" loading="lazy" /><?php }
  156. ?><span class="title"><?= $feed->name() ?></span></a></li>
  157. <?php
  158. endforeach;
  159. ?>
  160. </ul>
  161. </li>
  162. <?php
  163. }
  164. endforeach;
  165. ?>
  166. <li class="tree-bottom"></li>
  167. </ul>
  168. </form>
  169. </nav>
  170. <a class="close-aside" href="#close">❌</a>
  171. <div id="first_load" class="loading"></div>
  172. <?php flush(); ?>
  173. <template id="dynamic_favicon_base">
  174. <?= file_get_contents(PUBLIC_PATH . '/themes/icons/favicon.svg') ?>
  175. </template>
  176. <template id="tag_config_template">
  177. <ul class="dropdown-menu">
  178. <li class="item">
  179. <a class="configure open-slider" href="<?= _url('tag', 'update', 'id', '------', 'from', Minz_Request::actionName()) ?>"><?= _t('gen.action.manage') ?></a>
  180. </li>
  181. </ul>
  182. <a class="dropdown-close" href="#close">❌</a>
  183. </template>
  184. <template id="feed_config_template">
  185. <ul class="dropdown-menu">
  186. <li class="item"><a href="<?= _url('index', $actual_view, 'get', 'f_------') ?>"><?= _t('gen.action.filter') ?></a></li>
  187. <?php if (FreshRSS_Auth::hasAccess()) { ?>
  188. <li class="item"><a href="<?= _url('stats', 'repartition', 'id', '------') ?>"><?= _t('index.menu.stats') ?></a></li>
  189. <?php } ?>
  190. <li class="item link website"><a target="_blank" rel="noreferrer" href="http://example.net/"><?= _t('gen.action.see_website') ?></a></li>
  191. <?php if (FreshRSS_Auth::hasAccess()) {
  192. $get = Minz_Request::paramString('get');
  193. if ($get === '') {
  194. $url = _url('subscription', 'feed', 'id', '------', 'from', $actual_view);
  195. } else {
  196. $url = _url('subscription', 'feed', 'id', '------', 'get', $get, 'from', $actual_view);
  197. }
  198. ?>
  199. <li class="item"><a class="configure open-slider" href="<?= $url ?>"><?= _t('gen.action.manage') ?></a></li>
  200. <li class="item"><a href="<?= _url('feed', 'actualize', 'id', '------') ?>"><?= _t('gen.action.actualize') ?></a></li>
  201. <li class="item">
  202. <?php $confirm = FreshRSS_Context::userConf()->reading_confirm ? 'confirm" disabled="disabled' : ''; ?>
  203. <button class="read_all as-link <?= $confirm ?>"
  204. form="mark-read-aside"
  205. formaction="<?= _url('entry', 'read', 'get', 'f_------') ?>"
  206. type="submit"><?= _t('index.menu.mark_feed_read') ?></button>
  207. </li>
  208. <?php } ?>
  209. </ul>
  210. <a class="dropdown-close" href="#close">❌</a>
  211. </template>