implement caching on macOS, improve UI for NetworkDevicesToConnectWidget

This commit is contained in:
uncor3
2026-02-18 13:58:25 -08:00
parent 9336a7faa2
commit ca5cba575f
8 changed files with 131 additions and 15 deletions
+22 -13
View File
@@ -72,9 +72,9 @@ void AppContext::cachePairedDevices()
if (!fileData) {
continue;
}
plist_print(fileData);
const std::string wifiMacAddress =
PlistNavigator(fileData)["WiFiMACAddress"].getString();
// FIXME: free ?
// plist_free(fileData);
bool isCompatible = !wifiMacAddress.empty();
// TODO: !important invalidate expired pairing files
@@ -98,13 +98,11 @@ void AppContext::cachePairedDevices()
auto conn = UsbmuxdConnection::default_new(0);
if (conn.is_err()) {
qDebug() << "ERROR: Failed to connect to usbmuxd!";
// return 1;
}
auto devices = conn.unwrap().get_devices();
if (devices.is_err()) {
qDebug() << "ERROR: Failed to get device list!";
// return 1;
}
for (const auto &device : devices.unwrap()) {
@@ -142,11 +140,14 @@ void AppContext::cachePairedDevices()
if (mac_address) {
qDebug() << "Adding to cache"
<< QString::fromUtf8(mac_address);
QString path = QString::fromStdString(
"/var/db/lockdown/" + udid.unwrap() +
".plist");
SettingsManager::sharedInstance()
->setIdeviceDefaultPairingFile(
QString::fromUtf8(mac_address), path);
m_pairingFileCache[QString::fromUtf8(
mac_address)] =
QString::fromStdString("/var/db/lockdown/" +
udid.unwrap() +
".plist");
mac_address)] = path;
free(mac_address);
}
}
@@ -155,12 +156,6 @@ void AppContext::cachePairedDevices()
}
free(plist_data);
}
// qDebug() << "Wireless device UDID:"
// << QString::fromStdString(udid.unwrap())
// << "Pairing file retrieval"
// << (error == nullptr
// ? "succeeded"
// : QString::fromStdString(error->message));
// Clean up
// idevice_pairing_file_free(pairing_file.unwrap().raw());
}
@@ -172,6 +167,19 @@ void AppContext::cachePairedDevices()
}
}
}
// sometimes macOS doesn't find the network iDevice even tho we can connect
// if we know the ip address
QMap<QString, QString> cachedPairingFiles =
SettingsManager::sharedInstance()->getAllIdeviceDefaultPairingFiles();
for (const QString &mac : cachedPairingFiles.keys()) {
const QString path = cachedPairingFiles.value(mac);
qDebug() << "Using pairing file for MAC:" << mac
<< "cached from settings";
m_pairingFileCache[mac] = path;
}
#endif
}
@@ -181,6 +189,7 @@ void AppContext::addDevice(QString udid,
QString ipAddress)
{
emit initStarted(udid);
try {
// iDescriptorInitDeviceResult initResult;
auto initResult = std::make_shared<iDescriptorInitDeviceResult>();
+1
View File
@@ -75,6 +75,7 @@ signals:
// only fired on wireless devices when we have no pairing file for them
void noPairingFileForWirelessDevice(const QString &macAddress);
void initFailed(const QString &udid);
void initStarted(const QString &udid);
void systemSleepStarting();
void systemWakeup();
+36 -1
View File
@@ -32,6 +32,7 @@
#include <QLabel>
#include <QPalette>
#include <QPushButton>
#include <QTimer>
NetworkDeviceCard::NetworkDeviceCard(const NetworkDevice &device,
QWidget *parent)
@@ -117,6 +118,25 @@ void NetworkDeviceCard::failed()
});
}
void NetworkDeviceCard::noPairingFile()
{
// TODO: add a button or hint to explain how to create a pairing file for
// this device
m_connectButton->setText("No pairing file");
m_connectButton->setEnabled(false);
QTimer::singleShot(5000, this, [this]() {
m_connectButton->setText("Connect");
m_connectButton->setEnabled(true);
});
}
void NetworkDeviceCard::initStarted()
{
m_connectButton->setText("Connecting...");
m_connectButton->setEnabled(false);
}
NetworkDevicesToConnectWidget::NetworkDevicesToConnectWidget(QWidget *parent)
: QWidget(parent)
{
@@ -147,6 +167,8 @@ NetworkDevicesToConnectWidget::NetworkDevicesToConnectWidget(QWidget *parent)
&NetworkDevicesToConnectWidget::onNoPairingFileForWirelessDevice);
connect(AppContext::sharedInstance(), &AppContext::initFailed, this,
&NetworkDevicesToConnectWidget::onDeviceInitFailed);
connect(AppContext::sharedInstance(), &AppContext::initStarted, this,
&NetworkDevicesToConnectWidget::onDeviceInitStarted);
}
NetworkDevicesToConnectWidget::~NetworkDevicesToConnectWidget()
@@ -284,7 +306,11 @@ void NetworkDevicesToConnectWidget::onWirelessDeviceRemoved(
void NetworkDevicesToConnectWidget::onNoPairingFileForWirelessDevice(
const QString &macAddress)
{
// m_deviceCards.
NetworkDeviceCard *deviceCard = m_deviceCards[macAddress];
if (deviceCard) {
qDebug() << "Calling noPairingFile() on device card for" << macAddress;
deviceCard->noPairingFile();
}
}
// udid or mac address
@@ -295,4 +321,13 @@ void NetworkDevicesToConnectWidget::onDeviceInitFailed(const QString &udid)
qDebug() << "Calling failed() on device card for" << udid;
deviceCard->failed();
}
}
void NetworkDevicesToConnectWidget::onDeviceInitStarted(const QString &udid)
{
NetworkDeviceCard *deviceCard = m_deviceCards[udid];
if (deviceCard) {
qDebug() << "Calling initStarted() on device card for" << udid;
deviceCard->initStarted();
}
}
+5
View File
@@ -20,6 +20,8 @@
#ifndef NETWORKDEVICESTOCONNECTWIDGET_H
#define NETWORKDEVICESTOCONNECTWIDGET_H
#include "iDescriptor-ui.h"
#ifdef __linux__
#include "core/services/avahi/avahi_service.h"
#else
@@ -45,6 +47,8 @@ private:
public:
void failed();
void noPairingFile();
void initStarted();
};
class NetworkDevicesToConnectWidget : public QWidget
@@ -60,6 +64,7 @@ private slots:
void onWirelessDeviceRemoved(const QString &deviceName);
void onNoPairingFileForWirelessDevice(const QString &macAddress);
void onDeviceInitFailed(const QString &udid);
void onDeviceInitStarted(const QString &udid);
private:
void setupUI();
+1 -1
View File
@@ -180,7 +180,7 @@ IdeviceFfiError *ServiceManager::mountImage(const iDescriptorDevice *device,
void ServiceManager::getCableInfo(const iDescriptorDevice *device,
plist_t &response)
{
executeOperation<void>(
executeVoidOperation(
device, [device, &response]() { _get_cable_info(device, response); });
}
+25
View File
@@ -146,6 +146,31 @@ public:
operation();
}
static void
executeVoidOperation(const iDescriptorDevice *device,
std::function<void()> operation,
std::optional<AfcClientHandle *> altAfc = std::nullopt)
{
if (!device) {
return;
}
std::lock_guard<std::recursive_mutex> lock(device->mutex);
// Double-check device is still valid after acquiring lock
if (!device->afcClient) {
return;
}
if (altAfc && !*altAfc) {
// altAfc was explicitly provided but is null, which is an
// invalid state.
return;
}
operation();
}
static IdeviceFfiError *executeAfcOperation(
const iDescriptorDevice *device,
std::function<IdeviceFfiError *(AfcFileHandle *handle)> operation,
+33
View File
@@ -442,4 +442,37 @@ void SettingsManager::setShowV4L2(bool show)
m_settings->setValue("showV4L2", show);
m_settings->sync();
}
#endif
/*
only needed on macOS because
we cannot read /var/db/lockdown without root perm
so caching must be implemented
*/
#ifdef __APPLE__
void SettingsManager::setIdeviceDefaultPairingFile(const QString &macAddress,
const QString &pairingFile)
{
m_settings->setValue("_macos_idevice_" + macAddress, pairingFile);
m_settings->sync();
}
QString
SettingsManager::getIdeviceDefaultPairingFile(const QString &macAddress) const
{
return m_settings->value("_macos_idevice_" + macAddress, "").toString();
}
QMap<QString, QString> SettingsManager::getAllIdeviceDefaultPairingFiles() const
{
QMap<QString, QString> macAddresses;
QStringList allKeys = m_settings->allKeys();
for (const QString &key : allKeys) {
if (key.startsWith("_macos_idevice_")) {
QString macAddress = key.mid(QString("_macos_idevice_").length());
macAddresses[macAddress] = m_settings->value(key, "").toString();
}
}
return macAddresses;
}
#endif
+8
View File
@@ -119,6 +119,14 @@ public:
bool showV4L2() const;
void setShowV4L2(bool show);
#endif
#ifdef __APPLE__
void setIdeviceDefaultPairingFile(const QString &macAddress,
const QString &pairingFile);
QString getIdeviceDefaultPairingFile(const QString &macAddress) const;
QMap<QString, QString> getAllIdeviceDefaultPairingFiles() const;
#endif
signals:
void favoritePlacesChanged();
void recentLocationsChanged();