Added dragging proxy links onto window to open connection box.

This commit is contained in:
23rd
2026-06-05 13:41:02 +03:00
parent 9d4ad88a8a
commit e29458e8aa
5 changed files with 147 additions and 0 deletions
+3
View File
@@ -5565,6 +5565,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_drag_to_send_files" = "to send them as documents";
"lng_drag_to_send_media" = "to send them as media files";
"lng_drag_proxy_here" = "Connect to a proxy";
"lng_drag_proxy_about" = "Drop the link here";
"lng_selected_clear" = "Cancel";
"lng_selected_delete" = "Delete";
"lng_selected_forward" = "Forward";
@@ -24,8 +24,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "mainwidget.h"
#include "storage/storage_media_prepare.h"
#include "core/application.h"
#include "core/mime_type.h"
#include "core/local_url_handlers.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_layers.h"
#include "styles/style_window.h"
namespace {
@@ -37,6 +41,33 @@ constexpr auto kDragAreaEvents = {
QEvent::Leave,
};
[[nodiscard]] QString DetectProxyLink(const QMimeData *data) {
if (!data) {
return QString();
}
const auto check = [](const QString &text) -> QString {
const auto local = Core::TryConvertUrlToLocal(text.trimmed());
const auto proxy = [&](const QString &prefix) {
return local.startsWith(prefix, Qt::CaseInsensitive)
&& (local.size() > prefix.size());
};
return (proxy(u"tg://proxy?"_q) || proxy(u"tg://socks?"_q))
? local
: QString();
};
for (const auto &url : Core::ReadMimeUrls(data)) {
if (auto result = check(url.toString()); !result.isEmpty()) {
return result;
}
}
if (const auto text = Core::ReadMimeText(data); !text.isEmpty()) {
if (auto result = check(text); !result.isEmpty()) {
return result;
}
}
return QString();
}
} // namespace
DragArea::Areas DragArea::SetupDragAreaToContainer(
@@ -261,6 +292,100 @@ DragArea::Areas DragArea::SetupDragAreaToContainer(
};
}
void DragArea::SetupProxyDropArea(
not_null<Ui::RpWidget*> container,
Fn<void(const QString &localUrl)> connectProxy) {
auto &lifetime = container->lifetime();
container->setAcceptDrops(true);
const auto area = Ui::CreateChild<DragArea>(container.get());
area->hide();
area->raise();
area->setText(
tr::lng_drag_proxy_here(tr::now),
tr::lng_drag_proxy_about(tr::now));
const auto updateGeometry = [=] {
const auto margin = st::dragMargin;
const auto width = st::windowMinWidth
- margin.left()
- margin.right();
area->setGeometry(
(container->width() - width) / 2,
margin.top(),
width,
container->height() / 3 - margin.top());
};
container->sizeValue(
) | rpl::on_next([=](QSize) {
updateGeometry();
}, lifetime);
const auto reset = [=] {
if (!area->isHidden()) {
area->otherLeave();
}
};
const auto dragEnterEvent = [=](QDragEnterEvent *e) {
if (Core::App().passcodeLocked()
|| DetectProxyLink(e->mimeData()).isEmpty()) {
reset();
return;
}
updateGeometry();
area->raise();
area->otherEnter();
e->setDropAction(Qt::IgnoreAction);
e->accept();
};
const auto dropEvent = [=](QDropEvent *e) {
area->hideFast();
e->setDropAction(Qt::IgnoreAction);
e->accept();
};
const auto processDragEvents = [=](not_null<QEvent*> event) {
switch (event->type()) {
case QEvent::DragEnter:
dragEnterEvent(static_cast<QDragEnterEvent*>(event.get()));
return true;
case QEvent::DragLeave:
reset();
return true;
case QEvent::Drop:
dropEvent(static_cast<QDropEvent*>(event.get()));
return true;
}
return false;
};
container->events(
) | rpl::filter([=](not_null<QEvent*> event) {
return ranges::contains(kDragAreaEvents, event->type());
}) | rpl::on_next([=](not_null<QEvent*> event) {
const auto type = event->type();
if (processDragEvents(event)) {
return;
} else if (type == QEvent::Leave
|| type == QEvent::MouseButtonRelease) {
reset();
}
}, lifetime);
base::install_event_filter(area, [=](not_null<QEvent*> event) {
processDragEvents(event);
return base::EventFilterResult::Continue;
});
area->setDroppedCallback([=](const QMimeData *data) {
if (const auto local = DetectProxyLink(data); !local.isEmpty()) {
connectProxy(local);
}
});
}
DragArea::DragArea(QWidget *parent) : Ui::RpWidget(parent) {
setMouseTracking(true);
setAcceptDrops(true);
@@ -34,6 +34,10 @@ public:
CallbackComputeState &&computeState = nullptr,
bool hideSubtext = false);
static void SetupProxyDropArea(
not_null<Ui::RpWidget*> container,
Fn<void(const QString &localUrl)> connectProxy);
void setText(const QString &text, const QString &subtext);
void otherEnter();
+11
View File
@@ -53,6 +53,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "dialogs/dialogs_widget.h"
#include "history/history_widget.h"
#include "history/history_drag_area.h"
#include "history/history_item_helpers.h" // GetErrorForSending.
#include "history/view/media/history_view_media.h"
#include "history/view/history_view_chat_section.h"
@@ -75,6 +76,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/update_checker.h"
#include "core/shortcuts.h"
#include "core/application.h"
#include "core/click_handler_types.h"
#include "core/changelogs.h"
#include "core/mime_type.h"
#include "calls/calls_call.h"
@@ -436,6 +438,15 @@ MainWidget::MainWidget(
cSetOtherOnline(0);
session().data().stickers().notifySavedGifsUpdated();
const auto weak = base::make_weak(controller);
DragArea::SetupProxyDropArea(this, [=](const QString &localUrl) {
Core::App().openLocalUrl(
localUrl,
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = weak,
}));
});
}
MainWidget::~MainWidget() {
+4
View File
@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h"
#include "dialogs/ui/dialogs_layout.h"
#include "history/history.h"
#include "history/history_drag_area.h"
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
@@ -296,6 +297,9 @@ void MainWindow::setupIntro(
clearWidgets();
_intro = std::move(created);
DragArea::SetupProxyDropArea(_intro.data(), [](const QString &localUrl) {
Core::App().openLocalUrl(localUrl, {});
});
if (_passcodeLock || _setupEmailLock) {
_intro->hide();
} else {