Compare commits
17 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
ab5016c9bc |
|||
|
|
9d96345347 | ||
|
|
0ddcc56e20 | ||
|
|
ed30418b47 | ||
|
028d43f0ba |
|||
|
|
c5fe285571 | ||
|
|
63cf240c0e | ||
|
|
4346efe1b4 | ||
|
|
14a6c5fd9a | ||
|
7364ba7c37 |
|||
|
|
82b6a9d129 | ||
|
5ee9ae7125 |
|||
|
d31f5ea48c |
|||
|
13e261d341 |
|||
|
f930cdfcae |
|||
|
|
b6c879c90a | ||
|
|
3e37ef5026 |
6 changed files with 249 additions and 96 deletions
142
fix-treat-missing-interval-as-once.patch
Normal file
142
fix-treat-missing-interval-as-once.patch
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
From c9a7cbbdb385521f992d60539daa6a94d403d253 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Horstman <khaneliman12@gmail.com>
|
||||
Date: Mon, 9 Feb 2026 15:26:23 -0600
|
||||
Subject: [PATCH 1/2] fix(image): treat missing interval as once
|
||||
|
||||
PR #4390 enabled millisecond intervals but changed image interval parsing so a missing interval could resolve to 1ms. That creates a hot update loop and can spike CPU and destabilize rendering in drawer/group setups (issue #4835).
|
||||
|
||||
Use explicit semantics: missing, null, non-numeric, or <=0 interval is treated as "once" (max sleep), while positive numeric values still support ms precision with a 1ms floor. This keeps the intended feature (sub-second polling when requested) without defaulting to busy looping.
|
||||
|
||||
Also align waybar-image(5) docs with runtime behavior.
|
||||
|
||||
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
|
||||
---
|
||||
man/waybar-image.5.scd | 3 ++-
|
||||
src/modules/image.cpp | 27 ++++++++++++++++-----------
|
||||
2 files changed, 18 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/man/waybar-image.5.scd b/man/waybar-image.5.scd
|
||||
index 8c991265e..8be182a6f 100644
|
||||
--- a/man/waybar-image.5.scd
|
||||
+++ b/man/waybar-image.5.scd
|
||||
@@ -26,7 +26,8 @@ The *image* module displays an image from a path.
|
||||
*interval*: ++
|
||||
typeof: integer or float ++
|
||||
The interval (in seconds) to re-render the image. ++
|
||||
- Minimum value is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
|
||||
+ If set to a positive value, the minimum is 0.001 (1ms). Values smaller than 1ms will be set to 1ms. ++
|
||||
+ Zero or negative values are treated as "once". ++
|
||||
This is useful if the contents of *path* changes. ++
|
||||
If no *interval* is defined, the image will only be rendered once.
|
||||
|
||||
diff --git a/src/modules/image.cpp b/src/modules/image.cpp
|
||||
index 189deee6a..98bf3c46f 100644
|
||||
--- a/src/modules/image.cpp
|
||||
+++ b/src/modules/image.cpp
|
||||
@@ -14,22 +14,27 @@ waybar::modules::Image::Image(const std::string& id, const Json::Value& config)
|
||||
|
||||
size_ = config["size"].asInt();
|
||||
|
||||
- interval_ = config_["interval"] == "once"
|
||||
- ? std::chrono::milliseconds::max()
|
||||
- : std::chrono::milliseconds(std::max(
|
||||
- 1L, // Minimum 1ms due to millisecond precision
|
||||
- static_cast<long>(
|
||||
- (config_["interval"].isNumeric() ? config_["interval"].asDouble() : 0) *
|
||||
- 1000)));
|
||||
+ const auto once = std::chrono::milliseconds::max();
|
||||
+ if (!config_.isMember("interval") || config_["interval"].isNull() ||
|
||||
+ config_["interval"] == "once") {
|
||||
+ interval_ = once;
|
||||
+ } else if (config_["interval"].isNumeric()) {
|
||||
+ const auto interval_seconds = config_["interval"].asDouble();
|
||||
+ if (interval_seconds <= 0) {
|
||||
+ interval_ = once;
|
||||
+ } else {
|
||||
+ interval_ =
|
||||
+ std::chrono::milliseconds(std::max(1L, // Minimum 1ms due to millisecond precision
|
||||
+ static_cast<long>(interval_seconds * 1000)));
|
||||
+ }
|
||||
+ } else {
|
||||
+ interval_ = once;
|
||||
+ }
|
||||
|
||||
if (size_ == 0) {
|
||||
size_ = 16;
|
||||
}
|
||||
|
||||
- if (interval_.count() == 0) {
|
||||
- interval_ = std::chrono::milliseconds::max();
|
||||
- }
|
||||
-
|
||||
delayWorker();
|
||||
}
|
||||
|
||||
|
||||
From 3b478ee6a53f153f35f35729c26bf11b15f692a2 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Horstman <khaneliman12@gmail.com>
|
||||
Date: Mon, 9 Feb 2026 15:53:44 -0600
|
||||
Subject: [PATCH 2/2] chore: format
|
||||
|
||||
Some unrelated files failed formatting.
|
||||
|
||||
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
|
||||
---
|
||||
include/util/command.hpp | 4 +---
|
||||
src/modules/hyprland/window.cpp | 4 +---
|
||||
src/modules/hyprland/windowcount.cpp | 6 ++----
|
||||
3 files changed, 4 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/include/util/command.hpp b/include/util/command.hpp
|
||||
index 58c59a965..89d4372a1 100644
|
||||
--- a/include/util/command.hpp
|
||||
+++ b/include/util/command.hpp
|
||||
@@ -172,8 +172,6 @@ inline int32_t forkExec(const std::string& cmd, const std::string& output_name)
|
||||
return pid;
|
||||
}
|
||||
|
||||
-inline int32_t forkExec(const std::string& cmd) {
|
||||
- return forkExec(cmd, "");
|
||||
-}
|
||||
+inline int32_t forkExec(const std::string& cmd) { return forkExec(cmd, ""); }
|
||||
|
||||
} // namespace waybar::util::command
|
||||
diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp
|
||||
index e02a76917..197ed0920 100644
|
||||
--- a/src/modules/hyprland/window.cpp
|
||||
+++ b/src/modules/hyprland/window.cpp
|
||||
@@ -237,9 +237,7 @@ void Window::queryActiveWorkspace() {
|
||||
}
|
||||
}
|
||||
|
||||
-void Window::onEvent(const std::string& ev) {
|
||||
- dp.emit();
|
||||
-}
|
||||
+void Window::onEvent(const std::string& ev) { dp.emit(); }
|
||||
|
||||
void Window::setClass(const std::string& classname, bool enable) {
|
||||
if (enable) {
|
||||
diff --git a/src/modules/hyprland/windowcount.cpp b/src/modules/hyprland/windowcount.cpp
|
||||
index 487b00834..d881a3616 100644
|
||||
--- a/src/modules/hyprland/windowcount.cpp
|
||||
+++ b/src/modules/hyprland/windowcount.cpp
|
||||
@@ -38,7 +38,7 @@ WindowCount::~WindowCount() {
|
||||
|
||||
auto WindowCount::update() -> void {
|
||||
std::lock_guard<std::mutex> lg(mutex_);
|
||||
-
|
||||
+
|
||||
queryActiveWorkspace();
|
||||
|
||||
std::string format = config_["format"].asString();
|
||||
@@ -125,9 +125,7 @@ void WindowCount::queryActiveWorkspace() {
|
||||
}
|
||||
}
|
||||
|
||||
-void WindowCount::onEvent(const std::string& ev) {
|
||||
- dp.emit();
|
||||
-}
|
||||
+void WindowCount::onEvent(const std::string& ev) { dp.emit(); }
|
||||
|
||||
void WindowCount::setClass(const std::string& classname, bool enable) {
|
||||
if (enable) {
|
||||
2
sources
2
sources
|
|
@ -1 +1 @@
|
|||
SHA512 (waybar-0.11.0.tar.gz) = 6bd23a469205662e524e53dd8798c4dce6ed371e5106f34644540e2f89804181753814f74b45645185b933c43dc4a0eabb99633936433fdadc25a9cce58b06b0
|
||||
SHA512 (waybar-0.15.0.tar.gz) = f267c1ad2af1e4e74c3d8c966009a013c0b5c2849bfaf312b3b91e9d6f6856dc5466118f308208948118ea1de0cf70986cc3b592cc830f84d634b8518c5b8c9e
|
||||
|
|
|
|||
|
|
@ -1,82 +0,0 @@
|
|||
From 0006e4713ae19776528038b3242ded05db884ba5 Mon Sep 17 00:00:00 2001
|
||||
From: Aleksei Bavshin <alebastr89@gmail.com>
|
||||
Date: Sat, 14 Sep 2024 07:37:37 -0700
|
||||
Subject: [PATCH] fix(tray): revert ustring formatting changes
|
||||
|
||||
This reverts commit a4d31ab10d1630cb9104c695d7b777ca12468904.
|
||||
---
|
||||
src/modules/sni/item.cpp | 23 +++++++++--------------
|
||||
1 file changed, 9 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/src/modules/sni/item.cpp b/src/modules/sni/item.cpp
|
||||
index 8afb39fb3..6c4ec8c06 100644
|
||||
--- a/src/modules/sni/item.cpp
|
||||
+++ b/src/modules/sni/item.cpp
|
||||
@@ -104,11 +104,9 @@ void Item::proxyReady(Glib::RefPtr<Gio::AsyncResult>& result) {
|
||||
this->updateImage();
|
||||
|
||||
} catch (const Glib::Error& err) {
|
||||
- spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path,
|
||||
- std::string(err.what()));
|
||||
+ spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path, err.what());
|
||||
} catch (const std::exception& err) {
|
||||
- spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path,
|
||||
- std::string(err.what()));
|
||||
+ spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path, err.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,15 +124,14 @@ ToolTip get_variant<ToolTip>(const Glib::VariantBase& value) {
|
||||
result.text = get_variant<Glib::ustring>(container.get_child(2));
|
||||
auto description = get_variant<Glib::ustring>(container.get_child(3));
|
||||
if (!description.empty()) {
|
||||
- result.text = fmt::format("<b>{}</b>\n{}", std::string(result.text), std::string(description));
|
||||
+ result.text = fmt::format("<b>{}</b>\n{}", result.text, description);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
||||
try {
|
||||
- spdlog::trace("Set tray item property: {}.{} = {}", id.empty() ? bus_name : id,
|
||||
- std::string(name), get_variant<std::string>(value));
|
||||
+ spdlog::trace("Set tray item property: {}.{} = {}", id.empty() ? bus_name : id, name, value);
|
||||
|
||||
if (name == "Category") {
|
||||
category = get_variant<std::string>(value);
|
||||
@@ -179,12 +176,10 @@ void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
||||
}
|
||||
} catch (const Glib::Error& err) {
|
||||
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
||||
- id.empty() ? bus_name : id, std::string(name), get_variant<std::string>(value),
|
||||
- std::string(err.what()));
|
||||
+ id.empty() ? bus_name : id, name, value, err.what());
|
||||
} catch (const std::exception& err) {
|
||||
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
||||
- id.empty() ? bus_name : id, std::string(name), get_variant<std::string>(value),
|
||||
- std::string(err.what()));
|
||||
+ id.empty() ? bus_name : id, name, value, err.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,9 +221,9 @@ void Item::processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& _result) {
|
||||
|
||||
this->updateImage();
|
||||
} catch (const Glib::Error& err) {
|
||||
- spdlog::warn("Failed to update properties: {}", std::string(err.what()));
|
||||
+ spdlog::warn("Failed to update properties: {}", err.what());
|
||||
} catch (const std::exception& err) {
|
||||
- spdlog::warn("Failed to update properties: {}", std::string(err.what()));
|
||||
+ spdlog::warn("Failed to update properties: {}", err.what());
|
||||
}
|
||||
update_pending_.clear();
|
||||
}
|
||||
@@ -250,7 +245,7 @@ static const std::map<std::string_view, std::set<std::string_view>> signal2props
|
||||
|
||||
void Item::onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
||||
const Glib::VariantContainerBase& arguments) {
|
||||
- spdlog::trace("Tray item '{}' got signal {}", id, std::string(signal_name));
|
||||
+ spdlog::trace("Tray item '{}' got signal {}", id, signal_name);
|
||||
auto changed = signal2props.find(signal_name.raw());
|
||||
if (changed != signal2props.end()) {
|
||||
if (update_pending_.empty()) {
|
||||
|
|
@ -21,7 +21,7 @@ index 7e830285..e0310372 100644
|
|||
* {
|
||||
- /* `otf-font-awesome` is required to be installed for icons */
|
||||
- font-family: FontAwesome, Roboto, Helvetica, Arial, sans-serif;
|
||||
+ font-family: 'Noto Sans Mono', 'Font Awesome 6 Free', 'Font Awesome 6 Brands', monospace;
|
||||
+ font-family: 'Noto Sans Mono', 'Font Awesome 7 Free', 'Font Awesome 7 Brands', monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
|
|
|
|||
39
waybar-fedora-systemd-target-conflicts.patch
Normal file
39
waybar-fedora-systemd-target-conflicts.patch
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
From f67dcce02d02ef1dc8e78efc565647b6fe8656d4 Mon Sep 17 00:00:00 2001
|
||||
From: Aleksei Bavshin <alebastr89@gmail.com>
|
||||
Date: Sat, 4 Jul 2026 22:51:31 -0700
|
||||
Subject: [PATCH] systemd: declare known incompatible desktop environments
|
||||
|
||||
Waybar can be used with many different Wayland compositors. Some of
|
||||
those provide distinct user session targets, some aren't. The usual
|
||||
recommendation for the latter ones is to allow manual startup of the
|
||||
graphical-session.target and run "systemd --user start ..." command on
|
||||
init.
|
||||
|
||||
To ensure that all of the above is supported, we have to keep the
|
||||
service bound to the graphical-session.target. However, this may impact
|
||||
unrelated sessions on machines with multiple DEs installed.
|
||||
|
||||
Instead of listing dozens of supported Wayland compositors and breaking
|
||||
any configs that explicitly use graphical-session.target, keep a list
|
||||
of known sessions where Waybar is not wanted.
|
||||
---
|
||||
resources/waybar.service.in | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/resources/waybar.service.in b/resources/waybar.service.in
|
||||
index 18bac54c..9a54e5ba 100644
|
||||
--- a/resources/waybar.service.in
|
||||
+++ b/resources/waybar.service.in
|
||||
@@ -6,6 +6,9 @@ After=graphical-session.target
|
||||
Requisite=graphical-session.target
|
||||
|
||||
[Service]
|
||||
+ExecCondition=sh -c '[ -n "$WAYLAND_DISPLAY" ]'
|
||||
+# Known incompatible Wayland sessions
|
||||
+ExecCondition=/usr/lib/systemd/systemd-xdg-autostart-condition "" "GNOME:KDE:COSMIC:X-Cinnamon"
|
||||
ExecStart=@prefix@/bin/waybar
|
||||
ExecReload=kill -SIGUSR2 $MAINPID
|
||||
Restart=on-failure
|
||||
--
|
||||
2.55.0
|
||||
|
||||
78
waybar.spec
78
waybar.spec
|
|
@ -1,8 +1,6 @@
|
|||
%bcond wireplumber %[0%{?fedora} >= 40]
|
||||
|
||||
Name: waybar
|
||||
Version: 0.11.0
|
||||
Release: 1%{?dist}
|
||||
Version: 0.15.0
|
||||
Release: 6%{?dist}
|
||||
Summary: Highly customizable Wayland bar for Sway and Wlroots based compositors
|
||||
# Source files/overall project licensed as MIT, but
|
||||
# - BSL-1.0
|
||||
|
|
@ -23,8 +21,14 @@ Source: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
|
|||
# - Remove several modules from the config
|
||||
# - Switch font to monospace
|
||||
Patch: waybar-fedora-config-changes.patch
|
||||
# https://github.com/Alexays/Waybar/issues/3597
|
||||
Patch: %{url}/commit/0006e471.patch#/waybar-0.11.0-fix-std-bad_cast-in-tray-module.patch
|
||||
# Downstream changes to the systemd service:
|
||||
# - Check that the environment is Wayland and is not listed as unsupported
|
||||
Patch: waybar-fedora-systemd-target-conflicts.patch
|
||||
|
||||
# Fix for hot update loop that can spike CPU and
|
||||
# destabilize rendering in drawer/group setups
|
||||
# https://github.com/Alexays/Waybar/pull/4838
|
||||
Patch: fix-treat-missing-interval-as-once.patch
|
||||
|
||||
BuildRequires: gcc
|
||||
BuildRequires: gcc-c++
|
||||
|
|
@ -33,16 +37,16 @@ BuildRequires: scdoc
|
|||
BuildRequires: systemd-rpm-macros
|
||||
|
||||
BuildRequires: pkgconfig(catch2)
|
||||
BuildRequires: pkgconfig(date)
|
||||
BuildRequires: pkgconfig(dbusmenu-gtk3-0.4)
|
||||
BuildRequires: pkgconfig(fmt) >= 8.1.1
|
||||
BuildRequires: pkgconfig(gdk-pixbuf-2.0)
|
||||
BuildRequires: pkgconfig(gio-unix-2.0)
|
||||
BuildRequires: pkgconfig(gtk-layer-shell-0)
|
||||
BuildRequires: pkgconfig(gtk-layer-shell-0) >= 0.9.0
|
||||
BuildRequires: pkgconfig(gtkmm-3.0)
|
||||
BuildRequires: pkgconfig(jack)
|
||||
BuildRequires: pkgconfig(jsoncpp)
|
||||
BuildRequires: pkgconfig(libevdev)
|
||||
BuildRequires: pkgconfig(libgps)
|
||||
BuildRequires: pkgconfig(libinput)
|
||||
BuildRequires: pkgconfig(libmpdclient)
|
||||
BuildRequires: pkgconfig(libnl-3.0)
|
||||
|
|
@ -58,14 +62,17 @@ BuildRequires: pkgconfig(upower-glib)
|
|||
BuildRequires: pkgconfig(wayland-client)
|
||||
BuildRequires: pkgconfig(wayland-cursor)
|
||||
BuildRequires: pkgconfig(wayland-protocols)
|
||||
%if %{with wireplumber}
|
||||
BuildRequires: pkgconfig(wireplumber-0.5)
|
||||
%endif
|
||||
BuildRequires: pkgconfig(xkbregistry)
|
||||
|
||||
Enhances: sway
|
||||
%if 0%{?fedora} < 45
|
||||
Recommends: font(fontawesome6free)
|
||||
Recommends: font(fontawesome6brands)
|
||||
%else
|
||||
Recommends: font(fontawesome7free)
|
||||
Recommends: font(fontawesome7brands)
|
||||
%endif
|
||||
|
||||
%description
|
||||
%{summary}.
|
||||
|
|
@ -76,8 +83,7 @@ Recommends: font(fontawesome6brands)
|
|||
%build
|
||||
%meson \
|
||||
-Dcava=disabled \
|
||||
-Dsndio=disabled \
|
||||
%{!?with_wireplumber:-Dwireplumber=disabled}
|
||||
-Dsndio=disabled
|
||||
%meson_build
|
||||
|
||||
%install
|
||||
|
|
@ -104,6 +110,54 @@ Recommends: font(fontawesome6brands)
|
|||
%{_userunitdir}/%{name}.service
|
||||
|
||||
%changelog
|
||||
* Sun Aug 02 2026 Aleksei Bavshin <alebastr@fedoraproject.org> - 0.15.0-6
|
||||
- systemd: declare known incompatible desktop environments
|
||||
|
||||
* Fri Jul 17 2026 Fedora Release Engineering <releng@fedoraproject.org> - 0.15.0-5
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
|
||||
|
||||
* Thu Jun 25 2026 František Zatloukal <fzatlouk@redhat.com> - 0.15.0-4
|
||||
- Rebuilt for fmt/spdlog
|
||||
|
||||
* Wed May 27 2026 Jerry James <loganjerry@gmail.com> - 0.15.0-3
|
||||
- Migrate from FontAwesome 6.x to 7.x
|
||||
|
||||
* Sun Mar 22 2026 Björn Esser <besser82@fedoraproject.org> - 0.15.0-2
|
||||
- Rebuild (jsoncpp)
|
||||
|
||||
* Sat Feb 07 2026 Tomasz Hołubowicz <mail@alternateved.com> - 0.15.0-1
|
||||
- Update to 0.15.0
|
||||
|
||||
* Sat Jan 17 2026 Fedora Release Engineering <releng@fedoraproject.org> - 0.14.0-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild
|
||||
|
||||
* Wed Jan 14 2026 Jitka Plesnikova <jplesnik@redhat.com> - 0.14.0-2
|
||||
- Rebuild for new gpsd
|
||||
|
||||
* Sun Aug 10 2025 Aleksei Bavshin <alebastr@fedoraproject.org> - 0.14.0-1
|
||||
- Update to 0.14.0 (#2387223)
|
||||
|
||||
* Fri Jul 25 2025 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.0-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
|
||||
|
||||
* Sat Jul 12 2025 Aleksei Bavshin <alebastr@fedoraproject.org> - 0.13.0-2
|
||||
- Add patches for known 0.13.0 regressions (#2379698)
|
||||
|
||||
* Mon Jun 23 2025 Aleksei Bavshin <alebastr@fedoraproject.org> - 0.13.0-1
|
||||
- Update to 0.13.0 (rhbz#2374294)
|
||||
|
||||
* Thu Feb 27 2025 Björn Esser <besser82@fedoraproject.org> - 0.12.0-2
|
||||
- Rebuild (jsoncpp)
|
||||
|
||||
* Sun Feb 23 2025 Aleksei Bavshin <alebastr@fedoraproject.org> - 0.12.0-1
|
||||
- Update to 0.12.0 (#2346964)
|
||||
|
||||
* Sun Jan 19 2025 Fedora Release Engineering <releng@fedoraproject.org> - 0.11.0-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
|
||||
|
||||
* Tue Nov 26 2024 František Zatloukal <fzatlouk@redhat.com> - 0.11.0-2
|
||||
- Rebuilt for spdlog 1.15.0
|
||||
|
||||
* Sun Sep 15 2024 Aleksei Bavshin <alebastr@fedoraproject.org> - 0.11.0-1
|
||||
- Update to 0.11.0 (#2312394)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue