Fix lots of bugs

This commit is contained in:
Nova 2025-11-17 12:49:11 +03:30
parent fa25de7b74
commit 6bacd1c7a3
24 changed files with 175 additions and 96 deletions

View File

@ -274,8 +274,8 @@ set(PROJECT_SOURCES
src/configs/generate.cpp
include/configs/common/utils.h
src/configs/common/utils.cpp
include/configs/outbounds/Custom.h
include/configs/outbounds/Chain.h
include/configs/outbounds/custom.h
include/configs/outbounds/chain.h
include/configs/outbounds/extracore.h
)

View File

@ -1,4 +1,5 @@
#pragma once
#include <QHostInfo>
#include "DialFields.h"
#include "multiplex.h"
#include "TLS.h"
@ -13,6 +14,7 @@ namespace Configs
QString name;
QString server;
int server_port = 0;
bool invalid = false;
std::shared_ptr<DialFields> dialFields = std::make_shared<DialFields>();
outbound()
@ -23,7 +25,19 @@ namespace Configs
_add(new configItem("dial_fields", dynamic_cast<JsonStore *>(dialFields.get()), jsonStore));
}
void ResolveDomainToIP(const std::function<void()> &onFinished);
void ResolveDomainToIP(const std::function<void()> &onFinished) {
bool noResolve = false;
if (IsIpAddress(server) || server.isEmpty()) noResolve = true;
if (noResolve) {
onFinished();
return;
}
QHostInfo::lookupHost(server, QApplication::instance(), [=, this](const QHostInfo &host) {
auto addrs = host.addresses();
if (!addrs.isEmpty()) server = addrs.first().toString();
onFinished();
});
}
virtual QString GetAddress()
{
@ -56,6 +70,8 @@ namespace Configs
virtual bool HasTLS() { return false; }
virtual bool MustTLS() { return false; }
virtual std::shared_ptr<TLS> GetTLS() { return std::make_shared<TLS>(); }
virtual std::shared_ptr<Transport> GetTransport() { return std::make_shared<Transport>(); }
@ -64,6 +80,17 @@ namespace Configs
virtual bool IsEndpoint() { return false; };
QString ExportJsonLink() {
auto json = ExportToJson();
QUrl url;
url.setScheme("json");
url.setHost("throne");
url.setFragment(QJsonObject2QString(json, true)
.toUtf8()
.toBase64(QByteArray::Base64UrlEncoding));
return url.toString();
}
// baseConfig overrides
bool ParseFromLink(const QString& link) override;
bool ParseFromJson(const QJsonObject& object) override;

View File

@ -58,7 +58,10 @@ namespace Configs
}
void saveMuxState(int state) {
if (state == 1) enabled = true;
if (state == 1) {
enabled = true;
return;
}
enabled = false;
if (state == 0) unspecified = true;
}

View File

@ -26,6 +26,10 @@ namespace Configs
return true;
}
bool MustTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "include/configs/common/Outbound.h"
#include "QJsonArray"
namespace Configs
{
@ -17,6 +18,21 @@ namespace Configs
QString DisplayAddress() override { return ""; };
bool ParseFromJson(const QJsonObject &object) override {
if (object.isEmpty()) return false;
if (object.contains("name")) name = object["name"].toString();
if (object.contains("list")) list = QJsonArray2QListInt(object["list"].toArray());
return true;
}
QJsonObject ExportToJson() override {
QJsonObject object;
object["name"] = name;
object["type"] = "chain";
object["list"] = QListInt2QJsonArray(list);
return object;
}
BuildResult Build() override
{
return {{}, "Cannot call Build on chain config"};

View File

@ -15,6 +15,23 @@ namespace Configs
_add(new configItem("type", &type, string));
}
bool ParseFromJson(const QJsonObject &object) override {
if (object.isEmpty()) return false;
if (object.contains("name")) name = object["name"].toString();
if (object.contains("subtype")) type = object["subtype"].toString();
if (object.contains("config")) config = object["config"].toString();
return true;
}
QJsonObject ExportToJson() override {
QJsonObject object;
object["name"] = name;
object["type"] = "custom";
object["subtype"] = type;
object["config"] = config;
return object;
}
QString GetAddress() override
{
if (type == "outbound") {

View File

@ -21,6 +21,31 @@ namespace Configs
_add(new configItem("no_logs", &noLogs, itemType::boolean));
};
bool ParseFromJson(const QJsonObject &object) override {
if (object.isEmpty()) return false;
if (object.contains("name")) name = object["name"].toString();
if (object.contains("socks_address")) socksAddress = object["socks_address"].toString();
if (object.contains("socks_port")) socksPort = object["socks_port"].toInt();
if (object.contains("extra_core_path")) extraCorePath = object["extra_core_path"].toString();
if (object.contains("extra_core_args")) extraCoreArgs = object["extra_core_args"].toString();
if (object.contains("extra_core_conf")) extraCoreConf = object["extra_core_conf"].toString();
if (object.contains("no_logs")) noLogs = object["no_logs"].toBool();
return true;
}
QJsonObject ExportToJson() override {
QJsonObject object;
object["name"] = name;
object["type"] = "extracore";
object["socks_address"] = socksAddress;
object["socks_port"] = socksPort;
object["extra_core_path"] = extraCorePath;
object["extra_core_args"] = extraCoreArgs;
object["extra_core_conf"] = extraCoreConf;
object["no_logs"] = noLogs;
return object;
}
QString DisplayType() override { return "ExtraCore"; };
BuildResult Build() override

View File

@ -38,6 +38,10 @@ namespace Configs
return true;
}
bool MustTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}

View File

@ -32,6 +32,10 @@ namespace Configs
return true;
}
bool MustTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}

View File

@ -36,6 +36,10 @@ namespace Configs
return true;
}
bool MustTLS() override {
return true;
}
std::shared_ptr<TLS> GetTLS() override {
return tls;
}

View File

@ -878,7 +878,7 @@
</action>
<action name="menu_copy_links_nkr">
<property name="text">
<string>Copy links of selected (Custom Links)</string>
<string>Copy links of selected (Json Links)</string>
</property>
<property name="shortcut">
<string notr="true">Ctrl+Alt+C</string>

View File

@ -40,7 +40,11 @@ namespace Configs {
}
BuildResult outbound::Build()
{
return {ExportToJson(), ""};
QJsonObject object;
if (!server.isEmpty()) object["server"] = server;
if (server_port > 0) object["server_port"] = server_port;
mergeJsonObjects(object, dialFields->Build().object);
return {object, ""};
}
}

View File

@ -152,7 +152,13 @@ namespace Configs {
if (!url.isValid()) return false;
auto query = QUrlQuery(url.query(QUrl::ComponentFormattingOption::FullyDecoded));
if (query.hasQueryItem("security")) enabled = query.queryItemValue("security").replace("reality", "tls").replace("none", "") == "tls";
if (query.hasQueryItem("security")) enabled = query.queryItemValue("security")
.replace("reality", "tls")
.replace("none", "")
.replace("0", "")
.replace("false", "tls")
.replace("1", "tls")
.replace("true", "tls") == "tls";
if (query.hasQueryItem("disable_sni")) disable_sni = query.queryItemValue("disable_sni").replace("1", "true") == "true";
if (query.hasQueryItem("sni")) server_name = query.queryItemValue("sni");
if (query.hasQueryItem("peer")) server_name = query.queryItemValue("peer");

View File

@ -67,7 +67,10 @@ namespace Configs {
if (query.hasQueryItem("type"))
{
type = query.queryItemValue("type");
if ((type == "tcp" && query.queryItemValue("headerType") == "http") || type == "h2") type = "http";
if ((type == "tcp" && query.queryItemValue("headerType") == "http") || type == "h2") {
type = "http";
method = "GET";
}
}
if (query.hasQueryItem("host")) host = query.queryItemValue("host");
if (query.hasQueryItem("path")) path = query.queryItemValue("path");

View File

@ -6,6 +6,7 @@
#include <QInputDialog>
#include <QUrlQuery>
#include <QJsonDocument>
#include "3rdparty/fkYAML/node.hpp"
@ -13,22 +14,6 @@ namespace Subscription {
GroupUpdater *groupUpdater = new GroupUpdater;
void RawUpdater_FixEnt(const std::shared_ptr<Configs::ProxyEntity> &ent) {
if (ent == nullptr) return;
auto stream = Configs::GetStreamSettings(ent->bean.get());
if (stream == nullptr) return;
// 1. "security"
if (stream->security == "none" || stream->security == "0" || stream->security == "false") {
stream->security = "";
} else if (stream->security == "1" || stream->security == "true") {
stream->security = "tls";
}
// 2. TLS SNI: v2rayN config builder generate sni like this, so set sni here for their format.
if (stream->security == "tls" && IsIpAddress(ent->bean->serverAddress) && (!stream->host.isEmpty()) && stream->sni.isEmpty()) {
stream->sni = stream->host;
}
}
int JsonEndIdx(const QString &str, int begin) {
int sz = str.length();
int counter = 1;
@ -106,18 +91,18 @@ namespace Subscription {
}
std::shared_ptr<Configs::ProxyEntity> ent;
bool needFix = true;
// Nekoray format
if (str.startsWith("nekoray://")) {
needFix = false;
// Json base64 link format
if (str.startsWith("json://")) {
auto link = QUrl(str);
if (!link.isValid()) return;
ent = Configs::ProfileManager::NewProxyEntity(link.host());
if (ent->bean->version == -114514) return;
auto j = DecodeB64IfValid(link.fragment().toUtf8(), QByteArray::Base64UrlEncoding);
if (j.isEmpty()) return;
ent->bean->FromJsonBytes(j);
auto dataBytes = DecodeB64IfValid(link.fragment().toUtf8(), QByteArray::Base64UrlEncoding);
if (dataBytes.isEmpty()) return;
auto data = QJsonDocument::fromJson(dataBytes).object();
if (data.isEmpty()) return;
ent = Configs::ProfileManager::NewProxyEntity(data["type"].toString());
if (ent->outbound->invalid) return;
ent->outbound->ParseFromJson(data);
}
// Json
@ -188,7 +173,6 @@ namespace Subscription {
// Hysteria1
if (str.startsWith("hysteria://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("hysteria");
auto ok = ent->Hysteria()->ParseFromLink(str);
if (!ok) return;
@ -196,7 +180,6 @@ namespace Subscription {
// Hysteria2
if (str.startsWith("hysteria2://") || str.startsWith("hy2://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("hysteria2");
auto ok = ent->Hysteria2()->ParseFromLink(str);
if (!ok) return;
@ -204,7 +187,6 @@ namespace Subscription {
// TUIC
if (str.startsWith("tuic://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("tuic");
auto ok = ent->TUIC()->ParseFromLink(str);
if (!ok) return;
@ -212,7 +194,6 @@ namespace Subscription {
// Wireguard
if (str.startsWith("wg://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("wireguard");
auto ok = ent->Wireguard()->ParseFromLink(str);
if (!ok) return;
@ -220,7 +201,6 @@ namespace Subscription {
// SSH
if (str.startsWith("ssh://")) {
needFix = false;
ent = Configs::ProfileManager::NewProxyEntity("ssh");
auto ok = ent->SSH()->ParseFromLink(str);
if (!ok) return;
@ -228,9 +208,6 @@ namespace Subscription {
if (ent == nullptr) return;
// Fix
if (needFix) RawUpdater_FixEnt(ent);
// End
updated_order += ent;
}
@ -817,7 +794,7 @@ namespace Subscription {
continue;
}
if (needFix) RawUpdater_FixEnt(ent);
// if (needFix) RawUpdater_FixEnt(ent); TODO
updated_order += ent;
}
} catch (const fkyaml::exception &ex) {
@ -927,7 +904,7 @@ namespace Subscription {
if (Configs::dataStore->sub_clear) {
// all is new profile
for (const auto &ent: out_all) {
change_text += "[+] " + ent->bean->DisplayTypeAndName() + "\n";
change_text += "[+] " + ent->outbound->DisplayTypeAndName() + "\n";
}
} else {
// find and delete not updated profile by ProfileFilter
@ -940,7 +917,7 @@ namespace Subscription {
if (only_out.size() < 1000)
{
for (const auto &ent: only_out) {
notice_added += "[+] " + ent->bean->DisplayTypeAndName() + "\n";
notice_added += "[+] " + ent->outbound->DisplayTypeAndName() + "\n";
}
} else
{
@ -949,7 +926,7 @@ namespace Subscription {
if (only_in.size() < 1000)
{
for (const auto &ent: only_in) {
notice_deleted += "[-] " + ent->bean->DisplayTypeAndName() + "\n";
notice_deleted += "[-] " + ent->outbound->DisplayTypeAndName() + "\n";
}
} else
{

View File

@ -283,6 +283,7 @@ namespace Configs {
} else {
bean = new Configs::AbstractBean(-114514);
outbound = new Configs::outbound();
outbound->invalid = true;
}
auto ent = std::make_shared<ProxyEntity>(outbound, bean, type);

View File

@ -191,7 +191,7 @@ namespace Configs {
MW_show_log("The outbound described in the rule chain is missing, maybe your data is corrupted");
return {};
}
obj["outbound"] = prof->bean->DisplayName();
obj["outbound"] = prof->outbound->DisplayName();
}
} else {
if (!outboundTag.isEmpty()) obj["outbound"] = outboundTag;
@ -511,7 +511,7 @@ namespace Configs {
if (name == "proxy") return -1;
if (name == "direct") return -2;
for (const auto& item: profileManager->profiles) {
if (item.second->bean->name == name) return item.first;
if (item.second->outbound->name == name) return item.first;
}
return INVALID_ID;

View File

@ -77,7 +77,7 @@ DialogEditGroup::DialogEditGroup(const std::shared_ptr<Configs::Group> &ent, QWi
QStringList links;
for (const auto &[_, profile]: Configs::profileManager->profiles) {
if (profile->gid != ent->id) continue;
links += profile->bean->ToShareLink();
links += profile->outbound->ExportToLink();
}
QApplication::clipboard()->setText(links.join("\n"));
MessageBoxInfo(software_name, tr("Copied"));
@ -86,7 +86,7 @@ DialogEditGroup::DialogEditGroup(const std::shared_ptr<Configs::Group> &ent, QWi
QStringList links;
for (const auto &[_, profile]: Configs::profileManager->profiles) {
if (profile->gid != ent->id) continue;
links += profile->bean->ToNekorayShareLink(profile->type);
links += profile->outbound->ExportToLink(); // TODO FIX neko link
}
QApplication::clipboard()->setText(links.join("\n"));
MessageBoxInfo(software_name, tr("Copied"));
@ -122,7 +122,7 @@ QStringList DialogEditGroup::load_proxy_items() {
QStringList res = QStringList();
auto profiles = Configs::profileManager->profiles;
for (const auto &item: profiles) {
res.push_back(item.second->bean->DisplayName());
res.push_back(item.second->outbound->DisplayName());
}
return res;
@ -131,7 +131,7 @@ QStringList DialogEditGroup::load_proxy_items() {
int DialogEditGroup::get_proxy_id(QString name) {
auto profiles = Configs::profileManager->profiles;
for (const auto &item: profiles) {
if (item.second->bean->DisplayName() == name) return item.first;
if (item.second->outbound->DisplayName() == name) return item.first;
}
return -1;
@ -139,5 +139,5 @@ int DialogEditGroup::get_proxy_id(QString name) {
QString DialogEditGroup::get_proxy_name(int id) {
auto profiles = Configs::profileManager->profiles;
return profiles.count(id) == 0 ? "None" : profiles[id]->bean->DisplayName();
return profiles.count(id) == 0 ? "None" : profiles[id]->outbound->DisplayName();
}

View File

@ -1678,7 +1678,6 @@ void MainWindow::on_menu_add_from_clipboard_triggered() {
Subscription::groupUpdater->AsyncUpdate(clipboard);
}
// TODO fix full export
void MainWindow::on_menu_clone_triggered() {
auto ents = get_now_selected_list();
if (ents.isEmpty()) return;
@ -1688,7 +1687,7 @@ void MainWindow::on_menu_clone_triggered() {
QStringList sls;
for (const auto &ent: ents) {
sls << ent->outbound->ExportToLink();
sls << ent->outbound->ExportJsonLink();
}
Subscription::groupUpdater->AsyncUpdate(sls.join("\n"));
@ -1765,7 +1764,7 @@ void MainWindow::on_menu_copy_links_nkr_triggered() {
auto ents = get_now_selected_list();
QStringList links;
for (const auto &ent: ents) {
links += ent->outbound->ExportToLink();
links += ent->outbound->ExportJsonLink();
}
if (links.length() == 0) return;
QApplication::clipboard()->setText(links.join("\n"));

View File

@ -83,7 +83,7 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0;
else {
ent->latency = -1;
MW_show_log(tr("[%1] test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
MW_show_log(tr("[%1] test error: %2").arg(ent->outbound->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
}
}
ent->Save();
@ -127,7 +127,7 @@ void MainWindow::runURLTest(const QString& config, bool useDefault, const QStrin
QString::fromStdString(res.error.value()).contains("context canceled")) ent->latency=0;
else {
ent->latency = -1;
MW_show_log(tr("[%1] test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
MW_show_log(tr("[%1] test error: %2").arg(ent->outbound->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
}
}
ent->Save();
@ -285,7 +285,7 @@ void MainWindow::querySpeedtest(QDateTime lastProxyListUpdate, const QMap<QStrin
runOnUiThread([=, this, &lastProxyListUpdate]
{
showSpeedtestData = true;
currentSptProfileName = profile->bean->name;
currentSptProfileName = profile->outbound->name;
currentTestResult = res.result.value();
UpdateDataView();
@ -414,7 +414,7 @@ void MainWindow::runSpeedTest(const QString& config, bool useDefault, bool testC
ent->ul_speed = "N/A";
ent->latency = -1;
ent->test_country = "";
MW_show_log(tr("[%1] speed test error: %2").arg(ent->bean->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
MW_show_log(tr("[%1] speed test error: %2").arg(ent->outbound->DisplayTypeAndName(), QString::fromStdString(res.error.value())));
}
ent->Save();
}
@ -578,9 +578,9 @@ void MainWindow::profile_start(int _id) {
}, true);
}
// do start
MW_show_log(">>>>>>>> " + tr("Starting profile %1").arg(ent->bean->DisplayTypeAndName()));
MW_show_log(">>>>>>>> " + tr("Starting profile %1").arg(ent->outbound->DisplayTypeAndName()));
if (!profile_start_stage2()) {
MW_show_log("<<<<<<<< " + tr("Failed to start profile %1").arg(ent->bean->DisplayTypeAndName()));
MW_show_log("<<<<<<<< " + tr("Failed to start profile %1").arg(ent->outbound->DisplayTypeAndName()));
}
mu_starting.unlock();
// cancel timeout
@ -664,7 +664,7 @@ void MainWindow::profile_stop(bool crash, bool block, bool manual) {
runOnNewThread([=, this, &blocker] {
// do stop
MW_show_log(">>>>>>>> " + tr("Stopping profile %1").arg(running->bean->DisplayTypeAndName()));
MW_show_log(">>>>>>>> " + tr("Stopping profile %1").arg(running->outbound->DisplayTypeAndName()));
if (!profile_stop_stage2()) {
MW_show_log("<<<<<<<< " + tr("Failed to stop, please restart the program."));
}

View File

@ -19,9 +19,9 @@ ProxyItem::~ProxyItem() {
}
void ProxyItem::refresh_data() {
ui->type->setText(ent->bean->DisplayType());
ui->name->setText(ent->bean->DisplayName());
ui->address->setText(ent->bean->DisplayAddress());
ui->type->setText(ent->outbound->DisplayType());
ui->name->setText(ent->outbound->DisplayName());
ui->address->setText(ent->outbound->DisplayAddress());
ui->traffic->setText(ent->traffic_data->DisplayTraffic());
ui->test_result->setText(ent->DisplayTestResult());
@ -36,7 +36,7 @@ void ProxyItem::refresh_data() {
void ProxyItem::on_remove_clicked() {
if (!this->remove_confirm ||
QMessageBox::question(this, tr("Confirmation"), tr("Remove %1?").arg(ent->bean->DisplayName())) == QMessageBox::StandardButton::Yes) {
QMessageBox::question(this, tr("Confirmation"), tr("Remove %1?").arg(ent->outbound->DisplayName())) == QMessageBox::StandardButton::Yes) {
// TODO do remove (or not) -> callback
delete item;
}

View File

@ -39,20 +39,7 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
network_title_base = ui->network_box->title();
connect(ui->network, &QComboBox::currentTextChanged, this, [=,this](const QString &txt) {
ui->network_box->setTitle(network_title_base.arg(txt));
if (txt == "tcp") {
ui->header_type->setVisible(true);
ui->header_type_l->setVisible(true);
ui->headers->setVisible(false);
ui->headers_l->setVisible(false);
ui->method->setVisible(false);
ui->method_l->setVisible(false);
ui->path->setVisible(true);
ui->path_l->setVisible(true);
ui->host->setVisible(true);
ui->host_l->setVisible(true);
} else if (txt == "grpc") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
if (txt == "grpc") {
ui->headers->setVisible(false);
ui->headers_l->setVisible(false);
ui->method->setVisible(false);
@ -62,8 +49,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(false);
ui->host_l->setVisible(false);
} else if (txt == "ws" || txt == "httpupgrade") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(true);
ui->headers_l->setVisible(true);
ui->method->setVisible(false);
@ -73,8 +58,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(true);
ui->host_l->setVisible(true);
} else if (txt == "http") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(true);
ui->headers_l->setVisible(true);
ui->method->setVisible(true);
@ -84,8 +67,6 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(true);
ui->host_l->setVisible(true);
} else {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(false);
ui->headers_l->setVisible(false);
ui->method->setVisible(false);
@ -164,8 +145,8 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
LOAD_TYPE("wireguard")
LOAD_TYPE("tailscale")
LOAD_TYPE("ssh")
ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "internal");
ui->type->addItem(tr("Custom (%1 config)").arg(software_core_name), "internal-full");
ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "outbound");
ui->type->addItem(tr("Custom (%1 config)").arg(software_core_name), "fullconfig");
ui->type->addItem(tr("Extra Core"), "extracore");
LOAD_TYPE("chain")
@ -259,7 +240,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
auto _innerWidget = new EditSSH(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
} else if (type == "internal" || type == "internal-full" || type == "custom") {
} else if (type == "outbound" || type == "fullconfig" || type == "custom") {
auto _innerWidget = new EditCustom(this);
innerWidget = _innerWidget;
innerEditor = _innerWidget;
@ -286,7 +267,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
}
// hide some widget
auto showAddressPort = type != "chain" && customType != "internal" && customType != "internal-full" && type != "extracore" && type != "tailscale";
auto showAddressPort = type != "chain" && customType != "outbound" && customType != "fullconfig" && type != "extracore" && type != "tailscale";
ui->address->setVisible(showAddressPort);
ui->address_l->setVisible(showAddressPort);
ui->port->setVisible(showAddressPort);
@ -296,8 +277,13 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->right_all_w->setVisible(true);
auto tls = ent->outbound->GetTLS();
auto transport = ent->outbound->GetTransport();
if (ent->outbound->MustTLS()) {
ui->security->setCurrentText("tls");
ui->security->setEnabled(false);
} else {
ui->security->setCurrentText(tls->enabled ? "tls" : "");
}
ui->network->setCurrentText(transport->type);
ui->security->setCurrentText(tls->enabled ? "tls" : "");
ui->path->setText(transport->path);
ui->host->setText(transport->host);
ui->method->setText(transport->method);
@ -357,11 +343,9 @@ void DialogEditProfile::typeSelected(const QString &newType) {
if (ent->outbound->HasTransport()) {
ui->network_l->setVisible(true);
ui->network->setVisible(true);
ui->network_box->setVisible(true);
} else {
ui->network_l->setVisible(false);
ui->network->setVisible(false);
ui->network_box->setVisible(false);
}
if (ent->outbound->HasTLS()) {
ui->security->setVisible(true);
@ -385,7 +369,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
}
ui->stream_box->setVisible(streamBoxVisible);
auto rightNoBox = (ui->stream_box->isHidden() && ui->network_box->isHidden() && ui->security_box->isHidden());
auto rightNoBox = (ui->security_box->isHidden() && ui->network_box->isHidden() && ui->tls_camouflage_box->isHidden());
if (rightNoBox && !ui->right_all_w->isHidden()) {
ui->right_all_w->setVisible(false);
}

View File

@ -3,6 +3,7 @@
EditTrojan::EditTrojan(QWidget *parent)
: QWidget(parent),
ui(new Ui::EditTrojan) {
ui->setupUi(this);
}
EditTrojan::~EditTrojan() {

View File

@ -33,7 +33,7 @@ QString get_outbound_name(int id) {
if (id == -1) return "proxy";
if (id == -2) return "direct";
auto profiles = Configs::profileManager->profiles;
if (profiles.count(id)) return profiles[id]->bean->name;
if (profiles.count(id)) return profiles[id]->outbound->name;
return "INVALID OUTBOUND";
}
@ -41,7 +41,7 @@ QStringList get_all_outbounds() {
QStringList res;
auto profiles = Configs::profileManager->profiles;
for (const auto &item: profiles) {
res.append(item.second->bean->DisplayName());
res.append(item.second->outbound->DisplayName());
}
return res;