Просмотр исходного кода

Improve consistency of slider behavior after submitting form (#8612)

Closes https://github.com/FreshRSS/FreshRSS/issues/8529

* Preserve `error` parameter after submitting form in subscription management
Inverle 2 недель назад
Родитель
Сommit
815b97017b

+ 3 - 1
app/Controllers/categoryController.php

@@ -174,7 +174,9 @@ class FreshRSS_category_Controller extends FreshRSS_ActionController {
 
 			invalidateHttpCache();
 
-			$url_redirect = ['c' => 'subscription', 'params' => ['id' => $id, 'type' => 'category']];
+			$from = Minz_Request::paramString('from');
+			$prev_controller = $from === 'update' ? 'category' : 'subscription';
+			$url_redirect = ['c' => $prev_controller, 'a' => $from, 'params' => ['id' => $id, 'type' => 'category']];
 			if (false !== $categoryDAO->updateCategory($id, $values)) {
 				Minz_Request::good(
 					_t('feedback.sub.category.updated'),

+ 1 - 1
app/Controllers/configureController.php

@@ -542,7 +542,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
 
 			Minz_Request::good(
 				_t('feedback.conf.updated'),
-				[ 'c' => 'configure', 'a' => 'queries', 'params' => ['id' => (string)$id] ],
+				[ 'c' => 'configure', 'a' => Minz_Request::paramStringNull('from') ?? 'queries', 'params' => ['id' => (string)$id] ],
 				showNotification: FreshRSS_Context::userConf()->good_notification_timeout > 0);
 		}
 

+ 11 - 4
app/Controllers/indexController.php

@@ -111,10 +111,17 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
 
 		$id = Minz_Request::paramInt('id');
 		if ($id !== 0) {
-			$view = Minz_Request::paramString('a');
-			$url_redirect = ['c' => 'subscription', 'a' => 'feed', 'params' => ['id' => (string)$id, 'from' => $view]];
-			Minz_Request::forward($url_redirect, true);
-			return;
+			if (Minz_Request::paramString('type') === 'tag') {
+				$tagDAO = FreshRSS_Factory::createTagDao();
+				$tag = $tagDAO->searchById($id);
+				$this->view->tag = $tag;
+			} else {
+				$feedDAO = FreshRSS_Factory::createFeedDao();
+				$feed = $feedDAO->searchById($id);
+				$this->view->feed = $feed;
+			}
+			$this->view->displaySlider = true;
+			$this->view->cfrom = Minz_Request::actionName();
 		}
 
 		try {

+ 6 - 3
app/Controllers/subscriptionController.php

@@ -375,13 +375,16 @@ class FreshRSS_subscription_Controller extends FreshRSS_ActionController {
 				case 'reader':
 					$get = Minz_Request::paramString('get');
 					if ($get !== '') {
-						$url_redirect = ['c' => 'index', 'a' => $from, 'params' => ['get' => $get]];
+						$url_redirect = ['c' => 'index', 'a' => $from, 'params' => ['id' => $id, 'get' => $get]];
 					} else {
-						$url_redirect = ['c' => 'index', 'a' => $from];
+						$url_redirect = ['c' => 'index', 'a' => $from, 'params' => ['id' => $id]];
 					}
 					break;
+				case 'index':
+					$url_redirect = ['c' => 'subscription', 'params' => ['id' => $id, 'error' => Minz_Request::paramBoolean('error') ? 1 : 0]];
+					break;
 				default:
-					$url_redirect = ['c' => 'subscription', 'params' => ['id' => $id]];
+					$url_redirect = ['c' => 'subscription', 'a' => 'feed', 'params' => ['id' => $id]];
 			}
 
 			if ($favicon_uploaded && !$resetFavicon) {

+ 13 - 1
app/Controllers/tagController.php

@@ -124,7 +124,14 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController {
 
 			invalidateHttpCache();
 
-			$url_redirect = ['c' => 'tag', 'a' => 'update', 'params' => ['id' => $id]];
+			$prev_controller = 'tag';
+			$from = Minz_Request::paramStringNull('from') ?? 'update';
+			$params = ['id' => $id];
+			if ($from === 'normal' || $from === 'reader') {
+				$prev_controller = 'index';
+				$params['type'] = 'tag';
+			}
+			$url_redirect = ['c' => $prev_controller, 'a' => $from, 'params' => $params];
 			if ($ok) {
 				Minz_Request::good(
 					_t('feedback.tag.updated'),
@@ -225,6 +232,11 @@ class FreshRSS_tag_Controller extends FreshRSS_ActionController {
 		}
 		$tagDAO = FreshRSS_Factory::createTagDao();
 		$this->view->tags = $tagDAO->listTags(precounts: true);
+		$id = Minz_Request::paramInt('id');
+		if ($id !== 0) {
+			$this->view->displaySlider = true;
+			$this->view->tag = $tagDAO->searchById($id);
+		}
 	}
 
 	public static function escapeForSearch(string $tag): string {

+ 1 - 0
app/Models/View.php

@@ -38,6 +38,7 @@ class FreshRSS_View extends Minz_View {
 	public array $labels;
 
 	// Subscriptions
+	public string $cfrom = '';
 	public bool $displaySlider = false;
 	public bool $load_ok;
 	public bool $onlyFeedsWithError;

+ 1 - 1
app/layout/aside_feed.phtml

@@ -173,7 +173,7 @@
 <template id="tag_config_template">
 	<ul class="dropdown-menu">
 		<li class="item">
-			<a class="configure open-slider" href="<?= _url('tag', 'update', 'id', '------') ?>"><?= _t('gen.action.manage') ?></a>
+			<a class="configure open-slider" href="<?= _url('tag', 'update', 'id', '------', 'from', Minz_Request::actionName()) ?>"><?= _t('gen.action.manage') ?></a>
 		</li>
 	</ul>
 	<a class="dropdown-close" href="#close">❌</a>

+ 13 - 1
app/views/helpers/category/update.phtml

@@ -15,7 +15,19 @@
 		<a href="<?= _url('index', 'index', 'get', 'c_' . $this->category->id()) ?>"><?= _i('link') ?> <?= _t('gen.action.filter') ?></a>
 	</div>
 
-	<form method="post" action="<?= _url('category', 'update', 'id', $this->category->id(), '#', 'slider') ?>" autocomplete="off" data-auto-leave-validation="1">
+	<?php
+		$from = Minz_Request::paramString('from');
+		$slider = ['#', 'slider'];
+		$ajax = Minz_Request::paramBoolean('ajax') || $this->displaySlider;
+		if (!$ajax) {
+			$from = 'update';
+			$slider = [];
+		} elseif ($from === '') {
+			$from = 'index';
+		}
+	?>
+
+	<form method="post" action="<?= _url('category', 'update', 'id', $this->category->id(), 'from', $from, ...$slider) ?>" autocomplete="off" data-auto-leave-validation="1">
 		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
 		<fieldset>
 			<legend><?= _t('sub.category.information') ?></legend>

+ 3 - 1
app/views/helpers/configure/query.phtml

@@ -4,6 +4,8 @@
 	if ($this->query === null) {
 		throw new FreshRSS_Context_Exception('Query not initialised!');
 	}
+
+	$ajax = Minz_Request::paramBoolean('ajax') || $this->displaySlider;
 ?>
 <div class="post">
 	<h2><?= $this->query->getName() ?></h2>
@@ -11,7 +13,7 @@
 		<a href="<?= $this->query->getUrl() ?>"><?= _i('link') ?> <?= _t('gen.action.filter') ?></a>
 	</div>
 
-	<form method="post" action="<?= _url('configure', 'query', 'id', $this->queryId, '#', 'slider') ?>" autocomplete="off" data-auto-leave-validation="1">
+	<form method="post" action="<?= _url('configure', 'query', 'id', $this->queryId, 'from', $ajax ? 'queries' : 'query', ...($ajax ? ['#', 'slider'] : [])) ?>" autocomplete="off" data-auto-leave-validation="1">
 		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
 
 		<div class="form-group">

+ 11 - 3
app/views/helpers/feed/update.phtml

@@ -24,14 +24,22 @@
 
 	<?php
 	$from = Minz_Request::paramString('from');
+	$slider = ['#', 'slider'];
+	$ajax = Minz_Request::paramBoolean('ajax') || $this->displaySlider;
+	if (!$ajax) {
+		$from = 'feed';
+		$slider = [];
+	} elseif ($from === '') {
+		$from = $this->cfrom ?: 'index';
+	}
 	if ($from === '') {
-		$url = _url('subscription', 'feed', 'id', $this->feed->id(), '#', 'slider');
+		$url = _url('subscription', 'feed', 'id', $this->feed->id(), ...$slider);
 	} else {
 		$get = Minz_Request::paramString('get');
 		if ($get === '') {
-			$url = _url('subscription', 'feed', 'id', $this->feed->id(), 'from', $from, '#', 'slider');
+			$url = _url('subscription', 'feed', 'id', $this->feed->id(), 'from', $from, 'error', Minz_Request::paramBoolean('error') ? 1 : 0, ...$slider);
 		} else {
-			$url = _url('subscription', 'feed', 'id', $this->feed->id(), 'from', $from, 'get', $get, '#', 'slider');
+			$url = _url('subscription', 'feed', 'id', $this->feed->id(), 'from', $from, 'get', $get, ...$slider);
 		}
 	}
 	?>

+ 73 - 0
app/views/helpers/tag/update.phtml

@@ -0,0 +1,73 @@
+<?php
+	declare(strict_types=1);
+	/** @var FreshRSS_View $this */
+
+	if ($this->tag === null) {
+		throw new FreshRSS_Context_Exception('Tag not initialised!');
+	}
+
+	$ajax = Minz_Request::paramBoolean('ajax') || $this->displaySlider;
+	$from = $ajax ? ($this->cfrom ?: Minz_Request::paramString('from')) : 'update';
+?>
+<div class="post">
+	<h2>
+		<?= $this->tag->name() ?>
+	</h2>
+
+	<div>
+		<a href="<?= _url('index', 'index', 'get', 't_' . $this->tag->id()) ?>"><?= _i('link') ?> <?= _t('gen.action.filter') ?></a>
+	</div>
+
+	<form method="post" action="<?= _url('tag', 'update', 'id', $this->tag->id(), 'from', $from, ...($ajax ? ['#', 'slider'] : [])) ?>" autocomplete="off" data-auto-leave-validation="1">
+		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
+
+		<fieldset>
+			<legend><?= _t('sub.category.information') ?></legend>
+			<div class="form-group">
+				<label class="group-name" for="name"><?= _t('sub.tag.name') ?></label>
+				<div class="group-controls">
+					<input type="text" name="name" id="name" value="<?= $this->tag->name() ?>" />
+				</div>
+			</div>
+
+			<div class="form-group form-actions">
+				<div class="group-controls">
+					<button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
+					<button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button>
+				</div>
+			</div>
+		</fieldset>
+
+		<fieldset>
+			<legend><?= _t('sub.feed.filteractions') ?></legend>
+			<div class="form-group">
+				<label class="group-name" for="filteractions_label"><?= _t('sub.tag.auto_label') ?></label>
+				<div class="group-controls">
+					<textarea name="filteractions_label" id="filteractions_label" class="w100"><?php
+						foreach ($this->tag->filtersAction('label') as $filterRead) {
+							echo htmlspecialchars($filterRead->toString(expandUserQueries: false), ENT_NOQUOTES, 'UTF-8') . PHP_EOL;
+						}
+					?></textarea>
+					<p class="help"><?= _i('help') ?> <?= _t('sub.feed.filteractions.help') ?></p>
+				</div>
+			</div>
+		</fieldset>
+
+		<div class="form-group form-actions">
+			<div class="group-controls">
+				<button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
+				<button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button>
+			</div>
+		</div>
+	</form>
+
+	<h3><?= _t('sub.title.delete_label') ?></h3>
+	<form id="delete_tag" method="post" action="<?= _url('tag', 'delete', 'id_tag', $this->tag->id()) ?>">
+		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
+		<div class="form-group form-actions">
+			<div class="group-controls">
+				<button type="submit" class="btn btn-attention confirm"><?= _t('gen.action.remove') ?></button>
+			</div>
+		</div>
+	</form>
+</div>

+ 10 - 0
app/views/index/normal.phtml

@@ -6,6 +6,8 @@ if (!Minz_Request::paramBoolean('ajax')) {
 	$this->partial('nav_menu');
 }
 
+$slider_feed = $this->feed;
+
 call_user_func($this->callbackBeforeEntries, $this);
 
 $last_transition = '';
@@ -192,6 +194,14 @@ $today = @strtotime('today');
 <aside id="slider" class="<?= $class ?>">
 	<a class="toggle_aside" href="#close"><?= _i('close') ?></a>
 		<div id="slider-content">
+			<?php
+				if (isset($this->tag)) {
+					$this->renderHelper('tag/update');
+				} elseif (isset($slider_feed)) {
+					$this->feed = $slider_feed;
+					$this->renderHelper('feed/update');
+				}
+			?>
 		</div>
 </aside>
 <a href="#close" id="close-slider" class="<?= $class ?>">

+ 10 - 0
app/views/index/reader.phtml

@@ -6,6 +6,8 @@ if (!Minz_Request::paramBoolean('ajax')) {
 	$this->partial('nav_menu');
 }
 
+$slider_feed = $this->feed;
+
 call_user_func($this->callbackBeforeEntries, $this);
 
 $lazyload = FreshRSS_Context::userConf()->lazyload;
@@ -66,6 +68,14 @@ $useKeepUnreadImportant = !FreshRSS_Context::isImportant() && !FreshRSS_Context:
 <aside id="slider" class="<?= $class ?>">
 	<a class="toggle_aside" href="#close"><?= _i('close') ?></a>
 	<div id="slider-content">
+		<?php
+			if (isset($this->tag)) {
+				$this->renderHelper('tag/update');
+			} elseif (isset($slider_feed)) {
+				$this->feed = $slider_feed;
+				$this->renderHelper('feed/update');
+			}
+		?>
 	</div>
 </aside>
 <a href="#close" id="close-slider" class="<?= $class ?>">

+ 1 - 1
app/views/subscription/index.phtml

@@ -62,7 +62,7 @@
 				?>
 				<li class="item feed<?= $error_class, $empty_class, $mute_class ?>" title="<?= $title ?>"
 					draggable="true" data-feed-id="<?= $feed->id() ?>" data-priority="<?= $feed->priority() ?>">
-					<a class="configure open-slider" href="<?= _url('subscription', 'feed', 'id', $feed->id()) ?>" title="<?= _t('gen.action.manage') ?>"><?= _i('configure') ?></a><?php
+					<a class="configure open-slider" href="<?= _url('subscription', 'feed', 'id', $feed->id(), 'error', $feed->inError() ? 1 : 0) ?>" title="<?= _t('gen.action.manage') ?>"><?= _i('configure') ?></a><?php
 					if (FreshRSS_Context::userConf()->show_favicons): ?><img class="favicon" src="<?= $feed->favicon() ?>" alt="✇" loading="lazy" /><?php
 					endif; ?><span class="item-title"><?= $feed->name() ?></span>
 				</li>

+ 1 - 1
app/views/tag/index.phtml

@@ -28,7 +28,7 @@
 	<ul id="tagsList" <?= (count($this->tags) > 11) ? 'class="listInColumns"' : '' ?>>
 	<?php foreach ($this->tags as $tag): ?>
 		<li>
-			<a href="<?= _url('tag', 'update', 'id', $tag->id()) ?>" class="configure open-slider" title="<?= _t('gen.action.manage') ?>"><?= _i('configure') ?></a>
+			<a href="<?= _url('tag', 'update', 'id', $tag->id(), 'from', 'index') ?>" class="configure open-slider" title="<?= _t('gen.action.manage') ?>"><?= _i('configure') ?></a>
 			<span class="item-name"><?= $tag->name() ?></span>
 		</li>
 	<?php endforeach; ?>

+ 9 - 70
app/views/tag/update.phtml

@@ -1,73 +1,12 @@
 <?php
-	declare(strict_types=1);
-	/** @var FreshRSS_View $this */
+declare(strict_types=1);
+/** @var FreshRSS_View $this */
 
-	if (!Minz_Request::paramBoolean('ajax')) {
-		$this->partial('aside_subscription');
-	}
-	if ($this->tag === null) {
-		throw new FreshRSS_Context_Exception('Tag not initialised!');
-	}
-?>
-<div class="post">
-	<h2>
-		<?= $this->tag->name() ?>
-	</h2>
+if (!Minz_Request::paramBoolean('ajax')) {
+	$this->partial('aside_subscription');
+}
+if ($this->tag === null) {
+	throw new FreshRSS_Context_Exception('Tag not initialised!');
+}
 
-	<div>
-		<a href="<?= _url('index', 'index', 'get', 't_' . $this->tag->id()) ?>"><?= _i('link') ?> <?= _t('gen.action.filter') ?></a>
-	</div>
-
-	<form method="post" action="<?= _url('tag', 'update', 'id', $this->tag->id(), '#', 'slider') ?>" autocomplete="off" data-auto-leave-validation="1">
-		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
-
-		<fieldset>
-			<legend><?= _t('sub.category.information') ?></legend>
-			<div class="form-group">
-				<label class="group-name" for="name"><?= _t('sub.tag.name') ?></label>
-				<div class="group-controls">
-					<input type="text" name="name" id="name" value="<?= $this->tag->name() ?>" />
-				</div>
-			</div>
-
-			<div class="form-group form-actions">
-				<div class="group-controls">
-					<button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
-					<button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button>
-				</div>
-			</div>
-		</fieldset>
-
-		<fieldset>
-			<legend><?= _t('sub.feed.filteractions') ?></legend>
-			<div class="form-group">
-				<label class="group-name" for="filteractions_label"><?= _t('sub.tag.auto_label') ?></label>
-				<div class="group-controls">
-					<textarea name="filteractions_label" id="filteractions_label" class="w100"><?php
-						foreach ($this->tag->filtersAction('label') as $filterRead) {
-							echo htmlspecialchars($filterRead->toString(expandUserQueries: false), ENT_NOQUOTES, 'UTF-8') . PHP_EOL;
-						}
-					?></textarea>
-					<p class="help"><?= _i('help') ?> <?= _t('sub.feed.filteractions.help') ?></p>
-				</div>
-			</div>
-		</fieldset>
-
-		<div class="form-group form-actions">
-			<div class="group-controls">
-				<button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button>
-				<button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button>
-			</div>
-		</div>
-	</form>
-
-	<h3><?= _t('sub.title.delete_label') ?></h3>
-	<form id="delete_tag" method="post" action="<?= _url('tag', 'delete', 'id_tag', $this->tag->id()) ?>">
-		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
-		<div class="form-group form-actions">
-			<div class="group-controls">
-				<button type="submit" class="btn btn-attention confirm"><?= _t('gen.action.remove') ?></button>
-			</div>
-		</div>
-	</form>
-</div>
+$this->renderHelper('tag/update');

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

@@ -2069,6 +2069,7 @@ html.slider-active {
 #slider.active:target {
 	width: 750px;
 	box-shadow: -3px 3px 5px var(--frss-box-shadow-color-transparent);
+	outline: none;
 }
 
 #slider.sliding {

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

@@ -2069,6 +2069,7 @@ html.slider-active {
 #slider.active:target {
 	width: 750px;
 	box-shadow: 3px 3px 5px var(--frss-box-shadow-color-transparent);
+	outline: none;
 }
 
 #slider.sliding {