1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-29 16:02:51 -05:00

bluez: fix disappearing popouts with modal maanger

This commit is contained in:
bbedward
2025-11-18 14:36:10 -05:00
parent 10639a5ead
commit 4e6f0d5e87
9 changed files with 106 additions and 50 deletions

View File

@@ -165,12 +165,11 @@ func (a *BluezAgent) DisplayPasskey(device dbus.ObjectPath, passkey uint32, ente
log.Infof("[BluezAgent] DisplayPasskey: device=%s, passkey=%06d, entered=%d", device, passkey, entered) log.Infof("[BluezAgent] DisplayPasskey: device=%s, passkey=%06d, entered=%d", device, passkey, entered)
if entered == 0 { if entered == 0 {
pk := passkey passkeyStr := strconv.FormatUint(uint64(passkey), 10)
_, err := a.promptFor(device, "display-passkey", []string{}, nil) _, err := a.promptFor(device, "display-passkey", []string{}, &passkeyStr)
if err != nil { if err != nil {
log.Warnf("[BluezAgent] DisplayPasskey acknowledgment failed: %v", err) log.Warnf("[BluezAgent] DisplayPasskey acknowledgment failed: %v", err)
} }
_ = pk
} }
return nil return nil
@@ -179,7 +178,8 @@ func (a *BluezAgent) DisplayPasskey(device dbus.ObjectPath, passkey uint32, ente
func (a *BluezAgent) RequestConfirmation(device dbus.ObjectPath, passkey uint32) *dbus.Error { func (a *BluezAgent) RequestConfirmation(device dbus.ObjectPath, passkey uint32) *dbus.Error {
log.Infof("[BluezAgent] RequestConfirmation: device=%s, passkey=%06d", device, passkey) log.Infof("[BluezAgent] RequestConfirmation: device=%s, passkey=%06d", device, passkey)
secrets, err := a.promptFor(device, "confirm", []string{"decision"}, nil) passkeyStr := strconv.FormatUint(uint64(passkey), 10)
secrets, err := a.promptFor(device, "confirm", []string{"decision"}, &passkeyStr)
if err != nil { if err != nil {
log.Warnf("[BluezAgent] RequestConfirmation failed: %v", err) log.Warnf("[BluezAgent] RequestConfirmation failed: %v", err)
return a.errorFrom(err) return a.errorFrom(err)

View File

@@ -354,21 +354,25 @@ func (m *Manager) handleDevicePropertiesChanged(path dbus.ObjectPath, changed ma
_, hasTrusted := changed["Trusted"] _, hasTrusted := changed["Trusted"]
if hasPaired { if hasPaired {
if paired, ok := pairedVar.Value().(bool); ok && paired { devicePath := string(path)
devicePath := string(path) if paired, ok := pairedVar.Value().(bool); ok {
_, wasPending := m.pendingPairings.LoadAndDelete(devicePath) if paired {
_, wasPending := m.pendingPairings.LoadAndDelete(devicePath)
if wasPending { if wasPending {
select { select {
case m.eventQueue <- func() { case m.eventQueue <- func() {
time.Sleep(300 * time.Millisecond) time.Sleep(300 * time.Millisecond)
log.Infof("[Bluetooth] Auto-connecting newly paired device: %s", devicePath) log.Infof("[Bluetooth] Auto-connecting newly paired device: %s", devicePath)
if err := m.ConnectDevice(devicePath); err != nil { if err := m.ConnectDevice(devicePath); err != nil {
log.Warnf("[Bluetooth] Auto-connect failed: %v", err) log.Warnf("[Bluetooth] Auto-connect failed: %v", err)
}
}:
default:
} }
}:
default:
} }
} else {
m.pendingPairings.Delete(devicePath)
} }
} }
} }

View File

@@ -136,7 +136,9 @@ Singleton {
popout.currentTabIndex = tabIndex popout.currentTabIndex = tabIndex
} }
ModalManager.closeAllModalsExcept(null) if (currentPopout !== popout) {
ModalManager.closeAllModalsExcept(null)
}
TrayMenuManager.closeAllMenus() TrayMenuManager.closeAllMenus()
if (justClosedSamePopout) { if (justClosedSamePopout) {

View File

@@ -217,6 +217,14 @@ Item {
id: polkitAuthModal id: polkitAuthModal
} }
BluetoothPairingModal {
id: bluetoothPairingModal
Component.onCompleted: {
PopoutService.bluetoothPairingModal = bluetoothPairingModal
}
}
property string lastCredentialsToken: "" property string lastCredentialsToken: ""
property var lastCredentialsTime: 0 property var lastCredentialsTime: 0

View File

@@ -18,6 +18,7 @@ DankModal {
property string passkeyInput: "" property string passkeyInput: ""
function show(pairingData) { function show(pairingData) {
console.log("BluetoothPairingModal.show() called:", JSON.stringify(pairingData))
token = pairingData.token || "" token = pairingData.token || ""
deviceName = pairingData.deviceName || "" deviceName = pairingData.deviceName || ""
deviceAddress = pairingData.deviceAddr || "" deviceAddress = pairingData.deviceAddr || ""
@@ -26,6 +27,7 @@ DankModal {
pinInput = "" pinInput = ""
passkeyInput = "" passkeyInput = ""
console.log("BluetoothPairingModal: Calling open()")
open() open()
Qt.callLater(() => { Qt.callLater(() => {
if (contentLoader.item) { if (contentLoader.item) {
@@ -39,6 +41,8 @@ DankModal {
} }
shouldBeVisible: false shouldBeVisible: false
allowStacking: true
keepPopoutsOpen: true
width: 420 width: 420
height: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 240 height: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 240
@@ -62,8 +66,11 @@ DankModal {
} }
onBackgroundClicked: () => { onBackgroundClicked: () => {
DMSService.bluetoothCancelPairing(token) if (token) {
DMSService.bluetoothCancelPairing(token)
}
close() close()
token = ""
pinInput = "" pinInput = ""
passkeyInput = "" passkeyInput = ""
} }
@@ -80,8 +87,11 @@ DankModal {
implicitHeight: mainColumn.implicitHeight implicitHeight: mainColumn.implicitHeight
Keys.onEscapePressed: event => { Keys.onEscapePressed: event => {
DMSService.bluetoothCancelPairing(token) if (token) {
DMSService.bluetoothCancelPairing(token)
}
close() close()
token = ""
pinInput = "" pinInput = ""
passkeyInput = "" passkeyInput = ""
event.accepted = true event.accepted = true
@@ -110,17 +120,22 @@ DankModal {
StyledText { StyledText {
text: { text: {
if (requestType === "confirm") switch (requestType) {
case "confirm":
return I18n.tr("Confirm passkey for ") + deviceName return I18n.tr("Confirm passkey for ") + deviceName
if (requestType === "authorize") case "display-passkey":
return I18n.tr("Enter this passkey on ") + deviceName
case "authorize":
return I18n.tr("Authorize pairing with ") + deviceName return I18n.tr("Authorize pairing with ") + deviceName
if (requestType.startsWith("authorize-service")) case "pin":
return I18n.tr("Authorize service for ") + deviceName
if (requestType === "pin")
return I18n.tr("Enter PIN for ") + deviceName return I18n.tr("Enter PIN for ") + deviceName
if (requestType === "passkey") case "passkey":
return I18n.tr("Enter passkey for ") + deviceName return I18n.tr("Enter passkey for ") + deviceName
return deviceName default:
if (requestType.startsWith("authorize-service"))
return I18n.tr("Authorize service for ") + deviceName
return deviceName
}
} }
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceTextMedium color: Theme.surfaceTextMedium
@@ -204,7 +219,7 @@ DankModal {
height: 56 height: 56
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
visible: requestType === "confirm" visible: requestType === "confirm" || requestType === "display-passkey"
Column { Column {
anchors.centerIn: parent anchors.centerIn: parent
@@ -261,8 +276,11 @@ DankModal {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: () => { onClicked: () => {
DMSService.bluetoothCancelPairing(token) if (token) {
DMSService.bluetoothCancelPairing(token)
}
close() close()
token = ""
pinInput = "" pinInput = ""
passkeyInput = "" passkeyInput = ""
} }
@@ -288,11 +306,17 @@ DankModal {
anchors.centerIn: parent anchors.centerIn: parent
text: { text: {
if (requestType === "confirm") switch (requestType) {
case "confirm":
case "display-passkey":
return I18n.tr("Confirm") return I18n.tr("Confirm")
if (requestType === "authorize" || requestType.startsWith("authorize-service")) case "authorize":
return I18n.tr("Authorize") return I18n.tr("Authorize")
return I18n.tr("Pair") default:
if (requestType.startsWith("authorize-service"))
return I18n.tr("Authorize")
return I18n.tr("Pair")
}
} }
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.background color: Theme.background
@@ -331,8 +355,11 @@ DankModal {
iconSize: Theme.iconSize - 4 iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText iconColor: Theme.surfaceText
onClicked: () => { onClicked: () => {
DMSService.bluetoothCancelPairing(token) if (token) {
DMSService.bluetoothCancelPairing(token)
}
close() close()
token = ""
pinInput = "" pinInput = ""
passkeyInput = "" passkeyInput = ""
} }
@@ -343,12 +370,23 @@ DankModal {
function submitPairing() { function submitPairing() {
const secrets = {} const secrets = {}
if (requestType === "pin") { switch (requestType) {
case "pin":
secrets["pin"] = pinInput secrets["pin"] = pinInput
} else if (requestType === "passkey") { break
case "passkey":
secrets["passkey"] = passkeyInput secrets["passkey"] = passkeyInput
} else if (requestType === "confirm" || requestType === "authorize" || requestType.startsWith("authorize-service")) { break
case "confirm":
case "display-passkey":
case "authorize":
secrets["decision"] = "yes" secrets["decision"] = "yes"
break
default:
if (requestType.startsWith("authorize-service")) {
secrets["decision"] = "yes"
}
break
} }
DMSService.bluetoothSubmitPairing(token, secrets, true, response => { DMSService.bluetoothSubmitPairing(token, secrets, true, response => {
@@ -358,6 +396,7 @@ DankModal {
}) })
close() close()
token = ""
pinInput = "" pinInput = ""
passkeyInput = "" passkeyInput = ""
} }

View File

@@ -61,6 +61,7 @@ PanelWindow {
} }
function close() { function close() {
console.log("DankModal.close() called on:", layerNamespace, "Stack trace:", new Error().stack)
shouldBeVisible = false shouldBeVisible = false
shouldHaveFocus = false shouldHaveFocus = false
closeTimer.restart() closeTimer.restart()

View File

@@ -29,11 +29,13 @@ Rectangle {
if (!device) return if (!device) return
const deviceAddr = device.address const deviceAddr = device.address
devicesBeingPaired.add(deviceAddr) const pairingSet = devicesBeingPaired
pairingSet.add(deviceAddr)
devicesBeingPairedChanged() devicesBeingPairedChanged()
BluetoothService.pairDevice(device, function(response) { BluetoothService.pairDevice(device, function(response) {
devicesBeingPaired.delete(deviceAddr) pairingSet.delete(deviceAddr)
devicesBeingPairedChanged() devicesBeingPairedChanged()
if (response.error) { if (response.error) {
@@ -625,15 +627,14 @@ Rectangle {
} }
} }
BluetoothPairingModal {
id: bluetoothPairingModal
}
Connections { Connections {
target: DMSService target: DMSService
function onBluetoothPairingRequest(data) { function onBluetoothPairingRequest(data) {
bluetoothPairingModal.show(data) const modal = PopoutService.bluetoothPairingModal
if (modal && modal.token !== data.token) {
modal.show(data)
}
} }
} }
} }

View File

@@ -49,20 +49,20 @@ Singleton {
return devices.sort((a, b) => { return devices.sort((a, b) => {
const aName = a.name || a.deviceName || "" const aName = a.name || a.deviceName || ""
const bName = b.name || b.deviceName || "" const bName = b.name || b.deviceName || ""
const aAddr = a.address || ""
const bAddr = b.address || ""
const aHasRealName = aName.includes(" ") && aName.length > 3 const aHasRealName = aName.includes(" ") && aName.length > 3
const bHasRealName = bName.includes(" ") && bName.length > 3 const bHasRealName = bName.includes(" ") && bName.length > 3
if (aHasRealName && !bHasRealName) { if (aHasRealName && !bHasRealName) return -1
return -1 if (!aHasRealName && bHasRealName) return 1
}
if (!aHasRealName && bHasRealName) { if (aHasRealName && bHasRealName) {
return 1 return aName.localeCompare(bName)
} }
const aSignal = (a.signalStrength !== undefined && a.signalStrength > 0) ? a.signalStrength : 0 return aAddr.localeCompare(bAddr)
const bSignal = (b.signalStrength !== undefined && b.signalStrength > 0) ? b.signalStrength : 0
return bSignal - aSignal
}) })
} }

View File

@@ -23,6 +23,7 @@ Singleton {
property var colorPickerModal: null property var colorPickerModal: null
property var notificationModal: null property var notificationModal: null
property var wifiPasswordModal: null property var wifiPasswordModal: null
property var bluetoothPairingModal: null
property var networkInfoModal: null property var networkInfoModal: null
property var notepadSlideouts: [] property var notepadSlideouts: []