4
0
Эх сурвалжийг харах

New links in transitions and jump to next transition (#8294)

Easier to explain graphically:

<img width="408" height="266" alt="image" src="https://github.com/user-attachments/assets/0e3724a1-155b-4a87-89b3-cfe8a18cb100" />

The jump to next section ⏭ works when the sorting criterion is a date.

Need https://github.com/FreshRSS/FreshRSS/pull/8293
Alexandre Alapetite 3 сар өмнө
parent
commit
4b6127ee04

+ 34 - 3
app/Controllers/indexController.php

@@ -52,10 +52,9 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
 
 	/**
 	 * Content for displaying a transition between entries when sorting by specific criteria.
-	 * @param 'id'|'c.name'|'date'|'f.name'|'link'|'title'|'rand'|'lastUserModified'|'length' $sort
 	 */
-	public static function transition(FreshRSS_Entry $entry, string $sort): string {
-		return match ($sort) {
+	public static function transition(FreshRSS_Entry $entry): string {
+		return match (FreshRSS_Context::$sort) {
 			'id' => _t('index.feed.received' . self::dayRelative($entry->dateAdded(raw: true), mayBeFuture: false)) .
 				' — ' . timestamptodate($entry->dateAdded(raw: true), hour: false),
 			'date' => _t('index.feed.published' . self::dayRelative($entry->date(raw: true), mayBeFuture: true)) .
@@ -68,6 +67,38 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
 		};
 	}
 
+	/**
+	 * Produce a hyperlink to the next transition of entries.
+	 */
+	public static function transitionLink(FreshRSS_Entry $entry, int $offset = 0): string {
+		if (in_array(FreshRSS_Context::$sort, ['c.name', 'f.name'], true)) {
+			return Minz_Url::display(Minz_Request::modifiedCurrentRequest([
+				'get' => match (FreshRSS_Context::$sort) {
+					'c.name' => 'c_' . ($entry->feed()?->category()?->id() ?? '0'),
+					'f.name' => 'f_' . ($entry->feed()?->id() ?? '0'),
+				},
+			]));
+		}
+		$operator = match (FreshRSS_Context::$sort) {
+			'id' => 'date',
+			'date' => 'pubdate',
+			'lastUserModified' => 'userdate',
+			default => throw new InvalidArgumentException('Unsupported sort criterion for transition: ' . FreshRSS_Context::$sort),
+		};
+		$offset = FreshRSS_Context::$order === 'ASC' ? $offset : -$offset;
+		$timestamp = match (FreshRSS_Context::$sort) {
+			'id' => $entry->dateAdded(raw: true),
+			'date' => $entry->date(raw: true),
+			'lastUserModified' => $entry->lastUserModified(),
+			default => throw new InvalidArgumentException('Unsupported sort criterion for transition: ' . FreshRSS_Context::$sort),
+		};
+		$searchString = $operator . ':' . ($offset < 0 ? '/' : '') . date('Y-m-d', $timestamp + ($offset * 86400)) . ($offset > 0 ? '/' : '');
+		return Minz_Url::display(Minz_Request::modifiedCurrentRequest([
+			'search' => FreshRSS_Context::$search->getRawInput() === '' ? $searchString :
+				FreshRSS_Context::$search->enforce(new FreshRSS_Search($searchString))->__toString(),
+			]));
+	}
+
 	/**
 	 * This action displays the normal view of FreshRSS.
 	 */

+ 5 - 2
app/views/index/normal.phtml

@@ -59,14 +59,17 @@ $today = @strtotime('today');
 			$this->entry->feed() ?? FreshRSS_Feed::default();
 		$this->entry->_feed($this->feed);
 
-		if ($last_transition !== ($transition = FreshRSS_index_Controller::transition($this->entry, FreshRSS_Context::$sort))) {
+		if ($last_transition !== ($transition = FreshRSS_index_Controller::transition($this->entry))) {
 			$last_transition = $transition;
 			?><div class="transition">
 			<span class="transition-value">
 				<?php if (FreshRSS_Context::$sort === 'f.name' && FreshRSS_Context::userConf()->show_favicons): ?>
 				<img class="favicon" src="<?= $this->feed->favicon() ?>" alt="✇" loading="lazy" />
 				<?php endif;?>
-				<?= $transition ?>
+				<a href="<?= FreshRSS_index_Controller::transitionLink($this->entry) ?>"><?= $transition ?></a>
+				<?php if (in_array(FreshRSS_Context::$sort, ['id', 'date', 'lastUserModified'], true)): ?>
+					<a class="transition-next" href="<?= FreshRSS_index_Controller::transitionLink($this->entry, offset: 1) ?>">⏭</a>
+				<?php endif; ?>
 			</span>
 			<span class="name"><?= FreshRSS_Context::$name ?></span>
 			</div><?php

+ 1 - 0
lib/Minz/Request.php

@@ -214,6 +214,7 @@ class Minz_Request {
 		if (null !== $extraParams) {
 			$currentRequest['params'] = array_merge($currentRequest['params'], $extraParams);
 		}
+		unset($currentRequest['params']['rid']);
 		return $currentRequest;
 	}
 

+ 9 - 0
p/themes/base-theme/frss.css

@@ -1418,6 +1418,10 @@ input[type="search"] {
 	background: inherit;
 }
 
+.transition a, .transition a:hover {
+	color: inherit;
+}
+
 .transition .name {
 	position: absolute;
 	right: 0;
@@ -1427,6 +1431,11 @@ input[type="search"] {
 	text-overflow: ellipsis;
 }
 
+.transition-next {
+	margin-left: .5em;
+	opacity: 0.5;
+}
+
 /*=== Feed article header and footer */
 .flux_header {
 	background: inherit;

+ 9 - 0
p/themes/base-theme/frss.rtl.css

@@ -1418,6 +1418,10 @@ input[type="search"] {
 	background: inherit;
 }
 
+.transition a, .transition a:hover {
+	color: inherit;
+}
+
 .transition .name {
 	position: absolute;
 	left: 0;
@@ -1427,6 +1431,11 @@ input[type="search"] {
 	text-overflow: ellipsis;
 }
 
+.transition-next {
+	margin-right: .5em;
+	opacity: 0.5;
+}
+
 /*=== Feed article header and footer */
 .flux_header {
 	background: inherit;