diff --git a/resources.qrc b/resources.qrc
index 4b2c392..ab7ce47 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -71,6 +71,7 @@
DeveloperDiskImages.json
resources/keychain.mp4
resources/wireless-gallery-import.mp4
+ resources/dev-mode.mp4
resources/trust.png
\ No newline at end of file
diff --git a/resources/dev-mode.mp4 b/resources/dev-mode.mp4
new file mode 100755
index 0000000..5f9b72d
Binary files /dev/null and b/resources/dev-mode.mp4 differ
diff --git a/src/devdiskmanager.h b/src/devdiskmanager.h
index 273dd84..28481f3 100644
--- a/src/devdiskmanager.h
+++ b/src/devdiskmanager.h
@@ -48,9 +48,6 @@ public:
const QString &downloadPath) const;
// Mount operations
-
- bool mountImage(const QString &version, const iDescriptorDevice *device);
- bool unmountImage();
std::pair getPathsForVersion(const QString &version);
// Signature comparison
@@ -58,7 +55,6 @@ public:
const char *mounted_sig, uint64_t mounted_sig_len);
QByteArray getImageListData() const { return m_imageListJsonData; }
- bool mountCompatibleImage(const iDescriptorDevice *device);
QString downloadCompatibleImage(
const std::shared_ptr device,
std::function callback);
diff --git a/src/devmodewidget.cpp b/src/devmodewidget.cpp
new file mode 100644
index 0000000..225fa45
--- /dev/null
+++ b/src/devmodewidget.cpp
@@ -0,0 +1,83 @@
+#include "devmodewidget.h"
+
+DevModeWidget::DevModeWidget(std::shared_ptr device,
+ QWidget *parent)
+ : QDialog{parent}
+{
+ 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("Enable Developer Mode on your iOS device", this);
+ title->setAlignment(Qt::AlignCenter);
+ title->setStyleSheet("QLabel { font-size: 18px; font-weight: bold; }");
+
+ QLabel *description = new QLabel(
+ R"(In order to use this feature on your device, you need to enable Developer Mode in the Settings app.
+ This allows iDescriptor to access advanced features on your device.
+ Please follow the instructions in the video below to enable Developer Mode.)",
+ 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);
+
+ m_mediaPlayer->setSource(QUrl("qrc:/resources/dev-mode.mp4"));
+
+ connect(
+ device->service_manager,
+ &CXX::ServiceManager::developer_mode_option_revealed, this,
+ [this](bool revealed) {
+ if (revealed) {
+ QTimer::singleShot(500, this, &DevModeWidget::init);
+ } else {
+ m_loadingWidget->showError(
+ "Failed to reveal Developer Mode option in UI. Please try "
+ "again later.");
+ }
+ },
+ Qt::SingleShotConnection);
+
+ device->service_manager->reveal_developer_mode_option_in_ui();
+}
+
+void DevModeWidget::init()
+{
+ m_mediaPlayer->play();
+ m_loadingWidget->stop();
+}
diff --git a/src/devmodewidget.h b/src/devmodewidget.h
new file mode 100644
index 0000000..7262993
--- /dev/null
+++ b/src/devmodewidget.h
@@ -0,0 +1,29 @@
+#ifndef DEVMODEWIDGET_H
+#define DEVMODEWIDGET_H
+
+#include "iDescriptor-ui.h"
+#include "iDescriptor.h"
+#include "zloadingwidget.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+class DevModeWidget : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit DevModeWidget(std::shared_ptr device,
+ QWidget *parent = nullptr);
+
+private:
+ ZLoadingWidget *m_loadingWidget;
+ QMediaPlayer *m_mediaPlayer;
+ QVideoWidget *m_videoWidget;
+
+ void init();
+};
+
+#endif // DEVMODEWIDGET_H
diff --git a/src/exportalbum.cpp b/src/exportalbum.cpp
index 8d2dd6c..f9f3507 100644
--- a/src/exportalbum.cpp
+++ b/src/exportalbum.cpp
@@ -10,7 +10,7 @@ ExportAlbum::ExportAlbum(const std::shared_ptr device,
setupWinWindow(this);
#endif
- m_loadingWidget = new ZLoadingWidget(true, this);
+ m_loadingWidget = new ZLoadingWidget(false, this);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(m_loadingWidget);
@@ -99,6 +99,8 @@ void ExportAlbum::getTotalPhotoCount(const QStringList &paths)
watcher->setFuture(QtConcurrent::run([this, paths]() {
size_t count = 0;
bool errorOccurred = false;
+ // FIXME: if a dir returns empty, it could be an error or just an empty
+ // dir, we should check that
for (const QString &path : paths) {
QList items = m_device->afc_backend->list_files_flat(path);
diff --git a/src/virtuallocationwidget.cpp b/src/virtuallocationwidget.cpp
index c4e12bb..7e37438 100644
--- a/src/virtuallocationwidget.cpp
+++ b/src/virtuallocationwidget.cpp
@@ -291,7 +291,7 @@ void VirtualLocation::updateInputsFromMap(const QString &latitude,
qDebug() << "Updated inputs from map:" << latitude << "," << longitude;
}
-void VirtualLocation::handleEnable()
+void VirtualLocation::restoreButtons()
{
QTimer::singleShot(1000, this, [this]() {
m_applyButton->setText("Apply Location");
@@ -324,9 +324,8 @@ void VirtualLocation::onApplyClicked()
this,
[this, latitude, longitude, devDiskImageHelper](bool success) {
if (!success) {
- // mounter will show its own error message, just
- // re-enable the button here
- return handleEnable();
+ // mounter will show its own error message
+ return;
}
u_int32_t set_location_success =
@@ -344,17 +343,16 @@ void VirtualLocation::onApplyClicked()
QMessageBox::information(
this, "Success", "Location applied successfully!");
- // SettingsManager::sharedInstance()->saveRecentLocation(
- // latitude, longitude);
+ SettingsManager::sharedInstance()->saveRecentLocation(
+ latitude, longitude);
}
- return handleEnable();
});
connect(devDiskImageHelper, &DevDiskImageHelper::destroyed, this,
- &VirtualLocation::handleEnable, Qt::SingleShotConnection);
+ &VirtualLocation::restoreButtons, Qt::SingleShotConnection);
return devDiskImageHelper->start();
}
- // /* iOS 17 and above */
+ /* iOS 17 and above */
int32_t set_location_res =
m_device->service_manager->set_location(latitude, longitude);
@@ -364,10 +362,7 @@ void VirtualLocation::onApplyClicked()
"Location applied successfully");
break;
case ServiceNotFoundErrorCode:
- // TODO: create a widget for this
- qDebug() << "Failed to set location simulation: service not found";
- QMessageBox::warning(this, "Error",
- "Developer Mode is not enabled on the device.");
+ DevModeWidget(m_device, this).exec();
break;
case TimeoutErrorCode:
qDebug() << "Failed to set location simulation: timed out";
@@ -381,7 +376,7 @@ void VirtualLocation::onApplyClicked()
QString::number(set_location_res));
}
- handleEnable();
+ restoreButtons();
}
void VirtualLocation::loadRecentLocations(QVBoxLayout *layout)
diff --git a/src/virtuallocationwidget.h b/src/virtuallocationwidget.h
index cef1ed4..352c4c5 100644
--- a/src/virtuallocationwidget.h
+++ b/src/virtuallocationwidget.h
@@ -21,6 +21,7 @@
#define VIRTUAL_LOCATION_H
#include "devdiskimagehelper.h"
+#include "devmodewidget.h"
#include "iDescriptor-ui.h"
#include "iDescriptor.h"
#include
@@ -57,7 +58,7 @@ private:
void addLocationButtons(QLayout *layout,
QList recentLocations);
- void handleEnable();
+ void restoreButtons();
QQuickWidget *m_quickWidget;
QLineEdit *m_latitudeEdit;