diff --git a/resources.qrc b/resources.qrc index b170140..f558183 100644 --- a/resources.qrc +++ b/resources.qrc @@ -76,6 +76,7 @@ resources/keychain.mp4 resources/wireless-gallery-import.mp4 resources/dev-mode.mp4 + resources/unlock.mp4 resources/trust.png \ No newline at end of file diff --git a/resources/unlock.mp4 b/resources/unlock.mp4 new file mode 100755 index 0000000..64fd582 Binary files /dev/null and b/resources/unlock.mp4 differ diff --git a/src/appcontext.cpp b/src/appcontext.cpp index f726501..f7ed217 100644 --- a/src/appcontext.cpp +++ b/src/appcontext.cpp @@ -181,6 +181,12 @@ void AppContext::removeDevice(iDescriptor::Uniq uniq, bool ask_backend) auto device = m_devices[q_udid]; m_devices.remove(q_udid); + qDebug() << "Removed device with UUID " + q_udid << "macAddress:" + << QString::fromStdString(device->deviceInfo.wifiMacAddress) + << "ipAddress:" + << QString::fromStdString(device->deviceInfo.ipAddress) + << "wasWireless:" << device->deviceInfo.isWireless; + emit deviceRemoved(q_udid, device->deviceInfo.wifiMacAddress, device->deviceInfo.ipAddress, device->deviceInfo.isWireless); @@ -350,13 +356,17 @@ void AppContext::heartbeatFailed(const QString &macAddress, int tries) emit deviceHeartbeatFailed(macAddress, tries); } -void AppContext::tryToConnectToNetworkDevice(const NetworkDevice &device) +void AppContext::tryToConnectToNetworkDevice(const NetworkDevice &device, + bool forceCache, + bool setSelectionIfExists) { qDebug() << "Trying to connect to network device with MAC:" << device.macAddress << "IP:" << device.address; // force refresh macAddress-pairing file mapping - cachePairedDevices(); + if (forceCache) { + cachePairedDevices(); + } const iDescriptorDevice *existingDevice = nullptr; existingDevice = getDeviceByMacAddress(device.macAddress); @@ -365,8 +375,10 @@ void AppContext::tryToConnectToNetworkDevice(const NetworkDevice &device) emit deviceAlreadyExistsMAC( iDescriptor::Uniq(existingDevice->deviceInfo.wifiMacAddress, true)); // TODO: add a setting for this - - setCurrentDeviceSelection(DeviceSelection(existingDevice->udid), true); + if (setSelectionIfExists) { + setCurrentDeviceSelection(DeviceSelection(existingDevice->udid), + true); + } return; } diff --git a/src/appcontext.h b/src/appcontext.h index b4f993a..fc5b13c 100644 --- a/src/appcontext.h +++ b/src/appcontext.h @@ -45,7 +45,9 @@ public: const QString getCachedPairingFile(const QString &udid) const; CXX::Core *core = new CXX::Core(this); CXX::IOManager *ioManager = new CXX::IOManager(this); - void tryToConnectToNetworkDevice(const NetworkDevice &device); + void tryToConnectToNetworkDevice(const NetworkDevice &device, + bool forceCache = true, + bool setSelectionIfExists = true); #ifdef ENABLE_RECOVERY_DEVICE_SUPPORT QList getAllRecoveryDevices(); #endif diff --git a/src/devicemanagerwidget.cpp b/src/devicemanagerwidget.cpp index b9b3597..f2a8391 100644 --- a/src/devicemanagerwidget.cpp +++ b/src/devicemanagerwidget.cpp @@ -70,12 +70,12 @@ DeviceManagerWidget::DeviceManagerWidget(QWidget *parent) connect(AppContext::sharedInstance(), &AppContext::devicePaired, this, [this](const std::shared_ptr device) { addPairedDevice(device); - // SettingsManager::sharedInstance()->doIfEnabled( - // SettingsManager::Setting::SwitchToNewDevice, - // [this, device]() { - // AppContext::sharedInstance()->setCurrentDeviceSelection( - // DeviceSelection(device->udid)); - // }); + SettingsManager::sharedInstance()->doIfEnabled( + SettingsManager::Setting::SwitchToNewDevice, + [this, device]() { + AppContext::sharedInstance()->setCurrentDeviceSelection( + DeviceSelection(device->udid)); + }); updateUI(); }); diff --git a/src/devicesleepwarningwidget.cpp b/src/devicesleepwarningwidget.cpp new file mode 100644 index 0000000..d38d8e5 --- /dev/null +++ b/src/devicesleepwarningwidget.cpp @@ -0,0 +1,76 @@ +#include "devicesleepwarningwidget.h" + +DeviceSleepWarningWidget::DeviceSleepWarningWidget(QWidget *parent) + : QDialog{parent} +{ +#ifdef WIN32 + setupWinWindow(this); +#endif + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(0, 20, 0, 0); + mainLayout->setSpacing(0); + + m_loadingWidget = new ZLoadingWidget(false, this); + mainLayout->addWidget(m_loadingWidget); + + QWidget *contentContainer = new QWidget(this); + QVBoxLayout *contentLayout = new QVBoxLayout(contentContainer); + contentLayout->setContentsMargins(0, 0, 0, 0); + contentLayout->setSpacing(0); + m_loadingWidget->setupContentWidget(contentContainer); + + m_mediaPlayer = new QMediaPlayer(this); + m_videoWidget = new QVideoWidget(this); + m_videoWidget->setMinimumSize(300, 500); + m_videoWidget->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding); + m_videoWidget->setAspectRatioMode(Qt::KeepAspectRatio); + m_mediaPlayer->setVideoOutput(m_videoWidget); + + connect(m_mediaPlayer, + QOverload::of( + &QMediaPlayer::mediaStatusChanged), + [this](QMediaPlayer::MediaStatus status) { + if (status == QMediaPlayer::EndOfMedia) { + m_mediaPlayer->setPosition(0); + m_mediaPlayer->play(); + } + }); + + QLabel *title = new QLabel("Keep Your Device Awake", this); + title->setAlignment(Qt::AlignCenter); + title->setStyleSheet("QLabel { font-size: 18px; font-weight: bold; }"); + + QLabel *description = new QLabel( + R"(Please keep your device awake or unlocked while connected wirelessly to avoid disconnection)", + this); + description->setAlignment(Qt::AlignCenter); + description->setWordWrap(true); + + QVBoxLayout *textLayout = new QVBoxLayout(); + textLayout->setContentsMargins(20, 20, 20, 20); + textLayout->setSpacing(10); + contentLayout->addWidget(title); + textLayout->addWidget(description); + + contentLayout->addLayout(textLayout); + contentLayout->addWidget(m_videoWidget); + + contentLayout->addSpacing(20); + + QCheckBox *dontShowAgain = new QCheckBox("Don't show this again", this); + connect(dontShowAgain, &QCheckBox::toggled, this, [this](bool checked) { + SettingsManager::sharedInstance()->setIsSleepyDeviceWarningDismissed( + checked); + }); + + contentLayout->addWidget(dontShowAgain, 0, Qt::AlignCenter); + m_mediaPlayer->setSource(QUrl("qrc:/resources/unlock.mp4")); + QTimer::singleShot(500, this, &DeviceSleepWarningWidget::init); +} + +void DeviceSleepWarningWidget::init() +{ + m_mediaPlayer->play(); + m_loadingWidget->stop(); +} diff --git a/src/devicesleepwarningwidget.h b/src/devicesleepwarningwidget.h new file mode 100644 index 0000000..896d5ea --- /dev/null +++ b/src/devicesleepwarningwidget.h @@ -0,0 +1,29 @@ +#ifndef DEVICESLEEPWARNINGWIDGET_H +#define DEVICESLEEPWARNINGWIDGET_H + +#include "iDescriptor-ui.h" +#include "iDescriptor.h" +#include "zloadingwidget.h" +#include +#include +#include +#include +#include +#include +#include + +class DeviceSleepWarningWidget : public QDialog +{ + Q_OBJECT +public: + explicit DeviceSleepWarningWidget(QWidget *parent = nullptr); + +private: + ZLoadingWidget *m_loadingWidget; + QMediaPlayer *m_mediaPlayer; + QVideoWidget *m_videoWidget; + + void init(); +}; + +#endif // DEVICESLEEPWARNINGWIDGET_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 65582d8..83ca9a8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -26,23 +26,13 @@ #include "releasechangelogdialog.h" #include "toolboxwidget.h" #include "welcomewidget.h" -#include -#include -#include -#include -#include -#include #include #include "appcontext.h" #include "networkdeviceswidget.h" #include "settingsmanager.h" #include "statusballoon.h" -#include -#include -#include -#include -#include + #ifdef WIN32 #include "platform/windows/win_common.h" #endif @@ -129,11 +119,16 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) auto mainLayout = new QVBoxLayout(centralWidget); mainLayout->setContentsMargins(0, 0, 0, 0); - connect(AppContext::sharedInstance()->core, &CXX::Core::device_event, this, + auto core = AppContext::sharedInstance()->core; + + connect(core, &CXX::Core::device_event, this, [this](uint32_t code, const QString &udid, const QString &info) { handleCallback(code, udid, info); }); + connect(core, &CXX::Core::sleepy_time_detected, this, + &MainWindow::handleShowSleepyDeviceWarning); + AppContext::sharedInstance()->core->init(); m_ZTabWidget = new ZTabWidget(this); @@ -491,4 +486,27 @@ MainWindow::~MainWindow() #endif delete m_updater; // sleep(2); +} + +void MainWindow::handleShowSleepyDeviceWarning() +{ + + /* one minute cooldown to prevent spamming */ + static const int kMinIntervalMs = 60 * 1000; + + static QDateTime lastShown; + const auto now = QDateTime::currentDateTimeUtc(); + + if (lastShown.isValid() && lastShown.msecsTo(now) < kMinIntervalMs) { + qDebug() << "Ignoring sleepy device warning dialog."; + return; + } + + lastShown = now; + + if (SettingsManager::sharedInstance()->isSleepyDeviceWarningDismissed()) { + return; + } + + DeviceSleepWarningWidget(this).exec(); } \ No newline at end of file diff --git a/src/mainwindow.h b/src/mainwindow.h index 856fe5b..3d46fa3 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -21,13 +21,25 @@ #define MAINWINDOW_H #include "ZDownloader.h" #include "ZUpdater.h" +#include "devicesleepwarningwidget.h" #include "iDescriptor-ui.h" #include "iDescriptor.h" #include "iomanagerclient.h" #include "ztabwidget.h" +#include +#include +#include +#include #include #include +#include +#include +#include +#include #include +#include +#include +#include class DeviceManagerWidget; @@ -43,6 +55,7 @@ public: void raiseDeviceTab(); void showConnectedDevicesTab(); void showWelcomeTab(); + void handleShowSleepyDeviceWarning(); public slots: void updateNoDevicesConnected(); diff --git a/src/networkdevicestoconnectwidget.cpp b/src/networkdevicestoconnectwidget.cpp index d25e426..9ba5423 100644 --- a/src/networkdevicestoconnectwidget.cpp +++ b/src/networkdevicestoconnectwidget.cpp @@ -30,7 +30,7 @@ NetworkDeviceCard::NetworkDeviceCard(const NetworkDevice &device, QWidget *parent) - : QWidget(parent) + : QWidget(parent), m_device(device) { QVBoxLayout *cardLayout = new QVBoxLayout(this); cardLayout->setContentsMargins(12, 10, 12, 10); @@ -182,6 +182,12 @@ NetworkDevicesToConnectWidget::NetworkDevicesToConnectWidget(QWidget *parent) &NetworkDevicesToConnectWidget::onDeviceAdded); connect(AppContext::sharedInstance(), &AppContext::deviceAlreadyExistsMAC, this, &NetworkDevicesToConnectWidget::onDeviceAlreadyExists); + + // eval interval + QTimer *evalTimer = new QTimer(this); + connect(evalTimer, &QTimer::timeout, this, + &NetworkDevicesToConnectWidget::eval); + evalTimer->start(30000); // evaluate every 30 seconds } NetworkDevicesToConnectWidget::~NetworkDevicesToConnectWidget() {} @@ -313,6 +319,21 @@ void NetworkDevicesToConnectWidget::onWirelessDeviceRemoved( } } +void NetworkDevicesToConnectWidget::eval() +{ + if (QCoreApplication::closingDown()) + return; + bool forceCache = true; + for (const auto &card : m_deviceCards) { + if (card) { + NetworkDevice device = card->getDevice(); + AppContext::sharedInstance()->tryToConnectToNetworkDevice( + device, forceCache, false); + forceCache = false; // force cache once + } + } +} + void NetworkDevicesToConnectWidget::onNoPairingFileForWirelessDevice( const QString &macAddress) { @@ -367,4 +388,4 @@ void NetworkDevicesToConnectWidget::onDeviceAlreadyExists( return; } qDebug() << "No device card found for" << uniq.get(); -} \ No newline at end of file +} diff --git a/src/networkdevicestoconnectwidget.h b/src/networkdevicestoconnectwidget.h index e6ee170..97c0fa1 100644 --- a/src/networkdevicestoconnectwidget.h +++ b/src/networkdevicestoconnectwidget.h @@ -39,6 +39,7 @@ public: private: QPushButton *m_connectButton = nullptr; + NetworkDevice m_device; public: void failed(); @@ -46,6 +47,7 @@ public: void initStarted(); void connected(); void alreadyExists(); + NetworkDevice getDevice() { return m_device; }; }; class NetworkDevicesToConnectWidget : public QWidget @@ -70,7 +72,7 @@ private: void createDeviceCard(const NetworkDevice &device); void clearDeviceCards(); void updateDeviceList(); - + void eval(); QGroupBox *m_deviceGroup = nullptr; QScrollArea *m_scrollArea = nullptr; QWidget *m_scrollContent = nullptr; diff --git a/src/rust/src/hause_arrest.rs b/src/rust/src/hause_arrest.rs index deebf11..ab5e382 100644 --- a/src/rust/src/hause_arrest.rs +++ b/src/rust/src/hause_arrest.rs @@ -306,7 +306,10 @@ impl qobject::HauseArrest { true }); if !inserted { - eprintln!("start_video_stream: failed to insert video stream for udid={} path={}", udid_str, cloned_path); + eprintln!( + "start_video_stream: failed to insert video stream for udid={} path={}", + udid_str, cloned_path + ); return QString::default(); } eprintln!( diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 8bdbca1..4090169 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -1,13 +1,12 @@ use futures::StreamExt; use idevice::{ - IdeviceService, + IdeviceError, IdeviceService, afc::AfcClient, diagnostics_relay::DiagnosticsRelayClient, heartbeat, lockdown::LockdownClient, pairing_file::PairingFile, - provider::{TcpProvider}, - IdeviceError, + provider::TcpProvider, usbmuxd::{Connection, UsbmuxdAddr, UsbmuxdConnection, UsbmuxdListenEvent}, }; use std::{any::type_name, sync::Arc}; @@ -29,8 +28,8 @@ use crate::qobject::Core; use once_cell::sync::Lazy; use plist::Value; mod afc; -mod afc_services; mod afc2_services; +mod afc_services; mod hause_arrest; mod io_manager; mod screenshot; @@ -55,7 +54,6 @@ pub struct DeviceServices { pub lockdown: Arc>, } - pub static APP_DEVICE_STATE: Lazy>> = Lazy::new(|| Mutex::new(HashMap::new())); @@ -122,6 +120,9 @@ mod qobject { #[qsignal] fn no_pairing_file(self: Pin<&mut Core>, mac_address: &QString); + + #[qsignal] + fn sleepy_time_detected(self: Pin<&mut Core>); } impl cxx_qt::Threading for Core {} } @@ -638,7 +639,7 @@ async fn init_idescriptor_device< return None; } let mut hb = None; - + if is_wireless { eprintln!("init_idescriptor_device: Attempting to connect to HeartbeatClient."); hb = match heartbeat::HeartbeatClient::connect(&provider).await { @@ -735,7 +736,6 @@ async fn init_idescriptor_device< ); } - eprintln!("init_idescriptor_device: Storing device services."); let device_services = DeviceServices { afc: Arc::new(Mutex::new(afc_client)), @@ -810,6 +810,19 @@ async fn spawn_heartbeat_task( Err(e) => { fails += 1; eprintln!("heartbeat: get_marco failed (fail count: {fails}): {e:?}"); + + match e { + IdeviceError::Heartbeat(idevice::HeartbeatError::SleepyTime) => { + println!("heartbeat: Sleepy time"); + qt_thread + .queue(move |core_qobj| { + core_qobj.sleepy_time_detected(); + }) + .ok(); + } + _ => {} + }; + if fails >= 3 { eprintln!("heartbeat: too many failures for giving up"); clean_device_from_app_state(&udid_for_hb).await; @@ -832,6 +845,17 @@ async fn spawn_heartbeat_task( if let Err(e) = hb_client.send_polo().await { fails += 1; eprintln!("heartbeat: send_polo failed (fail count: {fails}): {e:?}"); + match e { + IdeviceError::Heartbeat(idevice::HeartbeatError::SleepyTime) => { + println!("heartbeat: Sleepy time"); + qt_thread + .queue(move |core_qobj| { + core_qobj.sleepy_time_detected(); + }) + .ok(); + } + _ => {} + }; if fails >= 3 { eprintln!("heartbeat: too many failures for , giving up"); clean_device_from_app_state(&udid_for_hb).await; diff --git a/src/rust/src/service_manager.rs b/src/rust/src/service_manager.rs index 369ebd6..47d97a7 100644 --- a/src/rust/src/service_manager.rs +++ b/src/rust/src/service_manager.rs @@ -75,7 +75,7 @@ mod qobject { ); #[qsignal] - fn dev_image_mounted(self: Pin<&mut ServiceManager>, success: bool,is_locked: bool); + fn dev_image_mounted(self: Pin<&mut ServiceManager>, success: bool, is_locked: bool); #[qsignal] fn developer_mode_option_revealed(self: Pin<&mut ServiceManager>, success: bool); @@ -131,7 +131,6 @@ mod qobject { #[qsignal] fn install_ipa_progress(self: Pin<&mut ServiceManager>, progress: f64, state: QString); - #[qinvokable] fn enable_wifi_connections(&self); @@ -908,11 +907,7 @@ impl qobject::ServiceManager { let udid = self.get_udid().to_string(); run_sync(async move { - let maybe_device = APP_DEVICE_STATE - .lock() - .await - .get(udid.as_str()) - .cloned(); + let maybe_device = APP_DEVICE_STATE.lock().await.get(udid.as_str()).cloned(); let device = match maybe_device { Some(d) => d, @@ -924,7 +919,7 @@ impl qobject::ServiceManager { if let Err(e) = device.diag.lock().await.restart().await { eprintln!("restart: Failed to restart device {udid}: {e}"); - return false + return false; } return true; }) @@ -934,11 +929,7 @@ impl qobject::ServiceManager { let udid = self.get_udid().to_string(); run_sync(async move { - let maybe_device = APP_DEVICE_STATE - .lock() - .await - .get(udid.as_str()) - .cloned(); + let maybe_device = APP_DEVICE_STATE.lock().await.get(udid.as_str()).cloned(); let device = match maybe_device { Some(d) => d, @@ -950,7 +941,7 @@ impl qobject::ServiceManager { if let Err(e) = device.diag.lock().await.shutdown().await { eprintln!("shutdown: Failed to shutdown device {udid}: {e}"); - return false + return false; } return true; }) @@ -959,11 +950,7 @@ impl qobject::ServiceManager { let udid = self.get_udid().to_string(); run_sync(async move { - let maybe_device = APP_DEVICE_STATE - .lock() - .await - .get(udid.as_str()) - .cloned(); + let maybe_device = APP_DEVICE_STATE.lock().await.get(udid.as_str()).cloned(); let device = match maybe_device { Some(d) => d, @@ -974,8 +961,10 @@ impl qobject::ServiceManager { }; if let Err(e) = device.lockdown.lock().await.enter_recovery().await { - eprintln!("enter_recovery_mode: Failed to enter recovery mode for device {udid}: {e}"); - return false + eprintln!( + "enter_recovery_mode: Failed to enter recovery mode for device {udid}: {e}" + ); + return false; } return true; }) @@ -985,8 +974,15 @@ impl qobject::ServiceManager { let udid = self.get_udid().to_string(); let qt_t = self.qt_thread(); let local_ipa_path_owned = local_ipa_path.clone().to_string(); - // FIXME: this is a bit hacky - let ipa_path_on_device = format!("/PublicStaging/{}", local_ipa_path.to_string().split('/').last().unwrap_or("app.ipa")); + // FIXME: this is a bit hacky + let ipa_path_on_device = format!( + "/PublicStaging/{}", + local_ipa_path + .to_string() + .split('/') + .last() + .unwrap_or("app.ipa") + ); RUNTIME.spawn(async move { let qt_thread = qt_t.clone(); @@ -1145,24 +1141,21 @@ impl qobject::ServiceManager { let qt_t = self.qt_thread(); let udid = self.get_udid().to_string(); - RUNTIME.spawn(async move { let qt_thread = qt_t.clone(); - + let lc_arc = { - let maybe_device = APP_DEVICE_STATE - .lock() - .await - .get(udid.as_str()) - .cloned(); + let maybe_device = APP_DEVICE_STATE.lock().await.get(udid.as_str()).cloned(); let device = match maybe_device { Some(d) => d, None => { eprintln!("enable_wifi_connections: device {udid} not found"); - let _ = qt_thread.queue(|t| { - t.enable_wifi_connections_result(false); - }).ok(); + let _ = qt_thread + .queue(|t| { + t.enable_wifi_connections_result(false); + }) + .ok(); return; } }; @@ -1173,22 +1166,31 @@ impl qobject::ServiceManager { let mut lc = lc_arc.lock().await; let value = Value::Boolean(true); - match lc.set_value("EnableWifiConnections", value, Some("com.apple.mobile.wireless_lockdown")).await { + match lc + .set_value( + "EnableWifiConnections", + value, + Some("com.apple.mobile.wireless_lockdown"), + ) + .await + { Ok(_) => { - let _ = qt_thread.queue(|t| { - t.enable_wifi_connections_result(true); - }).ok(); - }, + let _ = qt_thread + .queue(|t| { + t.enable_wifi_connections_result(true); + }) + .ok(); + } Err(e) => { eprintln!("wireless: LockdownClient::set_value failed: {e:?}"); - let _ = qt_thread.queue(|t| { - t.enable_wifi_connections_result(false); - }).ok(); + let _ = qt_thread + .queue(|t| { + t.enable_wifi_connections_result(false); + }) + .ok(); } } - }); - } } @@ -1202,21 +1204,21 @@ async fn set_device_location_lockdown( } // iOS 17+: -async fn set_device_location_rsd( - proxy: CoreDeviceProxy, - latitude: f64, - longitude: f64, -) -> Result<(), idevice::IdeviceError> { +async fn set_device_location_rsd( + proxy: CoreDeviceProxy, + latitude: f64, + longitude: f64, +) -> Result<(), idevice::IdeviceError> { let rsd_port = proxy.tunnel_info().server_rsd_port; - let adapter = proxy.create_software_tunnel()?; - let mut adapter = adapter.to_async_handle(); - let stream = adapter.connect(rsd_port).await?; - - let mut handshake = RsdHandshake::new(stream).await?; - - let mut remote_server = RemoteServerClient::connect_rsd(&mut adapter, &mut handshake).await?; - remote_server.read_message(0).await?; - - let mut location_client = LocationSimulationClient::new(&mut remote_server).await?; - location_client.set(latitude, longitude).await -} \ No newline at end of file + let adapter = proxy.create_software_tunnel()?; + let mut adapter = adapter.to_async_handle(); + let stream = adapter.connect(rsd_port).await?; + + let mut handshake = RsdHandshake::new(stream).await?; + + let mut remote_server = RemoteServerClient::connect_rsd(&mut adapter, &mut handshake).await?; + remote_server.read_message(0).await?; + + let mut location_client = LocationSimulationClient::new(&mut remote_server).await?; + location_client.set(latitude, longitude).await +} diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index 5bac3c9..d71a965 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -265,6 +265,7 @@ void SettingsManager::resetToDefaults() #ifdef __linux__ setShowV4L2(false); #endif + setIsSleepyDeviceWarningDismissed(false); } void SettingsManager::saveFavoritePlace(const QString &path, @@ -502,4 +503,21 @@ WIN_BACKDROP SettingsManager::winBackdropType() const return static_cast( m_settings->value("winBackdropType", static_cast(MICA)).toInt()); } -#endif \ No newline at end of file +#endif + +bool SettingsManager::isSleepyDeviceWarningDismissed() const +{ + return m_settings->value("sleepyDeviceWarningDismissed", false).toBool(); +} + +void SettingsManager::dismissSleepyDeviceWarning() +{ + m_settings->setValue("sleepyDeviceWarningDismissed", true); + m_settings->sync(); +} + +void SettingsManager::setIsSleepyDeviceWarningDismissed(bool dismissed) +{ + m_settings->setValue("sleepyDeviceWarningDismissed", dismissed); + m_settings->sync(); +} \ No newline at end of file diff --git a/src/settingsmanager.h b/src/settingsmanager.h index 6a0776a..75fbd15 100644 --- a/src/settingsmanager.h +++ b/src/settingsmanager.h @@ -138,6 +138,11 @@ public: void setWinBackdropType(WIN_BACKDROP type); WIN_BACKDROP winBackdropType() const; #endif + + bool isSleepyDeviceWarningDismissed() const; + void setIsSleepyDeviceWarningDismissed(bool dismissed); + void dismissSleepyDeviceWarning(); + signals: void favoritePlacesChanged(); void recentLocationsChanged();