quick-settings: add submenu headers, empty states, and WiFi rescan

parent ae19d5c4
...@@ -67,6 +67,23 @@ ...@@ -67,6 +67,23 @@
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
box-shadow: 0px 0px 10px var(--headerbar-shade-color); box-shadow: 0px 0px 10px var(--headerbar-shade-color);
.submenu-header {
padding: 5px 8px;
.submenu-header-icon {
background: var(--accent-bg-color);
color: var(--accent-fg-color);
border-radius: 100%;
padding: 8px;
-gtk-icon-size: 24px;
}
.submenu-header-label {
font-weight: bold;
font-size: 1.4rem;
}
}
button { button {
margin: 2px 4px; margin: 2px 4px;
} }
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ximper-shell-notification-center 0.1.0\n" "Project-Id-Version: ximper-shell-notification-center 0.1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-27 23:10+0300\n" "POT-Creation-Date: 2026-03-31 19:15+0300\n"
"PO-Revision-Date: 2026-03-24 00:00+0300\n" "PO-Revision-Date: 2026-03-24 00:00+0300\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Russian\n" "Language-Team: Russian\n"
...@@ -113,20 +113,24 @@ msgstr "Отключён" ...@@ -113,20 +113,24 @@ msgstr "Отключён"
msgid "Not Connected" msgid "Not Connected"
msgstr "Не подключён" msgstr "Не подключён"
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:405 #: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:349
msgid "No networks found"
msgstr "Сети не найдены"
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:440
msgid "Password" msgid "Password"
msgstr "Пароль" msgstr "Пароль"
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:409 #: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:444
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:120 #: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:130
msgid "Connect" msgid "Connect"
msgstr "Подключить" msgstr "Подключить"
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:469 #: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:504
msgid "Connecting…" msgid "Connecting…"
msgstr "Подключение…" msgstr "Подключение…"
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:485 #: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:520
msgid "Network Settings" msgid "Network Settings"
msgstr "Настройки сети" msgstr "Настройки сети"
...@@ -138,7 +142,11 @@ msgstr "VPN" ...@@ -138,7 +142,11 @@ msgstr "VPN"
msgid "Disconnected" msgid "Disconnected"
msgstr "Отключён" msgstr "Отключён"
#: src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala:344 #: src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala:274
msgid "No VPN connections"
msgstr "Нет VPN-подключений"
#: src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala:348
msgid "VPN Settings" msgid "VPN Settings"
msgstr "Настройки VPN" msgstr "Настройки VPN"
...@@ -146,11 +154,15 @@ msgstr "Настройки VPN" ...@@ -146,11 +154,15 @@ msgstr "Настройки VPN"
msgid "Bluetooth" msgid "Bluetooth"
msgstr "Bluetooth" msgstr "Bluetooth"
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:119 #: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:91
msgid "Searching for devices…"
msgstr "Поиск устройств…"
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:129
msgid "Disconnect" msgid "Disconnect"
msgstr "Отключить" msgstr "Отключить"
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:162 #: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:172
msgid "Bluetooth Settings" msgid "Bluetooth Settings"
msgstr "Настройки Bluetooth" msgstr "Настройки Bluetooth"
......
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ximper-shell-notification-center\n" "Project-Id-Version: ximper-shell-notification-center\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-27 23:10+0300\n" "POT-Creation-Date: 2026-03-31 19:15+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -110,20 +110,24 @@ msgstr "" ...@@ -110,20 +110,24 @@ msgstr ""
msgid "Not Connected" msgid "Not Connected"
msgstr "" msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:405 #: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:349
msgid "No networks found"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:440
msgid "Password" msgid "Password"
msgstr "" msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:409 #: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:444
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:120 #: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:130
msgid "Connect" msgid "Connect"
msgstr "" msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:469 #: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:504
msgid "Connecting…" msgid "Connecting…"
msgstr "" msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:485 #: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:520
msgid "Network Settings" msgid "Network Settings"
msgstr "" msgstr ""
...@@ -135,7 +139,11 @@ msgstr "" ...@@ -135,7 +139,11 @@ msgstr ""
msgid "Disconnected" msgid "Disconnected"
msgstr "" msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala:344 #: src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala:274
msgid "No VPN connections"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala:348
msgid "VPN Settings" msgid "VPN Settings"
msgstr "" msgstr ""
...@@ -143,11 +151,15 @@ msgstr "" ...@@ -143,11 +151,15 @@ msgstr ""
msgid "Bluetooth" msgid "Bluetooth"
msgstr "" msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:119 #: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:91
msgid "Searching for devices…"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:129
msgid "Disconnect" msgid "Disconnect"
msgstr "" msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:162 #: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:172
msgid "Bluetooth Settings" msgid "Bluetooth Settings"
msgstr "" msgstr ""
......
...@@ -115,5 +115,51 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -115,5 +115,51 @@ namespace XimperShellNotificationCenter.Widgets {
public virtual void on_cc_visibility_change (bool visible) { public virtual void on_cc_visibility_change (bool visible) {
} }
protected void build_submenu_header (
Gtk.Box submenu_box,
Gtk.Button ?action_button = null) {
var header = new Gtk.Box (
Gtk.Orientation.HORIZONTAL, 8);
header.add_css_class ("submenu-header");
var header_icon =
new Gtk.Image.from_icon_name (
icon.icon_name);
header_icon.set_valign (Gtk.Align.CENTER);
header_icon.add_css_class (
"submenu-header-icon");
var header_label =
new Gtk.Label (title_label.get_text ());
header_label.add_css_class (
"submenu-header-label");
header_label.set_hexpand (true);
header_label.set_halign (Gtk.Align.START);
header.append (header_icon);
header.append (header_label);
if (action_button != null) {
action_button.add_css_class ("flat");
action_button.add_css_class ("circular");
header.append (action_button);
}
submenu_box.prepend (header);
}
protected void clear_submenu_content (
Gtk.Box submenu_box) {
for (var child =
submenu_box.get_first_child ();
child != null;) {
var next = child.get_next_sibling ();
if (!child.has_css_class (
"submenu-header")) {
submenu_box.remove (child);
}
child = next;
}
}
} }
} }
...@@ -78,6 +78,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -78,6 +78,7 @@ namespace XimperShellNotificationCenter.Widgets {
Gtk.Orientation.VERTICAL, 0); Gtk.Orientation.VERTICAL, 0);
box.add_css_class ("quick-settings-submenu"); box.add_css_class ("quick-settings-submenu");
build_submenu_header (box);
bt_proxy.start_discovery (); bt_proxy.start_discovery ();
build_device_list (box); build_device_list (box);
...@@ -85,6 +86,15 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -85,6 +86,15 @@ namespace XimperShellNotificationCenter.Widgets {
} }
private void build_device_list (Gtk.Box box) { private void build_device_list (Gtk.Box box) {
if (bt_proxy.devices.size == 0) {
var empty = new Gtk.Label (
_("Searching for devices…"));
empty.add_css_class ("dim-label");
empty.set_margin_top (8);
empty.set_margin_bottom (8);
box.append (empty);
}
foreach (var dev in bt_proxy.devices) { foreach (var dev in bt_proxy.devices) {
var row = new Gtk.Box ( var row = new Gtk.Box (
Gtk.Orientation.HORIZONTAL, 8); Gtk.Orientation.HORIZONTAL, 8);
......
...@@ -138,9 +138,12 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -138,9 +138,12 @@ namespace XimperShellNotificationCenter.Widgets {
public override Gtk.Widget ?create_submenu () { public override Gtk.Widget ?create_submenu () {
if (proxy == null) return null; if (proxy == null) return null;
var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); var box = new Gtk.Box (
Gtk.Orientation.VERTICAL, 0);
box.add_css_class ("quick-settings-submenu"); box.add_css_class ("quick-settings-submenu");
build_submenu_header (box);
string current = proxy.active_profile; string current = proxy.active_profile;
foreach (string name in profile_names) { foreach (string name in profile_names) {
......
...@@ -79,12 +79,8 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -79,12 +79,8 @@ namespace XimperShellNotificationCenter.Widgets {
active = any_active; active = any_active;
if (any_active && active_name != null) { if (any_active && active_name != null) {
icon.set_from_icon_name (
"network-vpn-symbolic");
set_subtitle (active_name); set_subtitle (active_name);
} else { } else {
icon.set_from_icon_name (
"network-vpn-symbolic");
set_subtitle (_("Disconnected")); set_subtitle (_("Disconnected"));
} }
} }
...@@ -248,6 +244,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -248,6 +244,7 @@ namespace XimperShellNotificationCenter.Widgets {
box.add_css_class ("quick-settings-submenu"); box.add_css_class ("quick-settings-submenu");
current_submenu = box; current_submenu = box;
build_submenu_header (box);
refresh_submenu.begin (); refresh_submenu.begin ();
return box; return box;
...@@ -261,19 +258,22 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -261,19 +258,22 @@ namespace XimperShellNotificationCenter.Widgets {
yield load_vpn_list (); yield load_vpn_list ();
if (current_submenu != null) { if (current_submenu != null) {
for (var child = clear_submenu_content (current_submenu);
current_submenu.get_first_child ();
child != null;) {
var next = child.get_next_sibling ();
current_submenu.remove (child);
child = next;
}
build_vpn_list (current_submenu); build_vpn_list (current_submenu);
} }
updating_submenu = false; updating_submenu = false;
} }
private void build_vpn_list (Gtk.Box box) { private void build_vpn_list (Gtk.Box box) {
if (vpn_list.size == 0) {
var empty = new Gtk.Label (
_("No VPN connections"));
empty.add_css_class ("dim-label");
empty.set_margin_top (8);
empty.set_margin_bottom (8);
box.append (empty);
}
foreach (var vpn in vpn_list) { foreach (var vpn in vpn_list) {
var row = new Gtk.Box ( var row = new Gtk.Box (
Gtk.Orientation.HORIZONTAL, 8); Gtk.Orientation.HORIZONTAL, 8);
...@@ -363,12 +363,17 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -363,12 +363,17 @@ namespace XimperShellNotificationCenter.Widgets {
box.append (btn); box.append (btn);
} }
private static string ?_settings_cmd = null;
private static bool _settings_checked = false;
private static string ?get_settings_command () { private static string ?get_settings_command () {
if (_settings_checked) return _settings_cmd;
_settings_checked = true;
if (Environment.find_program_in_path ( if (Environment.find_program_in_path (
"nm-connection-editor") != null) { "nm-connection-editor") != null) {
return "nm-connection-editor"; _settings_cmd = "nm-connection-editor";
} }
return null; return _settings_cmd;
} }
} }
} }
...@@ -136,6 +136,30 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -136,6 +136,30 @@ namespace XimperShellNotificationCenter.Widgets {
} }
} }
private Gtk.Button ?scan_button = null;
private async void rescan () {
if (scan_button != null) {
var spinner = new Gtk.Spinner ();
spinner.start ();
scan_button.set_child (spinner);
scan_button.set_sensitive (false);
}
wifi_dev_path =
yield nm_proxy.get_wifi_device ();
yield scan ();
Timeout.add (1000, () => {
if (scan_button != null) {
scan_button.set_child (
new Gtk.Image.from_icon_name (
"view-refresh-symbolic"));
scan_button.set_sensitive (true);
}
refresh_submenu.begin ();
return Source.REMOVE;
});
}
private async void scan () { private async void scan () {
if (wifi_dev_path == null) return; if (wifi_dev_path == null) return;
try { try {
...@@ -291,6 +315,14 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -291,6 +315,14 @@ namespace XimperShellNotificationCenter.Widgets {
box.add_css_class ("quick-settings-submenu"); box.add_css_class ("quick-settings-submenu");
current_submenu = box; current_submenu = box;
scan_button =
new Gtk.Button.from_icon_name (
"view-refresh-symbolic");
scan_button.clicked.connect (() => {
rescan.begin ();
});
build_submenu_header (box, scan_button);
refresh_submenu.begin (); refresh_submenu.begin ();
return box; return box;
...@@ -304,13 +336,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -304,13 +336,7 @@ namespace XimperShellNotificationCenter.Widgets {
var aps = yield get_access_points (); var aps = yield get_access_points ();
if (current_submenu != null) { if (current_submenu != null) {
for (var child = clear_submenu_content (current_submenu);
current_submenu.get_first_child ();
child != null;) {
var next = child.get_next_sibling ();
current_submenu.remove (child);
child = next;
}
build_ap_list (current_submenu, aps); build_ap_list (current_submenu, aps);
} }
updating_submenu = false; updating_submenu = false;
...@@ -318,6 +344,15 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -318,6 +344,15 @@ namespace XimperShellNotificationCenter.Widgets {
private void build_ap_list ( private void build_ap_list (
Gtk.Box box, ApInfo[] aps) { Gtk.Box box, ApInfo[] aps) {
if (aps.length == 0) {
var empty = new Gtk.Label (
_("No networks found"));
empty.add_css_class ("dim-label");
empty.set_margin_top (8);
empty.set_margin_bottom (8);
box.append (empty);
}
foreach (var ap in aps) { foreach (var ap in aps) {
var row = new Gtk.Box ( var row = new Gtk.Box (
Gtk.Orientation.HORIZONTAL, 8); Gtk.Orientation.HORIZONTAL, 8);
...@@ -504,12 +539,17 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -504,12 +539,17 @@ namespace XimperShellNotificationCenter.Widgets {
box.append (btn); box.append (btn);
} }
private static string ?_settings_cmd = null;
private static bool _settings_checked = false;
private static string ?get_settings_command () { private static string ?get_settings_command () {
if (_settings_checked) return _settings_cmd;
_settings_checked = true;
if (Environment.find_program_in_path ( if (Environment.find_program_in_path (
"nm-connection-editor") != null) { "nm-connection-editor") != null) {
return "nm-connection-editor"; _settings_cmd = "nm-connection-editor";
} }
return null; return _settings_cmd;
} }
// Connection methods // Connection methods
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment