diff --git a/core/server/test_utils.go b/core/server/test_utils.go index 149fc1b..13a1c6c 100644 --- a/core/server/test_utils.go +++ b/core/server/test_utils.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/Mahdi-zarei/speedtest-go/speedtest" "github.com/sagernet/sing-box/adapter" - E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/metadata" "github.com/sagernet/sing/service" "nekobox_core/internal/boxbox" @@ -206,14 +205,14 @@ func speedTestWithDialer(ctx context.Context, dialer func(ctx context.Context, n defer func() { close(done) }() if testDl { err = srv[0].DownloadTestContext(ctx) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { res.Error = err return } } if testUl { err = srv[0].UploadTestContext(ctx) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { res.Error = err return } @@ -232,7 +231,7 @@ func speedTestWithDialer(ctx context.Context, dialer func(ctx context.Context, n SpTQuerier.storeResult(res) return nil case <-ctx.Done(): - return E.New("test cancelled") + return nil case <-ticker.C: res.DlSpeed = speedtest.ByteRate(srv[0].Context.GetEWMADownloadRate()).String() res.UlSpeed = speedtest.ByteRate(srv[0].Context.GetEWMAUploadRate()).String() diff --git a/include/api/gRPC.h b/include/api/gRPC.h index af18933..df5f3db 100644 --- a/include/api/gRPC.h +++ b/include/api/gRPC.h @@ -42,7 +42,7 @@ namespace NekoGui_rpc { libcore::SpeedTestResponse SpeedTest(bool *rpcOK, const libcore::SpeedTestRequest &request); - libcore::SpeedTestResult QueryCurrentSpeedTests(bool *rpcOK); + libcore::QuerySpeedTestResponse QueryCurrentSpeedTests(bool *rpcOK); private: std::function()> make_grpc_channel; diff --git a/include/ui/mainwindow.h b/include/ui/mainwindow.h index 4d904e7..f6fcae7 100644 --- a/include/ui/mainwindow.h +++ b/include/ui/mainwindow.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "include/global/NekoGui.hpp" #include "include/stats/connections/connectionLister.hpp" @@ -86,6 +87,9 @@ public: void UpdateConnectionListWithRecreate(const QList& connections); + // TODO maybe use a more generalized way of passing data later, for now we only need it for speedtest data + void UpdateDataView(const libcore::SpeedTestResult& result, const QString& profileName, bool clear); + signals: void profile_selected(int id); diff --git a/include/ui/mainwindow.ui b/include/ui/mainwindow.ui index 18fe6d5..b813666 100644 --- a/include/ui/mainwindow.ui +++ b/include/ui/mainwindow.ui @@ -165,23 +165,43 @@ - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - + + true + + + 0 + 0 + + + + false + + + Qt::FocusPolicy::NoFocus + + + Qt::ContextMenuPolicy::NoContextMenu + + + false + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Sunken + + + Qt::ScrollBarPolicy::ScrollBarAlwaysOff + + + Qt::ScrollBarPolicy::ScrollBarAlwaysOff + + + Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse + @@ -536,7 +556,7 @@ 0 0 800 - 25 + 17 diff --git a/src/api/gRPC.cpp b/src/api/gRPC.cpp index 02382d9..518ab3a 100644 --- a/src/api/gRPC.cpp +++ b/src/api/gRPC.cpp @@ -421,10 +421,10 @@ namespace NekoGui_rpc { } } - libcore::SpeedTestResult Client::QueryCurrentSpeedTests(bool *rpcOK) + libcore::QuerySpeedTestResponse Client::QueryCurrentSpeedTests(bool *rpcOK) { const libcore::EmptyReq req; - libcore::SpeedTestResult reply; + libcore::QuerySpeedTestResponse reply; auto status = make_grpc_channel()->Call("QuerySpeedTest", req, &reply); if (status == QNetworkReply::NoError) { diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 03f8ace..dd63d1e 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -310,38 +310,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi ui->proxyListTable->setTabKeyNavigation(false); // search box - ui->search->setVisible(false); - connect(shortcut_ctrl_f, &QShortcut::activated, this, [=] { - ui->search->setVisible(true); - ui->search->setFocus(); - }); connect(shortcut_esc, &QShortcut::activated, this, [=] { - if (ui->search->isVisible()) { - ui->search->setText(""); - ui->search->textChanged(""); - ui->search->setVisible(false); - } if (select_mode) { emit profile_selected(-1); select_mode = false; refresh_status(); } }); - connect(ui->search, &QLineEdit::textChanged, this, [=](const QString &text) { - if (text.isEmpty()) { - for (int i = 0; i < ui->proxyListTable->rowCount(); i++) { - ui->proxyListTable->setRowHidden(i, false); - } - } else { - QList findItem = ui->proxyListTable->findItems(text, Qt::MatchContains); - for (int i = 0; i < ui->proxyListTable->rowCount(); i++) { - ui->proxyListTable->setRowHidden(i, true); - } - for (auto item: findItem) { - if (item != nullptr) ui->proxyListTable->setRowHidden(item->row(), false); - } - } - }); // refresh this->refresh_groups(); @@ -953,6 +928,27 @@ void MainWindow::neko_set_spmode_vpn(bool enable, bool save) { if (NekoGui::dataStore->started_id >= 0) neko_start(NekoGui::dataStore->started_id); } +void MainWindow::UpdateDataView(const libcore::SpeedTestResult& result, const QString& profileName, bool clear) +{ + if (clear) + { + ui->data_view->clear(); + return; + } + QString html = QString( + "

Running Speedtest: %1

" + "

Dl↓ %2

" + "

Ul↑ %3

" + "

Server: %4, %5

" + ).arg(profileName, + result.dl_speed().c_str(), + result.ul_speed().c_str(), + result.server_country().c_str(), + result.server_name().c_str()); + ui->data_view->setHtml(html); +} + + void MainWindow::setupConnectionList() { ui->connections->horizontalHeader()->setHighlightSections(false); diff --git a/src/ui/mainwindow_grpc.cpp b/src/ui/mainwindow_grpc.cpp index d4cb1e3..544d8f9 100644 --- a/src/ui/mainwindow_grpc.cpp +++ b/src/ui/mainwindow_grpc.cpp @@ -223,8 +223,43 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, const QStr req.set_test_download(speedtestConf == NekoGui::TestConfig::FULL || speedtestConf == NekoGui::TestConfig::DL); req.set_test_upload(speedtestConf == NekoGui::TestConfig::FULL || speedtestConf == NekoGui::TestConfig::UL); + // loop query result + auto doneMu = new QMutex; + doneMu->lock(); + runOnNewThread([=] + { + bool ok; + while (true) { + QThread::msleep(100); + if (doneMu->tryLock()) + { + break; + } + auto res = defaultClient->QueryCurrentSpeedTests(&ok); + if (!ok || !res.is_running()) + { + continue; + } + auto profile = NekoGui::profileManager->GetProfile(tag2entID[res.result().outbound_tag().c_str()]); + if (profile == nullptr) + { + continue; + } + runOnUiThread([=] + { + UpdateDataView(res.result(), profile->bean->name, false); + }); + } + runOnUiThread([=] + { + UpdateDataView({}, {}, true); + }); + doneMu->unlock(); + delete doneMu; + }); bool rpcOK; auto result = defaultClient->SpeedTest(&rpcOK, req); + doneMu->unlock(); // if (!rpcOK) return;