diff --git a/db/ConfigBuilder.cpp b/db/ConfigBuilder.cpp index b27d421..ff92425 100644 --- a/db/ConfigBuilder.cpp +++ b/db/ConfigBuilder.cpp @@ -451,12 +451,10 @@ namespace NekoGui { {"type", "block"}, {"tag", "block"}, }; - if (!status->forTest) { - status->outbounds += QJsonObject{ - {"type", "dns"}, - {"tag", "dns-out"}, - }; - } + status->outbounds += QJsonObject{ + {"type", "dns"}, + {"tag", "dns-out"}, + }; // custom inbound if (!status->forTest) QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray()) @@ -465,18 +463,14 @@ namespace NekoGui { // geopath auto geoip = FindCoreAsset("geoip.db"); auto geosite = FindCoreAsset("geosite.db"); - if (geoip.isEmpty()) status->result->error = +"geoip.db not found"; - if (geosite.isEmpty()) status->result->error = +"geosite.db not found"; + if (geoip.isEmpty()) status->result->error = +"geoip.db not found, it is needed for generating rule sets"; + if (geosite.isEmpty()) status->result->error = +"geosite.db not found, it is needed for generating rule sets"; // manage routing section auto routeObj = QJsonObject { {"auto_detect_interface", true}, }; - if (!status->forTest) routeObj["final"] = dataStore->routing->def_outbound; - if (status->forExport) { - routeObj.remove("geoip"); - routeObj.remove("geosite"); - } + routeObj["final"] = dataStore->routing->def_outbound; auto routeChain = NekoGui::profileManager->GetRouteChain(NekoGui::dataStore->routing->current_route_id); if (routeChain == nullptr) { @@ -537,39 +531,35 @@ namespace NekoGui { QJsonArray dnsRules; // Remote - if (!status->forTest) - dnsServers += QJsonObject{ - {"tag", "dns-remote"}, - {"address_resolver", "dns-local"}, - {"strategy", dataStore->routing->remote_dns_strategy}, - {"address", dataStore->routing->remote_dns}, - {"detour", tagProxy}, - }; + dnsServers += QJsonObject{ + {"tag", "dns-remote"}, + {"address_resolver", "dns-local"}, + {"strategy", dataStore->routing->remote_dns_strategy}, + {"address", dataStore->routing->remote_dns}, + {"detour", tagProxy}, + }; // Direct auto directDNSAddress = dataStore->routing->direct_dns; if (directDNSAddress == "localhost") directDNSAddress = BOX_UNDERLYING_DNS_EXPORT; - if (!status->forTest) { - QJsonObject directObj{ - {"tag", "dns-direct"}, - {"address_resolver", "dns-local"}, - {"strategy", dataStore->routing->direct_dns_strategy}, - {"address", directDNSAddress.replace("+local://", "://")}, - {"detour", "direct"}, - }; - if (dataStore->routing->dns_final_out == "direct") { - dnsServers.prepend(directObj); - } else { - dnsServers.append(directObj); - } + QJsonObject directObj{ + {"tag", "dns-direct"}, + {"address_resolver", "dns-local"}, + {"strategy", dataStore->routing->direct_dns_strategy}, + {"address", directDNSAddress.replace("+local://", "://")}, + {"detour", "direct"}, + }; + if (dataStore->routing->dns_final_out == "direct") { + dnsServers.prepend(directObj); + } else { + dnsServers.append(directObj); } // block - if (!status->forTest) - dnsServers += QJsonObject{ - {"tag", "dns-block"}, - {"address", "rcode://success"}, - }; + dnsServers += QJsonObject{ + {"tag", "dns-block"}, + {"address", "rcode://success"}, + }; // Fakedns if (dataStore->fake_dns && dataStore->spmode_vpn && !status->forTest) { diff --git a/db/Database.hpp b/db/Database.hpp index a9fd345..3efe0c6 100644 --- a/db/Database.hpp +++ b/db/Database.hpp @@ -6,6 +6,8 @@ #include "RouteEntity.h" namespace NekoGui { + const int INVALID_ID = -99999; + class ProfileManager : private JsonStore { public: // JsonStore diff --git a/go/grpc_server/update.go b/go/grpc_server/update.go index c46fa5d..470798f 100644 --- a/go/grpc_server/update.go +++ b/go/grpc_server/update.go @@ -48,8 +48,6 @@ func (s *BaseServer) Update(ctx context.Context, in *gen.UpdateReq) (*gen.Update return ret, nil } - nowVer := strings.TrimLeft(neko_common.Version_neko, "nekoray-") - var search string if runtime.GOOS == "windows" && runtime.GOARCH == "amd64" { search = "windows64" @@ -69,13 +67,7 @@ func (s *BaseServer) Update(ctx context.Context, in *gen.UpdateReq) (*gen.Update for _, release := range v { if len(release.Assets) > 0 { for _, asset := range release.Assets { - if strings.Contains(asset.Name, nowVer) { - return ret, nil // No update - } if strings.Contains(asset.Name, search) { - if release.Prerelease && !in.CheckPreRelease { - continue - } update_download_url = asset.BrowserDownloadUrl ret.AssetsName = asset.Name ret.DownloadUrl = asset.BrowserDownloadUrl diff --git a/main/NekoGui_DataStore.hpp b/main/NekoGui_DataStore.hpp index 621dcaa..ac0e374 100644 --- a/main/NekoGui_DataStore.hpp +++ b/main/NekoGui_DataStore.hpp @@ -99,7 +99,7 @@ namespace NekoGui { QString v2ray_asset_dir = ""; int language = 0; QString mw_size = ""; - bool check_include_pre = false; + bool check_include_pre = true; QString system_proxy_format = ""; QStringList log_ignore = {}; bool start_minimal = false; diff --git a/nekoray_version.txt b/nekoray_version.txt index 0b49813..312a4ad 100644 --- a/nekoray_version.txt +++ b/nekoray_version.txt @@ -1 +1 @@ -4.0.8-beta.1-2024-06-16 +4.0.8-beta.2-2024-06-16 diff --git a/ui/mainwindow_grpc.cpp b/ui/mainwindow_grpc.cpp index 48402e4..64339dc 100644 --- a/ui/mainwindow_grpc.cpp +++ b/ui/mainwindow_grpc.cpp @@ -55,6 +55,11 @@ inline bool speedtesting = false; inline QList speedtesting_threads = {}; void MainWindow::speedtest_current_group(int mode) { + if (speedtesting) { + MessageBoxWarning(software_name, "The last speed test did not exit completely, please wait. If it persists, please restart the program."); + return; + } + auto profiles = get_selected_or_group(); if (profiles.isEmpty()) return; auto group = NekoGui::profileManager->CurrentGroup(); @@ -70,11 +75,6 @@ void MainWindow::speedtest_current_group(int mode) { return; } - if (speedtesting) { - MessageBoxWarning(software_name, "The last speed test did not exit completely, please wait. If it persists, please restart the program."); - return; - } - QStringList full_test_flags; if (mode == libcore::FullTest) { auto w = new QDialog(this); @@ -136,7 +136,6 @@ void MainWindow::speedtest_current_group(int mode) { } lock_write.unlock(); // quit of this thread - speedtesting_threads.removeAll(QObject::thread()); return; } auto profile = profiles_test.takeFirst(); @@ -232,6 +231,7 @@ void MainWindow::speedtest_current_group(int mode) { // Control lock_return.lock(); lock_return.unlock(); + speedtesting_threads.removeAll(QObject::thread()); speedtesting = false; }); } @@ -471,6 +471,58 @@ void MainWindow::neko_stop(bool crash, bool sem) { }); } +bool isNewer(QString version) { + version = version.mid(8); // take out nekoray- + auto parts = version.split('.'); + auto currentParts = QString(NKR_VERSION).split('.'); + std::vector verNums; + std::vector currNums; + // add base version first + verNums.push_back(parts[0].toInt()); + verNums.push_back(parts[1].toInt()); + verNums.push_back(parts[2].split('-')[0].toInt()); + + currNums.push_back(currentParts[0].toInt()); + currNums.push_back(currentParts[1].toInt()); + currNums.push_back(currentParts[2].split('-')[0].toInt()); + + // base version is equal or greater, check release mode + int releaseMode; + int partialVer = 0; + if (parts[2].split('-').size() > 1 && parts[2].split('-')[1].toInt() == 0 /* this makes sure it is not a number*/) { + partialVer = parts[3].split('-')[0].toInt(); + auto str = parts[2].split('-')[1]; + if (str == "rc") releaseMode = 3; + if (str == "beta") releaseMode = 2; + if (str == "alpha") releaseMode = 1; + } else { + releaseMode = 4; + } + verNums.push_back(releaseMode); + verNums.push_back(partialVer); + + int currReleaseMode; + int currentPartialVer = 0; + if (currentParts[2].split('-').size() > 1 && currentParts[2].split('-')[1].toInt() == 0 /* this makes sure it is not a number*/) { + currentPartialVer = currentParts[3].split('-')[0].toInt(); + auto str = currentParts[2].split('-')[1]; + if (str == "rc") currReleaseMode = 3; + if (str == "beta") currReleaseMode = 2; + if (str == "alpha") currReleaseMode = 1; + } else { + currReleaseMode = 4; + } + currNums.push_back(currReleaseMode); + currNums.push_back(currentPartialVer); + + for (int i=0;i currNums[i]) return true; + if (verNums[i] < currNums[i]) return false; + } + + return false; +} + void MainWindow::CheckUpdate() { // on new thread... bool ok; @@ -488,7 +540,7 @@ void MainWindow::CheckUpdate() { return; } - if (response.release_download_url() == nullptr || QString(response.assets_name().c_str()).contains(NKR_VERSION)) { + if (response.release_download_url() == nullptr || !isNewer(QString(response.assets_name().c_str()))) { runOnUiThread([=] { MessageBoxInfo(QObject::tr("Update"), QObject::tr("No update")); }); diff --git a/ui/widget/RouteItem.cpp b/ui/widget/RouteItem.cpp index e176c66..cb277cb 100644 --- a/ui/widget/RouteItem.cpp +++ b/ui/widget/RouteItem.cpp @@ -33,7 +33,7 @@ int get_outbound_id(const QString& name) { if (item.second->bean->name == name) return item.first; } - return -1; + return NekoGui::INVALID_ID; } QStringList get_all_outbounds() { @@ -103,6 +103,14 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptrprofiles) { + outboundMap[outboundMap.size()] = item.second->id; + } ui->route_name->setText(chain->name); ui->rule_attr->addItems(NekoGui::RouteRule::get_attributes()); @@ -146,8 +154,8 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptrrule_out, &QComboBox::currentTextChanged, this, [=](const QString& text) { if (currentIndex == -1) return; - auto id = get_outbound_id(text); - if (id == -1) { + auto id = outboundMap[ui->rule_out->currentIndex()]; // we need to do this to avoid defining a seprate function for SLOT, as Qt 5 does not support lambda for currentIndexChanged... + if (id == NekoGui::INVALID_ID) { MessageBoxWarning("Invalid state", "selected outbound does not exists in the database, try restarting the app."); return; } diff --git a/ui/widget/RouteItem.h b/ui/widget/RouteItem.h index 4b8ce2a..43688d5 100644 --- a/ui/widget/RouteItem.h +++ b/ui/widget/RouteItem.h @@ -39,6 +39,8 @@ private: QShortcut* deleteShortcut; + std::map outboundMap; + [[nodiscard]] int getIndexOf(const QString& name) const; void showSelectItem(const QStringList& items, const QString& currentItem);