diff --git a/quickshell/Modals/Settings/SettingsSidebar.qml b/quickshell/Modals/Settings/SettingsSidebar.qml index a8972b2a6..5ae7482b7 100644 --- a/quickshell/Modals/Settings/SettingsSidebar.qml +++ b/quickshell/Modals/Settings/SettingsSidebar.qml @@ -382,7 +382,8 @@ Rectangle { "id": "greeter", "text": I18n.tr("Greeter"), "icon": "login", - "tabIndex": 31 + "tabIndex": 31, + "greeterOnly": true }, { "id": "power_sleep", @@ -411,7 +412,7 @@ Rectangle { ] function isItemVisible(item) { - if (item.dmsOnly && NetworkService.usingLegacy) + if (item.dmsOnly && !NetworkService.networkAvailable) return false; if (item.cupsOnly && !CupsService.cupsAvailable) return false; @@ -431,6 +432,8 @@ Rectangle { return false; if (item.updaterOnly && !SystemUpdateService.sysupdateAvailable) return false; + if (item.greeterOnly && !GreeterService.available) + return false; if (item.autostartOnly && !DesktopService.autostartAvailable) return false; return true; @@ -637,6 +640,7 @@ Rectangle { Component.onCompleted: { root._expandedIds = SessionData.settingsSidebarExpandedIds; root._collapsedIds = SessionData.settingsSidebarCollapsedIds; + GreeterService.refresh(); } StyledTextMetrics { diff --git a/quickshell/Modules/Settings/GreeterTab.qml b/quickshell/Modules/Settings/GreeterTab.qml index cf62bc4bd..9ed0173ea 100644 --- a/quickshell/Modules/Settings/GreeterTab.qml +++ b/quickshell/Modules/Settings/GreeterTab.qml @@ -207,7 +207,7 @@ Item { Process { id: greeterBinaryCheckProcess - command: ["sh", "-c", "test -f /usr/bin/dms-greeter || test -f /usr/local/bin/dms-greeter"] + command: ["sh", "-c", "command -v dms-greeter >/dev/null 2>&1"] running: false onExited: exitCode => { diff --git a/quickshell/Services/GreeterService.qml b/quickshell/Services/GreeterService.qml new file mode 100644 index 000000000..10305484b --- /dev/null +++ b/quickshell/Services/GreeterService.qml @@ -0,0 +1,27 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import Quickshell.Io + +Singleton { + id: root + + property bool available: false + + function refresh() { + detectProcess.running = true; + } + + Process { + id: detectProcess + + command: ["sh", "-c", "command -v dms-greeter >/dev/null 2>&1 || grep -qs dms-greeter /etc/greetd/config.toml"] + running: true + + onExited: exitCode => { + root.available = exitCode === 0; + } + } +} diff --git a/quickshell/Services/LegacyNetworkService.qml b/quickshell/Services/LegacyNetworkService.qml deleted file mode 100644 index f35e516db..000000000 --- a/quickshell/Services/LegacyNetworkService.qml +++ /dev/null @@ -1,627 +0,0 @@ -pragma Singleton -pragma ComponentBehavior: Bound - -import QtQuick -import Quickshell -import Quickshell.Io -import Quickshell.Networking -import qs.Common -import qs.Services - -Singleton { - id: root - readonly property var log: Log.scoped("LegacyNetworkService") - - property bool isActive: false - - readonly property string backend: Networking.backend === NetworkBackendType.NetworkManager ? "networkmanager" : "" - readonly property string primaryConnection: "" - - readonly property var allDevices: Networking.devices?.values ?? [] - - readonly property var wifiDevices: allDevices.filter(d => d.type === DeviceType.Wifi).map(d => ({ - "name": d.name - })) - readonly property var ethernetDevices: allDevices.filter(d => d.type === DeviceType.Wired).map(d => ({ - "name": d.name - })) - - property string wifiDeviceOverride: SessionData.wifiDeviceOverride || "" - - readonly property var wifiDevice: { - const list = allDevices.filter(d => d.type === DeviceType.Wifi); - if (wifiDeviceOverride) { - const match = list.find(d => d.name === wifiDeviceOverride); - if (match) { - return match; - } - } - return list[0] ?? null; - } - - readonly property var wiredDevice: allDevices.find(d => d.type === DeviceType.Wired) ?? null - - readonly property bool ethernetConnected: wiredDevice?.connected ?? false - readonly property string ethernetInterface: wiredDevice?.name ?? "" - property string ethernetIP: "" - readonly property string ethernetConnectionUuid: { - const net = wiredDevice?.network; - if (!net) { - return ""; - } - const settings = net.nmSettings; - return settings.length > 0 ? settings[0].uuid : ""; - } - readonly property var wiredConnections: [] - - readonly property bool wifiAvailable: wifiDevice !== null - readonly property bool wifiEnabled: Networking.wifiEnabled - readonly property string wifiInterface: wifiDevice?.name ?? "" - readonly property bool wifiConnected: wifiDevice?.connected ?? false - property string wifiIP: "" - readonly property string wifiDevicePath: wifiDevice?.name ?? "" - readonly property string activeAccessPointPath: "" - readonly property string connectingDevice: "" - - readonly property var connectedWifiNetwork: { - const dev = wifiDevice; - if (!dev) { - return null; - } - const list = dev.networks?.values ?? []; - for (const net of list) { - if (net.connected) { - return net; - } - } - return null; - } - - readonly property string currentWifiSSID: connectedWifiNetwork?.name ?? "" - readonly property int wifiSignalStrength: Math.round((connectedWifiNetwork?.signalStrength ?? 0) * 100) - readonly property string wifiConnectionUuid: { - const net = connectedWifiNetwork; - if (!net) { - return ""; - } - const settings = net.nmSettings; - return settings.length > 0 ? settings[0].uuid : ""; - } - - readonly property string networkStatus: { - if (ethernetConnected) { - return "ethernet"; - } - if (wifiConnected) { - return "wifi"; - } - return "disconnected"; - } - - readonly property string wifiSignalIcon: { - if (isConnecting) { - return "wifi"; - } - if (!wifiConnected || networkStatus !== "wifi") { - return "wifi_off"; - } - if (wifiSignalStrength >= 50) { - return "wifi"; - } - if (wifiSignalStrength >= 25) { - return "wifi_2_bar"; - } - return "wifi_1_bar"; - } - - readonly property var wifiNetworks: { - const dev = wifiDevice; - if (!dev) { - return []; - } - const list = dev.networks?.values ?? []; - const result = []; - const seen = new Set(); - for (const net of list) { - if (!net?.name || seen.has(net.name)) { - continue; - } - seen.add(net.name); - result.push({ - "ssid": net.name, - "signal": Math.round(net.signalStrength * 100), - "secured": net.security !== WifiSecurityType.Open, - "bssid": "", - "connected": net.connected, - "saved": net.known - }); - } - result.sort((a, b) => b.signal - a.signal); - return result; - } - - readonly property var savedConnections: wifiNetworks.filter(n => n.saved).map(n => ({ - "ssid": n.ssid, - "saved": true, - "outOfRange": false - })) - readonly property var savedWifiNetworks: savedConnections - readonly property int savedWifiStateApiVersion: 26 - readonly property var ssidToConnectionName: { - const map = {}; - for (const n of wifiNetworks) { - if (n.saved) { - map[n.ssid] = n.ssid; - } - } - return map; - } - - property string userPreference: "auto" - property bool isConnecting: false - property string connectingSSID: "" - property string connectionError: "" - property string lastConnectionError: "" - property string connectionStatus: "" - property bool passwordDialogShouldReopen: false - - readonly property bool isScanning: wifiDevice?.scannerEnabled ?? false - property bool autoScan: false - property bool autoRefreshEnabled: false - property bool wifiToggling: false - property bool changingPreference: false - property string targetPreference: "" - property string wifiPassword: "" - property string forgetSSID: "" - property int refCount: 0 - - property string networkInfoSSID: "" - property string networkInfoDetails: "" - property bool networkInfoLoading: false - property string networkWiredInfoUUID: "" - property string networkWiredInfoDetails: "" - property bool networkWiredInfoLoading: false - - signal networksUpdated - signal connectionChanged - - readonly property var lowPriorityCmd: ["nice", "-n", "19", "ionice", "-c3"] - - property var _pendingNetwork: null - property string _pendingSSID: "" - property bool _pendingWithPsk: false - - onWifiNetworksChanged: networksUpdated() - onNetworkStatusChanged: { - connectionChanged(); - refreshIPs(); - } - onCurrentWifiSSIDChanged: { - connectionChanged(); - refreshIPs(); - } - onEthernetInterfaceChanged: refreshIPs() - onWifiInterfaceChanged: refreshIPs() - onWifiEnabledChanged: { - if (wifiEnabled && autoScan && wifiDevice) { - wifiDevice.scannerEnabled = true; - } - if (wifiToggling) { - wifiToggling = false; - ToastService.showInfo(wifiEnabled ? I18n.tr("WiFi enabled") : I18n.tr("WiFi disabled")); - } - } - - Component.onCompleted: { - userPreference = SettingsData.networkPreference; - } - - Connections { - target: root._pendingNetwork - enabled: root._pendingNetwork !== null - - function onConnectionFailed(reason) { - root._handleConnectionFailed(reason); - } - - function onConnectedChanged() { - if (root._pendingNetwork?.connected) { - root._handleConnectionSuccess(); - } - } - } - - function activate() { - if (isActive) { - return; - } - isActive = true; - log.info("Activating..."); - refreshIPs(); - if (wifiDevice && wifiEnabled) { - wifiDevice.scannerEnabled = true; - } - } - - function addRef() { - refCount++; - if (refCount === 1) { - startAutoScan(); - } - } - - function removeRef() { - refCount = Math.max(0, refCount - 1); - if (refCount === 0) { - stopAutoScan(); - } - } - - function startAutoScan() { - autoScan = true; - autoRefreshEnabled = true; - if (wifiDevice && wifiEnabled) { - wifiDevice.scannerEnabled = true; - } - } - - function stopAutoScan() { - autoScan = false; - autoRefreshEnabled = false; - if (wifiDevice) { - wifiDevice.scannerEnabled = false; - } - } - - function scanWifi() { - if (!wifiDevice || !wifiEnabled) { - return; - } - wifiDevice.scannerEnabled = true; - } - - function scanWifiNetworks() { - scanWifi(); - } - - function _findNetworkBySSID(ssid) { - const dev = wifiDevice; - if (!dev) { - return null; - } - return dev.networks?.values?.find(n => n.name === ssid) ?? null; - } - - function _handleConnectionFailed(reason) { - const ssid = _pendingSSID; - let invalidPsk = false; - - switch (reason) { - case ConnectionFailReason.NoSecrets: - invalidPsk = _pendingWithPsk; - break; - case ConnectionFailReason.WifiAuthTimeout: - invalidPsk = true; - break; - } - - connectionStatus = invalidPsk ? "invalid_password" : "failed"; - connectionError = ConnectionFailReason.toString(reason); - lastConnectionError = connectionError; - passwordDialogShouldReopen = invalidPsk; - isConnecting = false; - connectingSSID = ""; - - if (invalidPsk) { - ToastService.showError(I18n.tr("Invalid password for %1").arg(ssid)); - } else { - ToastService.showError(I18n.tr("Failed to connect to %1").arg(ssid)); - } - - _pendingNetwork = null; - _pendingSSID = ""; - _pendingWithPsk = false; - } - - function _handleConnectionSuccess() { - const ssid = _pendingSSID; - connectionStatus = "connected"; - connectionError = ""; - isConnecting = false; - connectingSSID = ""; - passwordDialogShouldReopen = false; - - ToastService.showInfo(I18n.tr("Connected to %1").arg(ssid)); - - if (userPreference === "wifi" || userPreference === "auto") { - setConnectionPriority("wifi"); - } - - _pendingNetwork = null; - _pendingSSID = ""; - _pendingWithPsk = false; - } - - function connectToWifi(ssid, password = "", username = "", anonymousIdentity = "", domainSuffixMatch = "") { - if (isConnecting) { - return; - } - - const network = _findNetworkBySSID(ssid); - if (!network) { - log.warn("SSID not found in scan results:", ssid); - ToastService.showError(I18n.tr("Network not found"), ssid); - return; - } - - isConnecting = true; - connectingSSID = ssid; - connectionError = ""; - connectionStatus = "connecting"; - passwordDialogShouldReopen = false; - - _pendingNetwork = network; - _pendingSSID = ssid; - - if (password) { - const sec = network.security; - switch (sec) { - case WifiSecurityType.WpaPsk: - case WifiSecurityType.Wpa2Psk: - case WifiSecurityType.Sae: - _pendingWithPsk = true; - network.connectWithPsk(password); - return; - default: - log.warn("Security type not supported with PSK, falling back to connect():", WifiSecurityType.toString(sec)); - } - } - - _pendingWithPsk = false; - network.connect(); - } - - function disconnectWifi() { - if (!wifiDevice) { - return; - } - wifiDevice.disconnect(); - connectionStatus = ""; - ToastService.showInfo(I18n.tr("Disconnected from WiFi")); - } - - function forgetWifiNetwork(ssid) { - forgetSSID = ssid; - const network = _findNetworkBySSID(ssid); - if (network) { - network.forget(); - ToastService.showInfo(I18n.tr("Forgot network %1").arg(ssid)); - } else { - log.warn("Cannot forget, SSID not found:", ssid); - } - forgetSSID = ""; - } - - function toggleWifiRadio() { - if (wifiToggling) { - return; - } - wifiToggling = true; - Networking.wifiEnabled = !Networking.wifiEnabled; - } - - function enableWifiDevice() { - if (!Networking.wifiEnabled) { - Networking.wifiEnabled = true; - ToastService.showInfo(I18n.tr("WiFi enabled")); - } - } - - function setNetworkPreference(preference) { - userPreference = preference; - targetPreference = preference; - changingPreference = true; - SettingsData.set("networkPreference", preference); - setConnectionPriority(preference); - changingPreference = false; - targetPreference = ""; - } - - function setConnectionPriority(type) { - const wifiMetric = type === "wifi" ? 50 : 100; - const wiredMetric = type === "ethernet" ? 50 : 100; - - for (const device of allDevices) { - let metric = -1; - switch (device.type) { - case DeviceType.Wifi: - metric = wifiMetric; - break; - case DeviceType.Wired: - metric = wiredMetric; - break; - default: - continue; - } - - for (const net of device.networks?.values ?? []) { - for (const settings of net.nmSettings) { - settings.write({ - "ipv4": { - "route-metric": metric - }, - "ipv6": { - "route-metric": metric - } - }); - } - } - } - } - - function connectToWifiAndSetPreference(ssid, password, username = "", anonymousIdentity = "", domainSuffixMatch = "") { - connectToWifi(ssid, password, username, anonymousIdentity, domainSuffixMatch); - setNetworkPreference("wifi"); - } - - function toggleNetworkConnection(type) { - if (type !== "ethernet" || !wiredDevice) { - return; - } - if (ethernetConnected) { - wiredDevice.disconnect(); - } else if (wiredDevice.network) { - wiredDevice.network.connect(); - } - } - - function disconnectEthernetDevice(deviceName) { - for (const dev of allDevices) { - if (dev.type === DeviceType.Wired && dev.name === deviceName) { - dev.disconnect(); - return; - } - } - } - - function setWifiDeviceOverride(deviceName) { - SessionData.setWifiDeviceOverride(deviceName || ""); - if (wifiEnabled) { - scanWifi(); - } - } - - function setWifiAutoconnect(ssid, autoconnect) { - const network = _findNetworkBySSID(ssid); - if (!network) { - return; - } - for (const settings of network.nmSettings) { - settings.write({ - "connection": { - "autoconnect": autoconnect - } - }); - } - ToastService.showInfo(autoconnect ? I18n.tr("Autoconnect enabled") : I18n.tr("Autoconnect disabled")); - } - - function fetchNetworkInfo(ssid) { - networkInfoSSID = ssid; - networkInfoLoading = false; - - const network = _findNetworkBySSID(ssid); - if (!network) { - networkInfoDetails = "Network information not found or network not available."; - return; - } - - const signalPct = Math.round(network.signalStrength * 100); - const secLabel = WifiSecurityType.toString(network.security); - const statusPrefix = network.connected ? "● " : " "; - const statusSuffix = network.connected ? " (Connected)" : ""; - - let details = statusPrefix + signalPct + "%" + statusSuffix + "\\n"; - details += " Security: " + secLabel + "\\n"; - if (network.known) { - details += " Status: Saved network\\n"; - } - networkInfoDetails = details; - } - - function fetchWiredNetworkInfo(uuid) { - networkWiredInfoUUID = uuid; - networkWiredInfoLoading = false; - - const dev = wiredDevice; - if (!dev) { - networkWiredInfoDetails = "Network information not found or network not available."; - return; - } - - let details = ""; - details += "Interface: " + (dev.name || "-") + "\\n"; - details += "MAC Addr: " + (dev.address || "-") + "\\n"; - details += "Speed: " + (dev.linkSpeed || 0) + " Mb/s\\n\\n"; - - details += "IPv4 information:\\n"; - details += " IPv4 address: " + (ethernetIP || "-") + "\\n"; - - networkWiredInfoDetails = details; - } - - function getNetworkInfo(ssid) { - const network = wifiNetworks.find(n => n.ssid === ssid); - if (!network) { - return null; - } - return { - "ssid": network.ssid, - "signal": network.signal, - "secured": network.secured, - "saved": network.saved, - "connected": network.connected, - "bssid": network.bssid - }; - } - - function getWiredNetworkInfo(uuid) { - return { - "uuid": uuid - }; - } - - function refreshNetworkState() { - refreshIPs(); - } - - function connectToSpecificWiredConfig(uuid) { - } - - function submitCredentials(token, secrets, save) { - } - - function cancelCredentials(token) { - } - - function refreshIPs() { - getEthernetIP.running = false; - getWifiIP.running = false; - - if (ethernetInterface && ethernetConnected) { - getEthernetIP.command = lowPriorityCmd.concat(["ip", "-4", "addr", "show", ethernetInterface]); - getEthernetIP.running = true; - } else { - ethernetIP = ""; - } - - if (wifiInterface && wifiConnected) { - getWifiIP.command = lowPriorityCmd.concat(["ip", "-4", "addr", "show", wifiInterface]); - getWifiIP.running = true; - } else { - wifiIP = ""; - } - } - - Process { - id: getEthernetIP - running: false - stdout: StdioCollector { - onStreamFinished: { - const match = text.match(/inet (\d+\.\d+\.\d+\.\d+)/); - root.ethernetIP = match ? match[1] : ""; - } - } - } - - Process { - id: getWifiIP - running: false - stdout: StdioCollector { - onStreamFinished: { - const match = text.match(/inet (\d+\.\d+\.\d+\.\d+)/); - root.wifiIP = match ? match[1] : ""; - } - } - } -} diff --git a/quickshell/Services/NetworkService.qml b/quickshell/Services/NetworkService.qml index f734cceac..7c2ab2887 100644 --- a/quickshell/Services/NetworkService.qml +++ b/quickshell/Services/NetworkService.qml @@ -95,7 +95,6 @@ Singleton { signal connectionChanged signal credentialsNeeded(string token, string ssid, string setting, var fields, var hints, string reason, string connType, string connName, string vpnService, var fieldsInfo) - property bool usingLegacy: false property var activeService: null readonly property string socketPath: Quickshell.env("DMS_SOCKET") @@ -107,8 +106,7 @@ Singleton { Component.onCompleted: { log.info("Initializing..."); if (!socketPath || socketPath.length === 0) { - log.info("DMS_SOCKET not set, using LegacyNetworkService"); - useLegacyService(); + log.info("DMS_SOCKET not set, network backend unavailable"); return; } if (DMSNetworkService.networkAvailable) { @@ -116,11 +114,6 @@ Singleton { useDMSService(); return; } - if (DMSService.isConnected && DMSService.capabilities.length > 0) { - log.info("Network capability not available in DMS, using LegacyNetworkService"); - useLegacyService(); - return; - } log.debug("DMS_SOCKET found, waiting for capabilities..."); } @@ -131,30 +124,16 @@ Singleton { if (!activeService && DMSNetworkService.networkAvailable) { log.info("Network capability detected, using DMSNetworkService"); useDMSService(); - } else if (!activeService && !DMSNetworkService.networkAvailable && socketPath && socketPath.length > 0) { - log.info("Network capability not available in DMS, using LegacyNetworkService"); - useLegacyService(); } } } function useDMSService() { activeService = DMSNetworkService; - usingLegacy = false; log.info("Switched to DMSNetworkService, networkAvailable:", networkAvailable); connectSignals(); } - function useLegacyService() { - activeService = LegacyNetworkService; - usingLegacy = true; - log.info("Switched to LegacyNetworkService, networkAvailable:", networkAvailable); - if (LegacyNetworkService.activate) { - LegacyNetworkService.activate(); - } - connectSignals(); - } - function connectSignals() { if (activeService) { if (activeService.networksUpdated) { diff --git a/quickshell/Services/SettingsSearchService.qml b/quickshell/Services/SettingsSearchService.qml index 8de2c0233..ce9fa7836 100644 --- a/quickshell/Services/SettingsSearchService.qml +++ b/quickshell/Services/SettingsSearchService.qml @@ -42,9 +42,10 @@ Singleton { "keybindsAvailable": () => KeybindsService.available, "soundsAvailable": () => AudioService.soundsAvailable, "cupsAvailable": () => CupsService.cupsAvailable, - "networkNotLegacy": () => !NetworkService.usingLegacy, + "networkAvailable": () => NetworkService.networkAvailable, "dmsConnected": () => DMSService.isConnected && DMSService.apiVersion >= 23, - "matugenAvailable": () => Theme.matugenAvailable + "matugenAvailable": () => Theme.matugenAvailable, + "greeterAvailable": () => GreeterService.available }) Component.onCompleted: indexFile.reload() diff --git a/quickshell/translations/extract_settings_index.py b/quickshell/translations/extract_settings_index.py index 280ee9aa8..61105dba1 100755 --- a/quickshell/translations/extract_settings_index.py +++ b/quickshell/translations/extract_settings_index.py @@ -137,6 +137,10 @@ TAB_INDEX_MAP = { "BatteryTab.qml": 42, } +FILE_CONDITION_MAP = { + "GreeterTab.qml": "greeterAvailable", +} + TAB_CATEGORY_MAP = { 0: "Personalization", 1: "Time & Weather", @@ -385,7 +389,7 @@ def find_settings_components(content, filename, wrappers): description = extract_i18n_string(desc_raw) visible_raw = extract_property(block, "visible") - condition_key = None + condition_key = FILE_CONDITION_MAP.get(filename) if visible_raw: if "CompositorService.isNiri" in visible_raw: condition_key = "isNiri" @@ -399,8 +403,8 @@ def find_settings_components(content, filename, wrappers): condition_key = "soundsAvailable" elif "CupsService.cupsAvailable" in visible_raw: condition_key = "cupsAvailable" - elif "NetworkService.usingLegacy" in visible_raw: - condition_key = "networkNotLegacy" + elif "NetworkService.networkAvailable" in visible_raw: + condition_key = "networkAvailable" elif "DMSService.isConnected" in visible_raw: condition_key = "dmsConnected" elif "Theme.matugenAvailable" in visible_raw: @@ -455,6 +459,7 @@ def parse_tabs_from_sidebar(sidebar_file): ("shortcutsOnly", "keybindsAvailable"), ("soundsOnly", "soundsAvailable"), ("cupsOnly", "cupsAvailable"), + ("greeterOnly", "greeterAvailable"), ("dmsOnly", "dmsConnected"), ("hyprlandNiriOnly", "isHyprlandOrNiri"), ("clipboardOnly", "dmsConnected"), diff --git a/quickshell/translations/settings_search_index.json b/quickshell/translations/settings_search_index.json index a9ba21753..e362b2d1f 100644 --- a/quickshell/translations/settings_search_index.json +++ b/quickshell/translations/settings_search_index.json @@ -7789,7 +7789,8 @@ "typography" ], "icon": "palette", - "description": "Font used on the login screen" + "description": "Font used on the login screen", + "conditionKey": "greeterAvailable" }, { "section": "greeterAuth", @@ -7813,7 +7814,8 @@ "write" ], "icon": "fingerprint", - "description": "DMS removes its managed block from /etc/pam.d/greetd and stops write services" + "description": "DMS removes its managed block from /etc/pam.d/greetd and stops write services", + "conditionKey": "greeterAvailable" }, { "section": "greeterAutoLogin", @@ -7846,7 +7848,8 @@ "unlock", "until" ], - "description": "Skip the greeter password after boot until you sign out. Lock screen unlock is unchanged. Takes effect on the next reboot after sync." + "description": "Skip the greeter password after boot until you sign out. Lock screen unlock is unchanged. Takes effect on the next reboot after sync.", + "conditionKey": "greeterAvailable" }, { "section": "greeterBehavior", @@ -7865,7 +7868,8 @@ "session" ], "icon": "history", - "description": "Pre-select the last used session on the greeter" + "description": "Pre-select the last used session on the greeter", + "conditionKey": "greeterAvailable" }, { "section": "greeterLockDateFormat", @@ -7881,7 +7885,8 @@ "login", "screen" ], - "description": "Format the date on the login screen" + "description": "Format the date on the login screen", + "conditionKey": "greeterAvailable" }, { "section": "greeterDeps", @@ -7896,7 +7901,8 @@ "greeter", "login" ], - "icon": "extension" + "icon": "extension", + "conditionKey": "greeterAvailable" }, { "section": "greeterEnableFprint", @@ -7912,7 +7918,8 @@ "greetd", "greeter", "login" - ] + ], + "conditionKey": "greeterAvailable" }, { "section": "greeterEnableU2f", @@ -7929,7 +7936,8 @@ "login", "security", "u2f" - ] + ], + "conditionKey": "greeterAvailable" }, { "section": "_tab_31", @@ -7942,7 +7950,8 @@ "greeter", "login" ], - "icon": "login" + "icon": "login", + "conditionKey": "greeterAvailable" }, { "section": "greeterFontFamily", @@ -7958,7 +7967,8 @@ "screen", "typography" ], - "description": "Font used on the login screen" + "description": "Font used on the login screen", + "conditionKey": "greeterAvailable" }, { "section": "greeterRememberLastSession", @@ -7975,7 +7985,8 @@ "select", "session" ], - "description": "Pre-select the last used session on the greeter" + "description": "Pre-select the last used session on the greeter", + "conditionKey": "greeterAvailable" }, { "section": "greeterRememberLastUser", @@ -7994,7 +8005,8 @@ "user", "username" ], - "description": "Pre-fill the last successful username on the greeter" + "description": "Pre-fill the last successful username on the greeter", + "conditionKey": "greeterAvailable" }, { "section": "greeterStatus", @@ -8008,7 +8020,8 @@ "login", "status" ], - "icon": "info" + "icon": "info", + "conditionKey": "greeterAvailable" }, { "section": "greeterPamExternallyManaged", @@ -8032,7 +8045,8 @@ "system", "write" ], - "description": "DMS removes its managed block from /etc/pam.d/greetd and stops write services" + "description": "DMS removes its managed block from /etc/pam.d/greetd and stops write services", + "conditionKey": "greeterAvailable" }, { "section": "muxType", @@ -8588,7 +8602,7 @@ "user", "users" ], - "description": "Add the new user to the %1 group so they can run dms greeter sync --profile." + "description": "Add the new user to the %1 group so they can run dms-greeter sync --profile." }, { "section": "createUser",