diff --git a/db/ConfigBuilder.cpp b/db/ConfigBuilder.cpp index 655c7d5..56c03d4 100644 --- a/db/ConfigBuilder.cpp +++ b/db/ConfigBuilder.cpp @@ -856,6 +856,20 @@ namespace NekoRay { routeObj.remove("auto_detect_interface"); } status->result->coreConfig.insert("route", routeObj); + + // experimental + QJsonObject experimentalObj; + + if (NekoRay::dataStore->core_box_clash_api > 0) { + QJsonObject clash_api = { + {"external_controller", "127.0.0.1:" + Int2String(NekoRay::dataStore->core_box_clash_api)}, + {"secret", NekoRay::dataStore->core_box_clash_api_secret}, + {"external_ui", "dashboard"}, + }; + experimentalObj["clash_api"] = clash_api; + } + + if (!experimentalObj.isEmpty()) status->result->coreConfig.insert("experimental", experimentalObj); } QString WriteVPNSingBoxConfig() { diff --git a/main/NekoRay.cpp b/main/NekoRay.cpp index 267b200..cf27df0 100644 --- a/main/NekoRay.cpp +++ b/main/NekoRay.cpp @@ -76,6 +76,8 @@ namespace NekoRay { _add(new configItem("splitter_state", &splitter_state, itemType::string)); _add(new configItem("utlsFingerprint", &utlsFingerprint, itemType::string)); _add(new configItem("core_box_auto_detect_interface", &core_box_auto_detect_interface, itemType::boolean)); + _add(new configItem("core_box_clash_api", &core_box_clash_api, itemType::integer)); + _add(new configItem("core_box_clash_api_secret", &core_box_clash_api_secret, itemType::string)); #ifndef Q_OS_WIN _add(new configItem("vpn_already_admin", &vpn_already_admin, itemType::boolean)); #endif diff --git a/main/NekoRay_DataStore.hpp b/main/NekoRay_DataStore.hpp index 5d7ed11..b169a15 100644 --- a/main/NekoRay_DataStore.hpp +++ b/main/NekoRay_DataStore.hpp @@ -151,6 +151,8 @@ namespace NekoRay { // Core bool core_box_auto_detect_interface = true; + int core_box_clash_api = -9090; + QString core_box_clash_api_secret = ""; // Other Core ExtraCore *extraCore = new ExtraCore; diff --git a/res/dashboard-notice.html b/res/dashboard-notice.html new file mode 100644 index 0000000..9b6c344 --- /dev/null +++ b/res/dashboard-notice.html @@ -0,0 +1,13 @@ + + + + + +

+

Please put your clash dashboard files to "nekoray/config/dashboard" dir.

+

For example, you can download from the following URL.

+ Yacd-meta +

+ + + \ No newline at end of file diff --git a/res/neko.qrc b/res/neko.qrc index af5501c..6e1c3f2 100644 --- a/res/neko.qrc +++ b/res/neko.qrc @@ -20,5 +20,6 @@ neko.css vpn/vpn-run-root.sh vpn/sing-box-vpn.json + dashboard-notice.html diff --git a/sub/GroupUpdater.cpp b/sub/GroupUpdater.cpp index 3ed5fab..7dac2f2 100644 --- a/sub/GroupUpdater.cpp +++ b/sub/GroupUpdater.cpp @@ -406,6 +406,8 @@ namespace NekoRay::sub { content = resp.data; sub_user_info = NetworkRequestHelper::GetHeader(resp.header, "Subscription-UserInfo"); + + MW_show_log("<<<<<<<< " + QObject::tr("Subscription request fininshed: %1").arg(groupName)); } QList> in; // 更新前 @@ -461,11 +463,11 @@ namespace NekoRay::sub { QString notice_added; for (const auto &ent: only_out) { - notice_added += ent->bean->DisplayTypeAndName() + "\n"; + notice_added += "[+] " + ent->bean->DisplayTypeAndName() + "\n"; } QString notice_deleted; for (const auto &ent: only_in) { - notice_deleted += ent->bean->DisplayTypeAndName() + "\n"; + notice_deleted += "[-] " + ent->bean->DisplayTypeAndName() + "\n"; } auto change = "\n" + QObject::tr("Added %1 profiles:\n%2\nDeleted %3 Profiles:\n%4") diff --git a/translations/fa_IR.ts b/translations/fa_IR.ts index c23f112..67cbee5 100644 --- a/translations/fa_IR.ts +++ b/translations/fa_IR.ts @@ -1471,6 +1471,10 @@ Direct: %2 Enable System Proxy پروکسی سیستم را فعال کنید + + Subscription request fininshed: %1 + + Qv2ray::ui::widgets::AutoCompleteTextEdit diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts index 3c4702a..d040c37 100644 --- a/translations/zh_CN.ts +++ b/translations/zh_CN.ts @@ -1461,12 +1461,8 @@ As of January 1, 2022, compatibility with MD5 authentication information will be 正在清理服务器... - Enable VPN - 启用 VPN - - - Enable System Proxy - 启用系统代理 + Subscription request fininshed: %1 + 订阅请求完成: %1 diff --git a/ui/dialog_basic_settings.cpp b/ui/dialog_basic_settings.cpp index e41ce04..2be17c6 100644 --- a/ui/dialog_basic_settings.cpp +++ b/ui/dialog_basic_settings.cpp @@ -378,7 +378,7 @@ void DialogBasicSettings::on_inbound_auth_clicked() { connect(box, &QDialogButtonBox::accepted, w, [=] { NekoRay::dataStore->inbound_auth->username = user->text(); NekoRay::dataStore->inbound_auth->password = pass->text(); - NekoRay::dataStore->Save(); + MW_dialog_message(Dialog_DialogBasicSettings, "UpdateDataStore"); w->accept(); }); connect(box, &QDialogButtonBox::rejected, w, &QDialog::reject); @@ -397,12 +397,33 @@ void DialogBasicSettings::on_core_settings_clicked() { // auto line = -1; QCheckBox *core_box_auto_detect_interface; + QCheckBox *core_box_enable_clash_api; + QLineEdit *core_box_clash_api; + QLineEdit *core_box_clash_api_secret; if (IS_NEKO_BOX) { auto core_box_auto_detect_interface_l = new QLabel("auto_detect_interface"); core_box_auto_detect_interface = new QCheckBox; core_box_auto_detect_interface->setChecked(NekoRay::dataStore->core_box_auto_detect_interface); layout->addWidget(core_box_auto_detect_interface_l, ++line, 0); layout->addWidget(core_box_auto_detect_interface, line, 1); + // + auto core_box_enable_clash_api_l = new QLabel("Enable Clash API"); + core_box_enable_clash_api = new QCheckBox; + core_box_enable_clash_api->setChecked(NekoRay::dataStore->core_box_clash_api > 0); + layout->addWidget(core_box_enable_clash_api_l, ++line, 0); + layout->addWidget(core_box_enable_clash_api, line, 1); + // + auto core_box_clash_api_l = new QLabel("Clash API Listen Port"); + core_box_clash_api = new MyLineEdit; + core_box_clash_api->setText(Int2String(std::abs(NekoRay::dataStore->core_box_clash_api))); + layout->addWidget(core_box_clash_api_l, ++line, 0); + layout->addWidget(core_box_clash_api, line, 1); + // + auto core_box_clash_api_secret_l = new QLabel("Clash API Secret"); + core_box_clash_api_secret = new MyLineEdit; + core_box_clash_api_secret->setText(NekoRay::dataStore->core_box_clash_api_secret); + layout->addWidget(core_box_clash_api_secret_l, ++line, 0); + layout->addWidget(core_box_clash_api_secret, line, 1); } // auto box = new QDialogButtonBox; @@ -411,8 +432,10 @@ void DialogBasicSettings::on_core_settings_clicked() { connect(box, &QDialogButtonBox::accepted, w, [=] { if (IS_NEKO_BOX) { NekoRay::dataStore->core_box_auto_detect_interface = core_box_auto_detect_interface->isChecked(); + NekoRay::dataStore->core_box_clash_api = core_box_clash_api->text().toInt() * (core_box_enable_clash_api->isChecked() ? 1 : -1); + NekoRay::dataStore->core_box_clash_api_secret = core_box_clash_api_secret->text(); } - NekoRay::dataStore->Save(); + MW_dialog_message(Dialog_DialogBasicSettings, "UpdateDataStore"); w->accept(); }); connect(box, &QDialogButtonBox::rejected, w, &QDialog::reject); diff --git a/ui/dialog_basic_settings.ui b/ui/dialog_basic_settings.ui index d18ecb5..adc5edb 100644 --- a/ui/dialog_basic_settings.ui +++ b/ui/dialog_basic_settings.ui @@ -288,7 +288,7 @@ - + 0 0 diff --git a/ui/edit/edit_custom.ui b/ui/edit/edit_custom.ui index a34d6c4..4083657 100644 --- a/ui/edit/edit_custom.ui +++ b/ui/edit/edit_custom.ui @@ -31,13 +31,38 @@ + + + 0 + 0 + + true + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + 0 + 0 + + Json Editor diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index 5345495..f0ae6ab 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -100,6 +100,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi if (!Preset::SingBox::DomainStrategy.contains(NekoRay::dataStore->outbound_domain_strategy)) { NekoRay::dataStore->outbound_domain_strategy = ""; } + // + if (QDir("dashboard").isEmpty()) { + QDir().mkdir("dashboard"); + QFile::copy(":/neko/dashboard-notice.html", "dashboard/index.html"); + } } // top bar