manual send (to ip)

This commit is contained in:
2026-05-26 16:33:57 +08:00
parent 6de6664aa0
commit 5922ff4ca5
5 changed files with 151 additions and 2 deletions

View File

@@ -74,6 +74,10 @@ void AppController::initialize()
this, &AppController::onUploadCompleted);
connect(m_httpClient, &LocalSend::HttpClient::uploadError,
this, &AppController::onUploadError);
connect(m_httpClient, &LocalSend::HttpClient::registerCompleted,
this, &AppController::onManualRegisterCompleted);
connect(m_httpClient, &LocalSend::HttpClient::registerError,
this, &AppController::onManualRegisterError);
startDiscovery();
}
@@ -556,6 +560,46 @@ void AppController::sendTo(const QString& deviceFingerprint)
sendFiles(deviceFingerprint, m_pendingSendPaths);
}
void AppController::sendToAddress(const QString& address)
{
if (m_pendingSendPaths.isEmpty()) {
emit sendError(QStringLiteral("No files selected"));
return;
}
if (sending()) {
emit sendError(QStringLiteral("Already sending files"));
return;
}
QString ip = address;
quint16 port = m_settings->port();
if (address.contains(':')) {
int colonPos = address.lastIndexOf(':');
ip = address.left(colonPos);
bool ok = false;
int parsedPort = address.mid(colonPos + 1).toInt(&ok);
if (ok && parsedPort > 0 && parsedPort <= 65535) {
port = static_cast<quint16>(parsedPort);
}
}
QHostAddress hostAddr(ip);
if (hostAddr.isNull()) {
emit sendError(QStringLiteral("Invalid IP address: %1").arg(ip));
return;
}
qDebug() << "[AppController] sendToAddress:" << ip << "port:" << port;
m_manualSendDevice = LocalSend::Device(ip, port);
m_manualSendDevice.discoveryMethod = LocalSend::DiscoveryMethod::HttpTarget;
m_manualSendPending = true;
m_httpClient->registerDevice(m_manualSendDevice, buildRegisterDto());
}
void AppController::sendFiles(const QString& deviceFingerprint, const QStringList& filePaths)
{
if (!m_devices.contains(deviceFingerprint)) {
@@ -898,3 +942,42 @@ void AppController::resetReceiveState()
emit receivingChanged();
emit receiveProgressChanged();
}
void AppController::onManualRegisterCompleted(const LocalSend::InfoDto& peerInfo)
{
if (!m_manualSendPending) return;
m_manualSendPending = false;
m_manualSendDevice.alias = peerInfo.alias;
m_manualSendDevice.deviceModel = peerInfo.deviceModel;
m_manualSendDevice.deviceType = peerInfo.deviceType;
m_manualSendDevice.version = peerInfo.version;
m_manualSendDevice.fingerprint = peerInfo.fingerprint;
qDebug() << "[AppController] Manual register completed:" << m_manualSendDevice.alias
<< "fingerprint:" << m_manualSendDevice.fingerprint;
if (!m_devices.contains(m_manualSendDevice.fingerprint)) {
m_devices.insert(m_manualSendDevice.fingerprint, m_manualSendDevice);
emit devicesChanged();
}
sendFiles(m_manualSendDevice.fingerprint, m_pendingSendPaths);
}
void AppController::onManualRegisterError(const QString& error)
{
if (!m_manualSendPending) return;
if (m_manualSendDevice.protocol == LocalSend::ProtocolType::Http) {
qWarning() << "[AppController] Manual register failed with HTTP, retrying with HTTPS:" << error;
m_manualSendDevice.protocol = LocalSend::ProtocolType::Https;
m_httpClient->registerDevice(m_manualSendDevice, buildRegisterDto());
return;
}
m_manualSendPending = false;
qWarning() << "[AppController] Manual register error:" << error;
emit sendError(QStringLiteral("Cannot reach device at %1: %2").arg(m_manualSendDevice.ip).arg(error));
}

View File

@@ -86,6 +86,7 @@ public:
Q_INVOKABLE void sendFiles(const QString& deviceFingerprint, const QStringList& filePaths);
Q_INVOKABLE void sendTo(const QString& deviceFingerprint);
Q_INVOKABLE void sendToAddress(const QString& address);
Q_INVOKABLE void cancelSend();
Q_INVOKABLE void addFiles(const QStringList& filePaths);
Q_INVOKABLE void removePendingFile(int index);
@@ -137,6 +138,8 @@ private slots:
void onUploadProgress(qint64 sent, qint64 total);
void onUploadCompleted();
void onUploadError(const QString& error);
void onManualRegisterCompleted(const LocalSend::InfoDto& peerInfo);
void onManualRegisterError(const QString& error);
void onCancelRequest(const QString& sessionId);
@@ -175,4 +178,7 @@ private:
LocalSend::RegisterDto buildRegisterDto() const;
void resetSendState();
void resetReceiveState();
bool m_manualSendPending = false;
LocalSend::Device m_manualSendDevice;
};

View File

@@ -410,6 +410,51 @@ ApplicationWindow {
}
}
Dialog {
id: manualSendDialog
anchors.centerIn: parent
modal: true
title: qsTr("Manual Sending")
ColumnLayout {
spacing: 12
Label {
text: qsTr("Enter the IP address of the target device.")
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
TextField {
id: manualAddressInput
Layout.fillWidth: true
placeholderText: qsTr("IP address (e.g., 192.168.1.100:53317)")
onAccepted: manualSendDialog.accepted()
}
}
footer: DialogButtonBox {
Button {
text: qsTr("Cancel")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
}
Button {
text: qsTr("Send")
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
enabled: manualAddressInput.text.trim().length > 0
}
}
onAccepted: {
appController.sendToAddress(manualAddressInput.text.trim())
}
onOpened: {
manualAddressInput.text = ""
manualAddressInput.forceActiveFocus()
}
}
Dialog {
id: setPinDialog
anchors.centerIn: parent
@@ -646,6 +691,11 @@ ApplicationWindow {
text: qsTr("Refresh")
onClicked: appController.refreshDevices()
}
Button {
text: qsTr("Manual Send")
enabled: appController.hasPendingFiles && !appController.sending
onClicked: manualSendDialog.open()
}
Item { Layout.fillWidth: true }
Label {
text: qsTr("Alias: %1").arg(appController.alias)

View File

@@ -31,7 +31,7 @@ public:
signals:
void infoReceived(const InfoDto& info);
void infoError(const QString& error);
void registerCompleted();
void registerCompleted(const InfoDto& peerInfo);
void registerError(const QString& error);
void prepareUploadResponse(const PrepareUploadResponseDto& response);
void prepareUploadError(const QString& error);

View File

@@ -95,7 +95,17 @@ void HttpClient::registerDevice(const Device& device, const RegisterDto& dto)
return;
}
emit registerCompleted();
QByteArray responseData = reply->readAll();
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(responseData, &error);
if (error.error != QJsonParseError::NoError) {
emit registerError(QStringLiteral("Invalid JSON response"));
return;
}
InfoDto info = InfoDto::fromJson(doc.object());
emit registerCompleted(info);
});
}