diff --git a/fmt/Bean2CoreObj.cpp b/fmt/Bean2CoreObj.cpp
index 956c5a1..7fadac7 100644
--- a/fmt/Bean2CoreObj.cpp
+++ b/fmt/Bean2CoreObj.cpp
@@ -17,30 +17,34 @@ namespace NekoRay::fmt {
if (network == "ws") {
QJsonObject ws;
- if (!path.isEmpty()) ws["path"] = path;
- if (!host.isEmpty()) ws["headers"] = QJsonObject{{"Host", host}};
+ if (!path.trimmed().isEmpty()) ws["path"] = path;
+ if (!host.trimmed().isEmpty()) ws["headers"] = QJsonObject{{"Host", host}};
streamSettings["wsSettings"] = ws;
} else if (network == "h2") {
QJsonObject h2;
- if (!path.isEmpty()) h2["path"] = path;
- if (!host.isEmpty()) h2["host"] = QList2QJsonArray(host.split(","));
+ if (!path.trimmed().isEmpty()) h2["path"] = path;
+ if (!host.trimmed().isEmpty()) h2["host"] = QList2QJsonArray(host.split(","));
streamSettings["httpSettings"] = h2;
} else if (network == "grpc") {
QJsonObject grpc;
- if (!path.isEmpty()) grpc["serviceName"] = path;
+ if (!path.trimmed().isEmpty()) grpc["serviceName"] = path;
streamSettings["grpcSettings"] = grpc;
}
if (security == "tls") {
QJsonObject tls;
- if (!sni.isEmpty()) tls["serverName"] = sni;
if (allow_insecure || dataStore->skip_cert) tls["allowInsecure"] = true;
- if (!certificate.isEmpty())
+ if (!sni.trimmed().isEmpty()) tls["serverName"] = sni;
+ if (!certificate.trimmed().isEmpty()) {
tls["certificates"] = QJsonArray{
QJsonObject{
{"certificate", certificate},
},
};
+ }
+ if (!alpn.trimmed().isEmpty()) {
+ tls["alpn"] = QList2QJsonArray(alpn.split(","));
+ }
streamSettings["tlsSettings"] = tls;
}
@@ -94,7 +98,7 @@ namespace NekoRay::fmt {
servers.push_back(server);
settings["servers"] = servers;
- if (!plugin.isEmpty()) {
+ if (!plugin.trimmed().isEmpty()) {
settings["plugin"] = SubStrBefore(plugin, ";");
settings["pluginOpts"] = SubStrAfter(plugin, ";");
}
diff --git a/fmt/V2RayStreamSettings.hpp b/fmt/V2RayStreamSettings.hpp
index 023ad54..e40f463 100644
--- a/fmt/V2RayStreamSettings.hpp
+++ b/fmt/V2RayStreamSettings.hpp
@@ -11,13 +11,11 @@ namespace NekoRay::fmt {
// ws/h2/grpc
QString path = "";
QString host = "";
- // ws
- int max_early_data = 0;
- QString early_data_header_name = "";
// QUIC & KCP
QString header_type = "";
// tls
QString sni = "";
+ QString alpn = "";
QString certificate = "";
bool allow_insecure = false;
@@ -28,10 +26,9 @@ namespace NekoRay::fmt {
_add(new configItem("path", &path, itemType::string));
_add(new configItem("host", &host, itemType::string));
_add(new configItem("sni", &sni, itemType::string));
+ _add(new configItem("alpn", &alpn, itemType::string));
_add(new configItem("cert", &certificate, itemType::string));
_add(new configItem("insecure", &allow_insecure, itemType::boolean));
- _add(new configItem("ws_med", &max_early_data, itemType::integer));
- _add(new configItem("ws_edhn", &early_data_header_name, itemType::string));
_add(new configItem("h_type", &header_type, itemType::string));
}
diff --git a/sub/GroupUpdater.cpp b/sub/GroupUpdater.cpp
index acac972..fd04e3f 100644
--- a/sub/GroupUpdater.cpp
+++ b/sub/GroupUpdater.cpp
@@ -205,8 +205,6 @@ namespace NekoRay::sub {
}
}
bean->stream->path = Node2QString(ws["path"]);
- bean->stream->max_early_data = Node2Int(proxy["max-early-data"]);
- bean->stream->early_data_header_name = Node2QString(ws["early-data-header-name"]);
}
auto grpc = proxy["grpc-opts"];
diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts
index 67472ed..07bcd0f 100644
--- a/translations/zh_CN.ts
+++ b/translations/zh_CN.ts
@@ -273,10 +273,6 @@
Host
主机(Host)
-
- SNI
-
-
Custom
自定义
@@ -997,10 +993,6 @@ End: %2
Export V2ray config
导出 V2ray 配置
-
- QR Code and link (Nekoray)
- 显示 QR Code 和分享链接 (Nekoray)
-
Active Routing
当前路由规则
@@ -1085,6 +1077,10 @@ End: %2
Clone %1 item(s)
克隆 %1 个项目
+
+ Copy links of selected (Nekoray)
+ 批量复制选中项目的分享链接 (Nekoray)
+
ProxyItem
diff --git a/ui/edit/dialog_edit_profile.cpp b/ui/edit/dialog_edit_profile.cpp
index 7c0bb45..0765dd5 100644
--- a/ui/edit/dialog_edit_profile.cpp
+++ b/ui/edit/dialog_edit_profile.cpp
@@ -173,6 +173,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->path->setText(stream->path);
ui->host->setText(stream->host);
ui->sni->setText(stream->sni);
+ ui->alpn->setText(stream->alpn);
ui->insecure->setChecked(stream->allow_insecure);
CACHE.certificate = stream->certificate;
} else {
@@ -209,6 +210,14 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->port->setText(Int2String(ent->bean->serverPort));
ui->port->setValidator(QRegExpValidator_Number, this));
+ // 星号
+ for (auto label: findChildren()) {
+ auto text = label->text();
+ if (!label->toolTip().isEmpty() && !text.endsWith("*")) {
+ label->setText(text + "*");
+ }
+ }
+
editor_cache_updated_impl();
ADJUST_SIZE
@@ -238,6 +247,7 @@ void DialogEditProfile::accept() {
stream->path = ui->path->text();
stream->host = ui->host->text();
stream->sni = ui->sni->text();
+ stream->alpn = ui->alpn->text();
stream->allow_insecure = ui->insecure->isChecked();
stream->certificate = CACHE.certificate;
}
diff --git a/ui/edit/dialog_edit_profile.ui b/ui/edit/dialog_edit_profile.ui
index e801b96..3025501 100644
--- a/ui/edit/dialog_edit_profile.ui
+++ b/ui/edit/dialog_edit_profile.ui
@@ -157,6 +157,9 @@
0
+
+
+
QLayout::SetDefaultConstraint
@@ -365,27 +368,17 @@
-
-
-
+
-
PushButton
- -
-
-
- 服务器名称指示,明文。
-
-
- SNI
-
-
-
- -
+
-
- 固定证书
+
Certificate
@@ -395,6 +388,29 @@
-
+ -
+
+
+ 服务器名称指示,明文。
+
+
+ SNI
+
+
+
+ -
+
+
+ 应用层协议协商,明文。多个请以英文逗号分隔。
+
+
+ ALPN
+
+
+
+ -
+
+
diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp
index 9d2aa61..414aa2b 100644
--- a/ui/mainwindow.cpp
+++ b/ui/mainwindow.cpp
@@ -344,7 +344,6 @@ MainWindow::MainWindow(QWidget *parent)
connect(ui->menu_spmode_disabled, &QAction::triggered, this,
[=]() { neko_set_spmode(NekoRay::SystemProxyMode::DISABLE); });
connect(ui->menu_qr, &QAction::triggered, this, [=]() { display_qr_link(false); });
- connect(ui->menu_qr_nkr, &QAction::triggered, this, [=]() { display_qr_link(true); });
connect(ui->menu_tcp_ping, &QAction::triggered, this, [=]() { speedtest_current_group(0); });
connect(ui->menu_url_test, &QAction::triggered, this, [=]() { speedtest_current_group(1); });
connect(ui->menu_full_test, &QAction::triggered, this, [=]() { speedtest_current_group(2); });
@@ -963,6 +962,17 @@ void MainWindow::on_menu_copy_links_triggered() {
MessageBoxInfo("NekoRay", tr("Copied %1 item(s)").arg(links.length()));
}
+void MainWindow::on_menu_copy_links_nkr_triggered() {
+ auto ents = get_now_selected();
+ QStringList links;
+ for (const auto &ent: ents) {
+ links += ent->bean->ToNekorayShareLink(ent->type);
+ }
+ if (links.length() == 0) return;
+ QApplication::clipboard()->setText(links.join("\n"));
+ MessageBoxInfo("NekoRay", tr("Copied %1 item(s)").arg(links.length()));
+}
+
void MainWindow::on_menu_export_config_triggered() {
auto ents = get_now_selected();
if (ents.count() != 1) return;
diff --git a/ui/mainwindow.h b/ui/mainwindow.h
index efad682..c75c608 100644
--- a/ui/mainwindow.h
+++ b/ui/mainwindow.h
@@ -86,6 +86,8 @@ private slots:
void on_menu_copy_links_triggered();
+ void on_menu_copy_links_nkr_triggered();
+
void on_menu_export_config_triggered();
void display_qr_link(bool nkrFormat = false);
diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui
index f46afbb..eb1f824 100644
--- a/ui/mainwindow.ui
+++ b/ui/mainwindow.ui
@@ -512,10 +512,10 @@
Share
-
+