1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-08-01 19:18:28 -04:00

greeter: more repairs for standalone package, scrap LegacyNetworkService

This commit is contained in:
bbedward
2026-07-19 17:04:57 -04:00
parent fb65a23fac
commit dc4916b9e0
8 changed files with 75 additions and 672 deletions
@@ -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 {
+1 -1
View File
@@ -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 => {
+27
View File
@@ -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;
}
}
}
@@ -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] : "";
}
}
}
}
+1 -22
View File
@@ -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) {
@@ -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()
@@ -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"),
@@ -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",