mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-18 04:54:38 +03:00
update ui
This commit is contained in:
@@ -136,12 +136,11 @@ namespace NekoGui {
|
||||
if (latency < 0) {
|
||||
return Qt::red;
|
||||
} else if (latency > 0) {
|
||||
if (latency < 100) {
|
||||
auto greenMs = dataStore->test_latency_url.startsWith("https://") ? 200 : 100;
|
||||
if (latency < greenMs) {
|
||||
return Qt::darkGreen;
|
||||
} else if (latency < 200) {
|
||||
return Qt::darkYellow;
|
||||
} else {
|
||||
return Qt::red;
|
||||
return Qt::darkYellow;
|
||||
}
|
||||
} else {
|
||||
return {};
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace NekoGui_fmt {
|
||||
return core;
|
||||
};
|
||||
|
||||
QString DisplayCoreType() override { return NeedExternal(false) ? core : software_core_name; };
|
||||
QString DisplayCoreType() override { return NeedExternal(true) == 0 ? software_core_name : core; };
|
||||
|
||||
QString DisplayAddress() override {
|
||||
if (core == "internal") {
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace NekoGui_fmt {
|
||||
return ::DisplayAddress(serverAddress, serverPort);
|
||||
}
|
||||
|
||||
QString DisplayCoreType() override { return NeedExternal(false) == 0 ? software_core_name : "Hysteria"; };
|
||||
QString DisplayCoreType() override { return NeedExternal(true) == 0 ? software_core_name : "Hysteria"; };
|
||||
|
||||
QString DisplayType() override { return "Hysteria"; };
|
||||
|
||||
|
||||
12
go/cmd/updater/launcher.go
Normal file
12
go/cmd/updater/launcher.go
Normal file
@@ -0,0 +1,12 @@
|
||||
//go:build !linux
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func Launcher() {
|
||||
log.Fatalln("launcher is not for your platform", runtime.GOOS)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package main
|
||||
|
||||
func Launcher() {
|
||||
println("?")
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func Launcher() {
|
||||
log.Fatalf("launcher is not for your platform", runtime.GOOS)
|
||||
}
|
||||
7
go/cmd/updater/msgbox.go
Normal file
7
go/cmd/updater/msgbox.go
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build !windows
|
||||
|
||||
package main
|
||||
|
||||
func MessageBoxPlain(title, caption string) int {
|
||||
return 0
|
||||
}
|
||||
26
go/cmd/updater/msgbox_windows.go
Normal file
26
go/cmd/updater/msgbox_windows.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// MessageBoxPlain of Win32 API.
|
||||
func MessageBoxPlain(title, caption string) int {
|
||||
const (
|
||||
NULL = 0
|
||||
MB_OK = 0
|
||||
)
|
||||
return MessageBox(NULL, caption, title, MB_OK)
|
||||
}
|
||||
|
||||
// MessageBox of Win32 API.
|
||||
func MessageBox(hwnd uintptr, caption, title string, flags uint) int {
|
||||
ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call(
|
||||
uintptr(hwnd),
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))),
|
||||
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))),
|
||||
uintptr(flags))
|
||||
|
||||
return int(ret)
|
||||
}
|
||||
@@ -64,6 +64,7 @@ func Updater() {
|
||||
// update move
|
||||
err := Mv("./nekoray_update/nekoray", "./")
|
||||
if err != nil {
|
||||
MessageBoxPlain("NekoGui Updater", "Update failed. Please close the running instance and run the updater again.\n\n"+err.Error())
|
||||
log.Fatalln(err.Error())
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <random>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QUrlQuery>
|
||||
#include <QTcpServer>
|
||||
#include <QTimer>
|
||||
@@ -194,9 +195,12 @@ QString DisplayTime(long long time, int formatType) {
|
||||
}
|
||||
|
||||
QWidget *GetMessageBoxParent() {
|
||||
if (mainwindow == nullptr) return nullptr;
|
||||
auto activeWindow = QApplication::activeWindow();
|
||||
if (activeWindow == nullptr && mainwindow != nullptr) {
|
||||
if (mainwindow->isVisible()) return mainwindow;
|
||||
return nullptr;
|
||||
}
|
||||
return activeWindow;
|
||||
}
|
||||
|
||||
int MessageBoxWarning(const QString &title, const QString &text) {
|
||||
|
||||
@@ -769,6 +769,10 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
<source>Select Profile</source>
|
||||
<translation>انتخاب کردن پروفایل</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Name cannot be empty.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditCustom</name>
|
||||
@@ -816,6 +820,10 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
<source>Please fill the complete config.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Name cannot be empty.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditHysteria</name>
|
||||
@@ -1360,10 +1368,6 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
<source>Remove %1 item(s) ?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reset traffic of %1 item(s) ?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copied %1 item(s)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
|
||||
@@ -767,6 +767,10 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
<source>Traffic order is from top to bottom</source>
|
||||
<translation>流量顺序是从上到下(最后一个配置为流量的出口)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Name cannot be empty.</source>
|
||||
<translation>名称 不能为空</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditCustom</name>
|
||||
@@ -814,6 +818,10 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
<source>Please fill the complete config.</source>
|
||||
<translation>请填写完整配置。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Name cannot be empty.</source>
|
||||
<translation>名称 不能为空</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditHysteria</name>
|
||||
@@ -1169,10 +1177,6 @@ This needs to be run NekoBox with administrator privileges.</source>
|
||||
<source>Remove %1 item(s) ?</source>
|
||||
<translation>删除 %1 个项目?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Reset traffic of %1 item(s) ?</source>
|
||||
<translation>重置 %1 个项目的流量?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Config copied</source>
|
||||
<translation>配置已复制</translation>
|
||||
|
||||
@@ -522,22 +522,25 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_22">
|
||||
<item>
|
||||
<widget class="QWidget" name="assest_group" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Asset Location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="MyLineEdit" name="core_v2ray_asset">
|
||||
<property name="placeholderText">
|
||||
<string>Default: dir of "nekoray"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="core_v2ray_asset_pick">
|
||||
<property name="text">
|
||||
<string>Select</string>
|
||||
@@ -546,72 +549,32 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_21">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Switch core</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="switch_core_v2ray">
|
||||
<property name="text">
|
||||
<string notr="true">V2Ray</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="switch_core_sing_box">
|
||||
<property name="text">
|
||||
<string notr="true">sing-box</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_log">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string notr="true">Loglevel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="log_level"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_mux">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="log_level">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_17">
|
||||
<item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Multiplex (mux)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="mux_protocol"/>
|
||||
</item>
|
||||
@@ -633,6 +596,8 @@
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -644,6 +609,58 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Switch core</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_21">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="switch_core_v2ray">
|
||||
<property name="text">
|
||||
<string notr="true">V2Ray</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="switch_core_sing_box">
|
||||
<property name="text">
|
||||
<string notr="true">sing-box</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_6">
|
||||
<attribute name="title">
|
||||
<string>Extra Core</string>
|
||||
@@ -662,8 +679,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>568</width>
|
||||
<height>297</height>
|
||||
<width>198</width>
|
||||
<height>58</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
|
||||
@@ -333,16 +333,16 @@ void DialogEditProfile::typeSelected(const QString &newType) {
|
||||
}
|
||||
|
||||
bool DialogEditProfile::onEnd() {
|
||||
// 左边
|
||||
ent->bean->name = ui->name->text();
|
||||
ent->bean->serverAddress = ui->address->text();
|
||||
ent->bean->serverPort = ui->port->text().toInt();
|
||||
|
||||
// bean
|
||||
if (!innerEditor->onEnd()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 左边
|
||||
ent->bean->name = ui->name->text();
|
||||
ent->bean->serverAddress = ui->address->text();
|
||||
ent->bean->serverPort = ui->port->text().toInt();
|
||||
|
||||
// 右边 stream
|
||||
auto stream = GetStreamSettings(ent->bean.get());
|
||||
if (stream != nullptr) {
|
||||
|
||||
@@ -25,6 +25,11 @@ void EditChain::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
||||
}
|
||||
|
||||
bool EditChain::onEnd() {
|
||||
if (get_edit_text_name().isEmpty()) {
|
||||
MessageBoxWarning(software_name, tr("Name cannot be empty."));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bean = this->ent->ChainBean();
|
||||
|
||||
QList<int> idList;
|
||||
|
||||
@@ -129,15 +129,19 @@ void EditCustom::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
||||
}
|
||||
|
||||
bool EditCustom::onEnd() {
|
||||
auto bean = this->ent->CustomBean();
|
||||
|
||||
SAVE_CUSTOM_BEAN
|
||||
|
||||
if (bean->core.isEmpty()) {
|
||||
if (get_edit_text_name().isEmpty()) {
|
||||
MessageBoxWarning(software_name, tr("Name cannot be empty."));
|
||||
return false;
|
||||
}
|
||||
if (ui->core->currentText().isEmpty()) {
|
||||
MessageBoxWarning(software_name, tr("Please pick a core."));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto bean = this->ent->CustomBean();
|
||||
|
||||
SAVE_CUSTOM_BEAN
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -529,12 +529,18 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info)
|
||||
refresh_status();
|
||||
}
|
||||
if (info.contains("UpdateDataStore")) {
|
||||
auto changed = NekoGui::dataStore->Save();
|
||||
if (info.contains("RouteChanged")) changed = true;
|
||||
auto suggestRestartProxy = NekoGui::dataStore->Save();
|
||||
if (info.contains("RouteChanged")) {
|
||||
suggestRestartProxy = true;
|
||||
}
|
||||
if (info.contains("NeedRestart")) {
|
||||
suggestRestartProxy = false;
|
||||
}
|
||||
refresh_proxy_list();
|
||||
if (info.contains("VPNChanged") && NekoGui::dataStore->spmode_vpn) {
|
||||
MessageBoxWarning(tr("VPN settings changed"), tr("Restart VPN to take effect."));
|
||||
} else if (changed && NekoGui::dataStore->started_id >= 0 &&
|
||||
}
|
||||
if (suggestRestartProxy && NekoGui::dataStore->started_id >= 0 &&
|
||||
QMessageBox::question(GetMessageBoxParent(), tr("Confirmation"), tr("Settings changed, restart proxy?")) == QMessageBox::StandardButton::Yes) {
|
||||
neko_start(NekoGui::dataStore->started_id);
|
||||
}
|
||||
@@ -1141,13 +1147,11 @@ void MainWindow::on_menu_delete_triggered() {
|
||||
void MainWindow::on_menu_reset_traffic_triggered() {
|
||||
auto ents = get_now_selected();
|
||||
if (ents.count() == 0) return;
|
||||
if (QMessageBox::question(this, tr("Confirmation"), QString(tr("Reset traffic of %1 item(s) ?")).arg(ents.count())) == QMessageBox::StandardButton::Yes) {
|
||||
for (const auto &ent: ents) {
|
||||
ent->traffic_data->Reset();
|
||||
ent->Save();
|
||||
refresh_proxy_list(ent->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_menu_profile_debug_info_triggered() {
|
||||
@@ -1193,10 +1197,10 @@ void MainWindow::on_menu_export_config_triggered() {
|
||||
auto ents = get_now_selected();
|
||||
if (ents.count() != 1) return;
|
||||
auto ent = ents.first();
|
||||
QString config_core;
|
||||
if (ent->bean->DisplayCoreType() != software_core_name) return;
|
||||
|
||||
auto result = BuildConfig(ent, false, true);
|
||||
config_core = QJsonObject2QString(result->coreConfig, true);
|
||||
QString config_core = QJsonObject2QString(result->coreConfig, true);
|
||||
QApplication::clipboard()->setText(config_core);
|
||||
|
||||
QMessageBox msg(QMessageBox::Information, tr("Config copied"), config_core);
|
||||
|
||||
@@ -684,6 +684,9 @@
|
||||
<property name="text">
|
||||
<string>Export %1 config</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string notr="true">Ctrl+E</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_reset_traffic">
|
||||
<property name="text">
|
||||
|
||||
Reference in New Issue
Block a user