Pārlūkot izejas kodu

Fix/Improved: Slider mobile (#4416)

* add close button, add content slider div

* add &ajax=1#slider to the links

* CSS

* fix showPW functionality

* open slider after received Ajax

* do not show empty slider

* RTL CSS

* fixed code smell

* improved: links prep via JS

* Redirect anchor

* enable #anchors in printuri()

* enable #slider when config was saved

* Active sliding via JS

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
maTh 3 gadi atpakaļ
vecāks
revīzija
2d807e06b1

+ 12 - 9
app/views/configure/queries.phtml

@@ -61,14 +61,17 @@
 	</form>
 </main>
 
-<?php $class = $this->displaySlider ? ' active' : ''; ?>
-<a href="#" id="close-slider" class="<?= $class ?>">
-	<?= _i('close') ?>
-</a>
+<?php $class = ($this->query != null) ? ' active' : ''; ?>
 <aside id="slider" class="scrollbar-thin<?= $class ?>">
-	<?php
-		if ($this->query != null) {
-			$this->renderHelper('configure/query');
-		}
-	?>
+<a class="toggle_aside" href="#close"><img class="icon" src="../themes/icons/close.svg" loading="lazy" alt="❌"></a>
+	<div id="slider-content">
+		<?php
+			if ($this->query != null) {
+				$this->renderHelper('configure/query');
+			}
+		?>
+	</div>
 </aside>
+<a href="#" id="close-slider">
+	<?= _i('close') ?>
+</a>

+ 11 - 7
app/views/extension/index.phtml

@@ -80,13 +80,17 @@
 </main>
 
 <?php $class = isset($this->extension) ? ' active' : ''; ?>
-<aside id="slider" class="scrollbar-thin<?= $class ?>">
-	<?php
-		if (isset($this->extension)) {
-			$this->renderHelper('extension/configure');
-		}
-	?>
+<?php $closelink = isset($this->extension) ? _url('extension', 'index') : ''; ?>
+<aside id="slider" class="scrollbar-thin">
+<a class="toggle_aside" href="<?= $closelink ?>#close"><img class="icon" src="../themes/icons/close.svg" loading="lazy" alt="❌"></a>
+	<div id="slider-content">
+		<?php
+			if (isset($this->extension)) {
+				$this->renderHelper('extension/configure');
+			}
+		?>
+	</div>
 </aside>
-<a href="#" id="close-slider" class="<?= $class ?>">
+<a href="#" id="close-slider">
 	<?= _i('close') ?>
 </a>

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

@@ -9,7 +9,7 @@
 		<a href="<?= _url('index', 'index', 'get', 'c_' . $this->category->id()) ?>"><?= _i('link') ?> <?= _t('gen.action.filter') ?></a>
 	</div>
 
-	<form method="post" action="<?= _url('subscription', 'category', 'id', $this->category->id()) ?>" autocomplete="off">
+	<form method="post" action="<?= _url('subscription', 'category', 'id', $this->category->id(), '#', 'slider') ?>" autocomplete="off">
 		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
 
 		<legend><?= _t('sub.category.information') ?></legend>

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

@@ -6,7 +6,7 @@
 		<a href="<?= $this->query->getUrl() ?>"><?= _i('link') ?> <?= _t('gen.action.filter') ?></a>
 	</div>
 
-	<form method="post" action="<?= _url('configure', 'query', 'id', $this->queryId) ?>" autocomplete="off">
+	<form method="post" action="<?= _url('configure', 'query', 'id', $this->queryId, '#', 'slider') ?>" autocomplete="off">
 		<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
 
 		<div class="form-group">

+ 8 - 8
app/views/helpers/feed/update.phtml

@@ -19,13 +19,13 @@
 	<?php
 	$from = Minz_Request::param('from');
 	if ($from === false) {
-		$url = _url('subscription', 'feed', 'id', $this->feed->id());
+		$url = _url('subscription', 'feed', 'id', $this->feed->id(), '#', 'slider');
 	} else {
 		$get = Minz_Request::param('get');
 		if (!$get) {
-			$url = _url('subscription', 'feed', 'id', $this->feed->id(), 'from', $from);
+			$url = _url('subscription', 'feed', 'id', $this->feed->id(), 'from', $from, '#', 'slider');
 		} else {
-			$url = _url('subscription', 'feed', 'id', $this->feed->id(), 'from', $from, 'get', $get);
+			$url = _url('subscription', 'feed', 'id', $this->feed->id(), 'from', $from, 'get', $get, '#', 'slider');
 		}
 	}
 	?>
@@ -256,7 +256,7 @@
 			<div class="group-controls">
 				<div class="stick">
 					<input type="text" value="<?= _t('sub.feed.number_entries', $nbEntries) ?>" disabled="disabled" />
-					<a class="btn" href="<?= _url('feed', 'actualize', 'id', $this->feed->id()) ?>">
+					<a class="btn" href="<?= _url('feed', 'actualize', 'id', $this->feed->id(), '#slider') ?>">
 						<?= _i('refresh') ?> <?= _t('gen.action.actualize') ?>
 					</a>
 				</div>
@@ -384,7 +384,7 @@
 			<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>
-				<button type="submit" class="btn btn-attention confirm" formmethod="post" formaction="<?= _url('feed', 'truncate', 'id', $this->feed->id()) ?>"><?= _t('gen.action.truncate') ?></button>
+				<button type="submit" class="btn btn-attention confirm" formmethod="post" formaction="<?= _url('feed', 'truncate', 'id', $this->feed->id(), '#slider') ?>"><?= _t('gen.action.truncate') ?></button>
 			</div>
 		</div>
 
@@ -491,7 +491,7 @@
 					<input type="text" name="path_entries" id="path_entries" class="w100" value="<?= $this->feed->pathEntries() ?>"
 						data-leave-validation="<?= $this->feed->pathEntries() ?>" placeholder="<?= _t('gen.short.blank_to_disable') ?>" />
 					<a id="popup-preview-selector" class="btn" href="<?=
-						_url('feed', 'contentSelectorPreview', 'id', $this->feed->id(), 'selector', 'selector-token') ?>"><?= _i('look') ?></a>
+						_url('feed', 'contentSelectorPreview', 'id', $this->feed->id(), 'selector', 'selector-token', '#slider') ?>"><?= _i('look') ?></a>
 				</div>
 				<p class="help"><?= _i('help') ?> <?= _t('sub.feed.css_help') ?></p>
 			</div>
@@ -589,13 +589,13 @@
 	<legend><?= _t('sub.feed.maintenance.title') ?></legend>
 	<div class="form-group">
 		<div class="group-controls">
-			<a class="btn btn-important" href="<?= _url('feed', 'clearCache', 'id', $this->feed->id()) ?>">
+			<a class="btn btn-important" href="<?= _url('feed', 'clearCache', 'id', $this->feed->id(), '#slider') ?>">
 				<?= _t('sub.feed.maintenance.clear_cache') ?>
 			</a>
 			<p class="help"><?= _i('help') ?> <?= _t('sub.feed.maintenance.clear_cache_help') ?></p>
 		</div>
 		<div class="group-controls">
-			<form method="post" action="<?= _url('feed', 'reload') ?>">
+			<form method="post" action="<?= _url('feed', 'reload', '#slider') ?>">
 				<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" />
 				<input type="hidden" name="id" value="<?= $this->feed->id() ?>" />
 				<button type="submit" class="btn btn-important">

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

@@ -261,6 +261,9 @@ $today = @strtotime('today');
 
 <?php $class = $this->displaySlider ? ' active' : ''; ?>
 <aside id="slider" class="scrollbar-thin<?= $class ?>">
+	<a class="toggle_aside" href="#close"><img class="icon" src="../themes/icons/close.svg" loading="lazy" alt="❌"></a>
+		<div id="slider-content">
+		</div>
 </aside>
 <a href="#" id="close-slider" class="<?= $class ?>">
 	<?= _i('close') ?>

+ 6 - 3
app/views/stats/idle.phtml

@@ -50,13 +50,16 @@
 	<?php } ?>
 </main>
 
-<?php $class = $this->displaySlider ? ' active' : ''; ?>
+<?php $class = isset($this->feed) ? ' active' : ''; ?>
 <aside id="slider" class="scrollbar-thin<?= $class ?>">
-	<?php
+	<a class="toggle_aside" href="#close"><img class="icon" src="../themes/icons/close.svg" loading="lazy" alt="❌"></a>
+	<div id="slider-content">
+		<?php
 		if (isset($this->feed)) {
 			$this->renderHelper('feed/update');
 		}
-	?>
+		?>
+	</div>
 </aside>
 <a href="#" id="close-slider" class="<?= $class ?>">
 	<?= _i('close') ?>

+ 12 - 9
app/views/subscription/index.phtml

@@ -78,16 +78,19 @@
 	</div>
 </main>
 
-<?php $class = $this->displaySlider ? ' active' : ''; ?>
+<?php $class = isset($this->feed) || isset($this->category) ? ' active' : ''; ?>
 <aside id="slider" class="scrollbar-thin<?= $class ?>">
-	<?php
-		if (isset($this->feed)) {
-			$this->renderHelper('feed/update');
-		} elseif (isset($this->category)) {
-			$this->renderHelper('category/update');
-		}
-	?>
+	<a class="toggle_aside" href="#close"><img class="icon" src="../themes/icons/close.svg" loading="lazy" alt="❌"></a>
+	<div id="slider-content">
+		<?php
+			if (isset($this->feed)) {
+				$this->renderHelper('feed/update');
+			} elseif (isset($this->category)) {
+				$this->renderHelper('category/update');
+			}
+		?>
+	</div>
 </aside>
-<a href="#" id="close-slider" class="<?= $class ?>">
+<a href="#" id="close-slider">
 	<?= _i('close') ?>
 </a>

+ 12 - 0
lib/Minz/Url.php

@@ -63,6 +63,7 @@ class Minz_Url {
 	private static function printUri($url, $encodage) {
 		$uri = '';
 		$separator = '?';
+		$anchor = '';
 
 		if ($encodage === 'html') {
 			$and = '&amp;';
@@ -70,6 +71,11 @@ class Minz_Url {
 			$and = '&';
 		}
 
+		if (!empty($url['params']['#'])) {
+			$anchor = '#' . ($encodage === 'html' ? htmlspecialchars($url['params']['#'], ENT_QUOTES, 'UTF-8') : $url['params']['#']);
+			unset($url['params']['#']);
+		}
+
 		if (isset($url['c'])
 		 && $url['c'] != Minz_Request::defaultControllerName()) {
 			$uri .= $separator . 'c=' . $url['c'];
@@ -91,6 +97,12 @@ class Minz_Url {
 			}
 		}
 
+		if (!empty($url['#'])) {
+			$uri .= '#' . ($encodage === 'html' ? htmlspecialchars($url['#'], ENT_QUOTES, 'UTF-8') : $url['#']);
+		}
+
+		$uri .= $anchor;
+
 		return $uri;
 	}
 

+ 9 - 5
p/scripts/extra.js

@@ -148,16 +148,20 @@ function open_slider_listener(ev) {
 	const a = ev.target.closest('.open-slider');
 	if (a) {
 		if (!context.ajax_loading) {
-			location.href = '#slider'; // close menu/dropdown
 			context.ajax_loading = true;
-
+			const slider = document.getElementById('slider');
+			const slider_content = document.getElementById('slider-content');
 			const req = new XMLHttpRequest();
-			req.open('GET', a.href + '&ajax=1', true);
+			slider_content.innerHTML = '';
+			slider.classList.add('sliding');
+			const ahref = a.href + '&ajax=1#slider';
+			req.open('GET', ahref, true);
 			req.responseType = 'document';
 			req.onload = function (e) {
-				const slider = document.getElementById('slider');
+				location.href = '#slider'; // close menu/dropdown
+				slider.classList.add('active');
 				slider.scrollTop = 0;
-				slider.innerHTML = this.response.body.innerHTML;
+				slider_content.innerHTML = this.response.body.innerHTML;
 				context.ajax_loading = false;
 				slider.dispatchEvent(freshrssSliderLoadEvent);
 			};

+ 32 - 17
p/themes/base-theme/template.css

@@ -1510,14 +1510,17 @@ br {
 	right: 0;
 	overflow: auto;
 	border-left: 1px solid #aaa;
-	transition: width 200ms linear;
 	z-index: 100;
 }
 
-#slider:target {
+#slider.active:target {
 	width: 750px;
 }
 
+#slider.sliding {
+	transition: width 200ms linear;
+}
+
 #close-slider {
 	position: fixed;
 	top: 0; bottom: 0;
@@ -1525,7 +1528,7 @@ br {
 	cursor: pointer;
 }
 
-#slider:target + #close-slider {
+#slider.active:target + #close-slider {
 	background: rgba(0, 0, 0, 0.2);
 	font-size: 0;
 	left: 0;
@@ -1536,7 +1539,7 @@ br {
 	display: none;
 }
 
-#slider:target + #close-slider img {
+#slider.active:target + #close-slider img {
 	padding: 0.5rem;
 	display: inline-block;
 	position: absolute;
@@ -1545,6 +1548,13 @@ br {
 	filter: grayscale(100%) brightness(2.5);
 }
 
+#slider-content .loader {
+	height: 90vh;
+	background-image: url('loader.gif');
+	background-repeat: no-repeat;
+	background-position: center;
+}
+
 /*=== SLIDESHOW */
 /*==============*/
 .slides {
@@ -1709,6 +1719,7 @@ input:checked + .slide-container .properties {
 .nav-login,
 .nav_menu .search,
 .aside .toggle_aside,
+#slider .toggle_aside,
 .nav_menu .toggle_aside,
 .configure .dropdown-header-close {
 	display: none;
@@ -1780,6 +1791,19 @@ input:checked + .slide-container .properties {
 		display: none;
 	}
 
+	.aside .toggle_aside,
+	#panel .close,
+	.dropdown-menu .toggle_aside,
+	#slider .toggle_aside {
+		background: #f6f6f6;
+		display: block;
+		width: 100%;
+		height: 50px;
+		border-bottom: 1px solid #ddd;
+		line-height: 50px;
+		text-align: center;
+	}
+
 	.form-group {
 		margin-bottom: 10px;
 	}
@@ -1950,9 +1974,7 @@ input:checked + .slide-container .properties {
 		height: 30px;
 	}
 
-	#slider.active {
-		left: 0;
-		top: 50px;
+	#slider.active:target {
 		width: 100%;
 	}
 
@@ -1960,21 +1982,14 @@ input:checked + .slide-container .properties {
 		display: initial;
 	}
 
-	#close-slider.active img {
+	#slider.active:target #close-slider img {
 		display: initial;
 		position: initial;
 		filter: initial;
 	}
 
-	#close-slider.active {
-		background: #f6f6f6;
-		display: block;
-		width: 100%;
-		height: 50px;
-		z-index: 10;
-		text-align: center;
-		line-height: 50px;
-		border-bottom: 1px solid #ddd;
+	#slider.active:target + #close-slider {
+		display: none;
 	}
 
 	.stat.half {

+ 32 - 17
p/themes/base-theme/template.rtl.css

@@ -1510,14 +1510,17 @@ br {
 	left: 0;
 	overflow: auto;
 	border-right: 1px solid #aaa;
-	transition: width 200ms linear;
 	z-index: 100;
 }
 
-#slider:target {
+#slider.active:target {
 	width: 750px;
 }
 
+#slider.sliding {
+	transition: width 200ms linear;
+}
+
 #close-slider {
 	position: fixed;
 	top: 0; bottom: 0;
@@ -1525,7 +1528,7 @@ br {
 	cursor: pointer;
 }
 
-#slider:target + #close-slider {
+#slider.active:target + #close-slider {
 	background: rgba(0, 0, 0, 0.2);
 	font-size: 0;
 	right: 0;
@@ -1536,7 +1539,7 @@ br {
 	display: none;
 }
 
-#slider:target + #close-slider img {
+#slider.active:target + #close-slider img {
 	padding: 0.5rem;
 	display: inline-block;
 	position: absolute;
@@ -1545,6 +1548,13 @@ br {
 	filter: grayscale(100%) brightness(2.5);
 }
 
+#slider-content .loader {
+	height: 90vh;
+	background-image: url('loader.gif');
+	background-repeat: no-repeat;
+	background-position: center;
+}
+
 /*=== SLIDESHOW */
 /*==============*/
 .slides {
@@ -1709,6 +1719,7 @@ input:checked + .slide-container .properties {
 .nav-login,
 .nav_menu .search,
 .aside .toggle_aside,
+#slider .toggle_aside,
 .nav_menu .toggle_aside,
 .configure .dropdown-header-close {
 	display: none;
@@ -1780,6 +1791,19 @@ input:checked + .slide-container .properties {
 		display: none;
 	}
 
+	.aside .toggle_aside,
+	#panel .close,
+	.dropdown-menu .toggle_aside,
+	#slider .toggle_aside {
+		background: #f6f6f6;
+		display: block;
+		width: 100%;
+		height: 50px;
+		border-bottom: 1px solid #ddd;
+		line-height: 50px;
+		text-align: center;
+	}
+
 	.form-group {
 		margin-bottom: 10px;
 	}
@@ -1950,9 +1974,7 @@ input:checked + .slide-container .properties {
 		height: 30px;
 	}
 
-	#slider.active {
-		right: 0;
-		top: 50px;
+	#slider.active:target {
 		width: 100%;
 	}
 
@@ -1960,21 +1982,14 @@ input:checked + .slide-container .properties {
 		display: initial;
 	}
 
-	#close-slider.active img {
+	#slider.active:target #close-slider img {
 		display: initial;
 		position: initial;
 		filter: initial;
 	}
 
-	#close-slider.active {
-		background: #f6f6f6;
-		display: block;
-		width: 100%;
-		height: 50px;
-		z-index: 10;
-		text-align: center;
-		line-height: 50px;
-		border-bottom: 1px solid #ddd;
+	#slider.active:target + #close-slider {
+		display: none;
 	}
 
 	.stat.half {