mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 12:34:37 +03:00
feat: Automatic update subscription
This commit is contained in:
@@ -1061,7 +1061,6 @@ namespace NekoGui {
|
|||||||
auto configFn = ":/neko/vpn/sing-box-vpn.json";
|
auto configFn = ":/neko/vpn/sing-box-vpn.json";
|
||||||
if (QFile::exists("vpn/sing-box-vpn.json")) configFn = "vpn/sing-box-vpn.json";
|
if (QFile::exists("vpn/sing-box-vpn.json")) configFn = "vpn/sing-box-vpn.json";
|
||||||
auto config = ReadFileText(configFn)
|
auto config = ReadFileText(configFn)
|
||||||
.replace("%ENABLED_FAKEDNS%", dataStore->fake_dns ? "true" : "false")
|
|
||||||
.replace("//%IPV6_ADDRESS%", dataStore->vpn_ipv6 ? R"("inet6_address": "fdfe:dcba:9876::1/126",)" : "")
|
.replace("//%IPV6_ADDRESS%", dataStore->vpn_ipv6 ? R"("inet6_address": "fdfe:dcba:9876::1/126",)" : "")
|
||||||
.replace("//%SOCKS_USER_PASS%", socks_user_pass)
|
.replace("//%SOCKS_USER_PASS%", socks_user_pass)
|
||||||
.replace("//%PROCESS_NAME_RULE%", process_name_rule)
|
.replace("//%PROCESS_NAME_RULE%", process_name_rule)
|
||||||
@@ -1072,6 +1071,7 @@ namespace NekoGui {
|
|||||||
.replace("%STRICT_ROUTE%", dataStore->vpn_strict_route ? "true" : "false")
|
.replace("%STRICT_ROUTE%", dataStore->vpn_strict_route ? "true" : "false")
|
||||||
.replace("%FINAL_OUT%", no_match_out)
|
.replace("%FINAL_OUT%", no_match_out)
|
||||||
.replace("%DNS_ADDRESS%", BOX_UNDERLYING_DNS)
|
.replace("%DNS_ADDRESS%", BOX_UNDERLYING_DNS)
|
||||||
|
.replace("%FAKE_DNS_ENABLE%", dataStore->fake_dns ? "true" : "false")
|
||||||
.replace("%FAKE_DNS_INBOUND%", dataStore->fake_dns ? "tun-in" : "empty")
|
.replace("%FAKE_DNS_INBOUND%", dataStore->fake_dns ? "tun-in" : "empty")
|
||||||
.replace("%PORT%", Int2String(dataStore->inbound_socks_port));
|
.replace("%PORT%", Int2String(dataStore->inbound_socks_port));
|
||||||
// hook.js
|
// hook.js
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ namespace NekoGui {
|
|||||||
_add(new configItem("id", &id, itemType::integer));
|
_add(new configItem("id", &id, itemType::integer));
|
||||||
_add(new configItem("front_proxy_id", &front_proxy_id, itemType::integer));
|
_add(new configItem("front_proxy_id", &front_proxy_id, itemType::integer));
|
||||||
_add(new configItem("archive", &archive, itemType::boolean));
|
_add(new configItem("archive", &archive, itemType::boolean));
|
||||||
|
_add(new configItem("skip_auto_update", &skip_auto_update, itemType::boolean));
|
||||||
_add(new configItem("name", &name, itemType::string));
|
_add(new configItem("name", &name, itemType::string));
|
||||||
_add(new configItem("order", &order, itemType::integerList));
|
_add(new configItem("order", &order, itemType::integerList));
|
||||||
_add(new configItem("url", &url, itemType::string));
|
_add(new configItem("url", &url, itemType::string));
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace NekoGui {
|
|||||||
public:
|
public:
|
||||||
int id = -1;
|
int id = -1;
|
||||||
bool archive = false;
|
bool archive = false;
|
||||||
|
bool skip_auto_update = false;
|
||||||
QString name = "";
|
QString name = "";
|
||||||
QString url = "";
|
QString url = "";
|
||||||
QString info = "";
|
QString info = "";
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <QNetworkProxy>
|
#include <QNetworkProxy>
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "main/NekoGui.hpp"
|
#include "main/NekoGui.hpp"
|
||||||
|
|
||||||
@@ -52,12 +53,21 @@ namespace NekoGui_network {
|
|||||||
}
|
}
|
||||||
MW_show_log(QString("SSL Errors: %1 %2").arg(error_str.join(","), NekoGui::dataStore->sub_insecure ? "(Ignored)" : ""));
|
MW_show_log(QString("SSL Errors: %1 %2").arg(error_str.join(","), NekoGui::dataStore->sub_insecure ? "(Ignored)" : ""));
|
||||||
});
|
});
|
||||||
//
|
// Wait for response
|
||||||
|
auto abortTimer = new QTimer;
|
||||||
|
abortTimer->setSingleShot(true);
|
||||||
|
abortTimer->setInterval(10000);
|
||||||
|
QObject::connect(abortTimer, &QTimer::timeout, _reply, &QNetworkReply::abort);
|
||||||
|
abortTimer->start();
|
||||||
{
|
{
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
QObject::connect(&accessManager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
|
QObject::connect(_reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||||
loop.exec();
|
loop.exec();
|
||||||
}
|
}
|
||||||
|
if (abortTimer != nullptr) {
|
||||||
|
abortTimer->stop();
|
||||||
|
abortTimer->deleteLater();
|
||||||
|
}
|
||||||
//
|
//
|
||||||
auto result = NekoHTTPResponse{_reply->error() == QNetworkReply::NetworkError::NoError ? "" : _reply->errorString(),
|
auto result = NekoHTTPResponse{_reply->error() == QNetworkReply::NetworkError::NoError ? "" : _reply->errorString(),
|
||||||
_reply->readAll(), _reply->rawHeaderPairs()};
|
_reply->readAll(), _reply->rawHeaderPairs()};
|
||||||
|
|||||||
@@ -271,6 +271,7 @@ namespace NekoGui {
|
|||||||
_add(new configItem("sp_format", &system_proxy_format, itemType::string));
|
_add(new configItem("sp_format", &system_proxy_format, itemType::string));
|
||||||
_add(new configItem("sub_clear", &sub_clear, itemType::boolean));
|
_add(new configItem("sub_clear", &sub_clear, itemType::boolean));
|
||||||
_add(new configItem("sub_insecure", &sub_insecure, itemType::boolean));
|
_add(new configItem("sub_insecure", &sub_insecure, itemType::boolean));
|
||||||
|
_add(new configItem("sub_auto_update", &sub_auto_update, itemType::integer));
|
||||||
_add(new configItem("enable_js_hook", &enable_js_hook, itemType::integer));
|
_add(new configItem("enable_js_hook", &enable_js_hook, itemType::integer));
|
||||||
_add(new configItem("log_ignore", &log_ignore, itemType::stringList));
|
_add(new configItem("log_ignore", &log_ignore, itemType::stringList));
|
||||||
_add(new configItem("start_minimal", &start_minimal, itemType::boolean));
|
_add(new configItem("start_minimal", &start_minimal, itemType::boolean));
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ namespace NekoGui {
|
|||||||
bool sub_use_proxy = false;
|
bool sub_use_proxy = false;
|
||||||
bool sub_clear = false;
|
bool sub_clear = false;
|
||||||
bool sub_insecure = false;
|
bool sub_insecure = false;
|
||||||
|
int sub_auto_update = -30;
|
||||||
|
|
||||||
// Security
|
// Security
|
||||||
bool skip_cert = false;
|
bool skip_cert = false;
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ inline std::function<void(QString, QString)> MW_dialog_message;
|
|||||||
class QThread;
|
class QThread;
|
||||||
inline QThread *DS_cores;
|
inline QThread *DS_cores;
|
||||||
|
|
||||||
|
// Timers
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
inline QTimer *TM_auto_update_subsctiption;
|
||||||
|
inline std::function<void(int)> TM_auto_update_subsctiption_Reset_Minute;
|
||||||
|
|
||||||
// String
|
// String
|
||||||
|
|
||||||
#define FIRST_OR_SECOND(a, b) a.isEmpty() ? b : a
|
#define FIRST_OR_SECOND(a, b) a.isEmpty() ? b : a
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
},
|
},
|
||||||
"dns": {
|
"dns": {
|
||||||
"fakeip": {
|
"fakeip": {
|
||||||
"enabled": %ENABLED_FAKEDNS%,
|
"enabled": %FAKE_DNS_ENABLE%,
|
||||||
"inet4_range": "198.18.0.0/15",
|
"inet4_range": "198.18.0.0/15",
|
||||||
"inet6_range": "fc00::/18"
|
"inet6_range": "fc00::/18"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -114,9 +114,7 @@ namespace QtGrpc {
|
|||||||
abortTimer = new QTimer;
|
abortTimer = new QTimer;
|
||||||
abortTimer->setSingleShot(true);
|
abortTimer->setSingleShot(true);
|
||||||
abortTimer->setInterval(timeout_ms);
|
abortTimer->setInterval(timeout_ms);
|
||||||
QObject::connect(abortTimer, &QTimer::timeout, abortTimer, [=]() {
|
QObject::connect(abortTimer, &QTimer::timeout, networkReply, &QNetworkReply::abort);
|
||||||
networkReply->abort();
|
|
||||||
});
|
|
||||||
abortTimer->start();
|
abortTimer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -561,3 +561,53 @@ namespace NekoGui_sub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace NekoGui_sub
|
} // namespace NekoGui_sub
|
||||||
|
|
||||||
|
bool UI_update_all_groups_Updating = false;
|
||||||
|
|
||||||
|
#define should_skip_group(g) (g == nullptr || g->url.isEmpty() || g->archive || (onlyAllowed && g->skip_auto_update))
|
||||||
|
|
||||||
|
void serialUpdateSubscription(const QList<int> &groupsTabOrder, int _order, bool onlyAllowed) {
|
||||||
|
// calculate next group
|
||||||
|
int nextOrder = _order;
|
||||||
|
std::shared_ptr<NekoGui::Group> nextGroup;
|
||||||
|
forever {
|
||||||
|
nextOrder += 1;
|
||||||
|
if (nextOrder >= groupsTabOrder.size()) break;
|
||||||
|
auto nextGid = groupsTabOrder[nextOrder];
|
||||||
|
nextGroup = NekoGui::profileManager->GetGroup(nextGid);
|
||||||
|
if (should_skip_group(nextGroup)) continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate this group
|
||||||
|
auto group = NekoGui::profileManager->GetGroup(groupsTabOrder[_order]);
|
||||||
|
if (group == nullptr) {
|
||||||
|
UI_update_all_groups_Updating = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// v2.2: listener is moved to GroupItem, no refresh here.
|
||||||
|
NekoGui_sub::groupUpdater->AsyncUpdate(group->url, group->id, [=] {
|
||||||
|
if (nextGroup == nullptr) {
|
||||||
|
UI_update_all_groups_Updating = false;
|
||||||
|
} else {
|
||||||
|
serialUpdateSubscription(groupsTabOrder, nextOrder, onlyAllowed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI_update_all_groups(bool onlyAllowed) {
|
||||||
|
if (UI_update_all_groups_Updating) {
|
||||||
|
MW_show_log("The last subscription update has not exited.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// first: freeze group order
|
||||||
|
auto groupsTabOrder = NekoGui::profileManager->groupsTabOrder;
|
||||||
|
for (const auto &gid: groupsTabOrder) {
|
||||||
|
auto group = NekoGui::profileManager->GetGroup(gid);
|
||||||
|
if (should_skip_group(group)) continue;
|
||||||
|
// start
|
||||||
|
UI_update_all_groups_Updating = true;
|
||||||
|
serialUpdateSubscription(groupsTabOrder, groupsTabOrder.indexOf(gid), onlyAllowed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,3 +29,6 @@ namespace NekoGui_sub {
|
|||||||
|
|
||||||
extern GroupUpdater *groupUpdater;
|
extern GroupUpdater *groupUpdater;
|
||||||
} // namespace NekoGui_sub
|
} // namespace NekoGui_sub
|
||||||
|
|
||||||
|
// 更新所有订阅 关闭分组窗口时 更新动作继续执行
|
||||||
|
void UI_update_all_groups(bool onlyAllowed = false);
|
||||||
|
|||||||
@@ -247,6 +247,14 @@ For NekoBox, this rewrites the underlying(localhost) DNS in Tun Mode, normal mod
|
|||||||
<source>Timeout (s)</source>
|
<source>Timeout (s)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Automatic update</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Interval (minute, invalid if less than 30)</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DialogEditGroup</name>
|
<name>DialogEditGroup</name>
|
||||||
@@ -314,6 +322,18 @@ For NekoBox, this rewrites the underlying(localhost) DNS in Tun Mode, normal mod
|
|||||||
<source>Clear</source>
|
<source>Clear</source>
|
||||||
<translation type="unfinished">پاک کردن</translation>
|
<translation type="unfinished">پاک کردن</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Skip automatic update</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Common</source>
|
||||||
|
<translation type="unfinished">متداول</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Share</source>
|
||||||
|
<translation type="unfinished">اشتراک گذاری</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DialogEditProfile</name>
|
<name>DialogEditProfile</name>
|
||||||
|
|||||||
@@ -243,6 +243,14 @@ For NekoBox, this rewrites the underlying(localhost) DNS in Tun Mode, normal mod
|
|||||||
<source>Timeout (s)</source>
|
<source>Timeout (s)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Automatic update</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Interval (minute, invalid if less than 30)</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DialogEditGroup</name>
|
<name>DialogEditGroup</name>
|
||||||
@@ -310,6 +318,18 @@ For NekoBox, this rewrites the underlying(localhost) DNS in Tun Mode, normal mod
|
|||||||
<source>None</source>
|
<source>None</source>
|
||||||
<translation>Нет</translation>
|
<translation>Нет</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Skip automatic update</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Common</source>
|
||||||
|
<translation type="unfinished">Общие</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Share</source>
|
||||||
|
<translation type="unfinished">Поделиться</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DialogEditProfile</name>
|
<name>DialogEditProfile</name>
|
||||||
|
|||||||
@@ -243,6 +243,14 @@ For NekoBox, this rewrites the underlying(localhost) DNS in Tun Mode, normal mod
|
|||||||
<source>Timeout (s)</source>
|
<source>Timeout (s)</source>
|
||||||
<translation>超时(秒)</translation>
|
<translation>超时(秒)</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Automatic update</source>
|
||||||
|
<translation>自动更新订阅</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Interval (minute, invalid if less than 30)</source>
|
||||||
|
<translation>时间间隔(分钟,少于 30 分钟无效)</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DialogEditGroup</name>
|
<name>DialogEditGroup</name>
|
||||||
@@ -310,6 +318,18 @@ For NekoBox, this rewrites the underlying(localhost) DNS in Tun Mode, normal mod
|
|||||||
<source>Clear</source>
|
<source>Clear</source>
|
||||||
<translation>清除</translation>
|
<translation>清除</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Skip automatic update</source>
|
||||||
|
<translation>跳过自动更新</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Common</source>
|
||||||
|
<translation>通用</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Share</source>
|
||||||
|
<translation>分享</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DialogEditProfile</name>
|
<name>DialogEditProfile</name>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
class ExtraCoreWidget : public QWidget {
|
class ExtraCoreWidget : public QWidget {
|
||||||
public:
|
public:
|
||||||
@@ -158,6 +159,7 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
D_LOAD_BOOL(sub_use_proxy)
|
D_LOAD_BOOL(sub_use_proxy)
|
||||||
D_LOAD_BOOL(sub_clear)
|
D_LOAD_BOOL(sub_clear)
|
||||||
D_LOAD_BOOL(sub_insecure)
|
D_LOAD_BOOL(sub_insecure)
|
||||||
|
D_LOAD_INT_ENABLE(sub_auto_update, sub_auto_update_enable)
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
|
|
||||||
@@ -298,10 +300,17 @@ void DialogBasicSettings::accept() {
|
|||||||
|
|
||||||
// Subscription
|
// Subscription
|
||||||
|
|
||||||
|
if (ui->sub_auto_update_enable->isChecked()) {
|
||||||
|
TM_auto_update_subsctiption_Reset_Minute(ui->sub_auto_update->text().toInt());
|
||||||
|
} else {
|
||||||
|
TM_auto_update_subsctiption_Reset_Minute(0);
|
||||||
|
}
|
||||||
|
|
||||||
NekoGui::dataStore->user_agent = ui->user_agent->text();
|
NekoGui::dataStore->user_agent = ui->user_agent->text();
|
||||||
D_SAVE_BOOL(sub_use_proxy)
|
D_SAVE_BOOL(sub_use_proxy)
|
||||||
D_SAVE_BOOL(sub_clear)
|
D_SAVE_BOOL(sub_clear)
|
||||||
D_SAVE_BOOL(sub_insecure)
|
D_SAVE_BOOL(sub_insecure)
|
||||||
|
D_SAVE_INT_ENABLE(sub_auto_update, sub_auto_update_enable)
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
|
|
||||||
|
|||||||
@@ -486,37 +486,84 @@
|
|||||||
<string>Subscription</string>
|
<string>Subscription</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
<item row="0" column="0">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="sub_auto_update_enable">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>User Agent</string>
|
<string>Enable</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item>
|
||||||
<widget class="MyLineEdit" name="user_agent"/>
|
<widget class="QLabel" name="label_21">
|
||||||
|
<property name="text">
|
||||||
|
<string>Interval (minute, invalid if less than 30)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="sub_auto_update">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
|
<widget class="MyLineEdit" name="user_agent"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
<widget class="QCheckBox" name="sub_use_proxy">
|
<widget class="QCheckBox" name="sub_use_proxy">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use proxy when updating subscription</string>
|
<string>Use proxy when updating subscription</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QCheckBox" name="sub_insecure">
|
<widget class="QCheckBox" name="sub_insecure">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Ignore TLS errors when updating subscription</string>
|
<string>Ignore TLS errors when updating subscription</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QCheckBox" name="sub_clear">
|
<widget class="QCheckBox" name="sub_clear">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Clear servers before updating subscription</string>
|
<string>Clear servers before updating subscription</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_20">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Automatic update</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>User Agent</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_4">
|
<widget class="QWidget" name="tab_4">
|
||||||
|
|||||||
@@ -53,34 +53,6 @@ void DialogManageGroups::on_add_clicked() {
|
|||||||
|
|
||||||
void DialogManageGroups::on_update_all_clicked() {
|
void DialogManageGroups::on_update_all_clicked() {
|
||||||
if (QMessageBox::question(this, tr("Confirmation"), tr("Update all subscriptions?")) == QMessageBox::StandardButton::Yes) {
|
if (QMessageBox::question(this, tr("Confirmation"), tr("Update all subscriptions?")) == QMessageBox::StandardButton::Yes) {
|
||||||
for (const auto &gid: NekoGui::profileManager->groupsTabOrder) {
|
UI_update_all_groups();
|
||||||
auto group = NekoGui::profileManager->GetGroup(gid);
|
|
||||||
if (group == nullptr || group->url.isEmpty()) continue;
|
|
||||||
UI_update_one_group(NekoGui::profileManager->groupsTabOrder.indexOf(gid));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UI_update_one_group(int _order) {
|
|
||||||
// calculate next group
|
|
||||||
int nextOrder = _order;
|
|
||||||
std::shared_ptr<NekoGui::Group> nextGroup;
|
|
||||||
forever {
|
|
||||||
nextOrder += 1;
|
|
||||||
if (nextOrder >= NekoGui::profileManager->groupsTabOrder.size()) break;
|
|
||||||
auto nextGid = NekoGui::profileManager->groupsTabOrder[nextOrder];
|
|
||||||
nextGroup = NekoGui::profileManager->GetGroup(nextGid);
|
|
||||||
if (nextGroup == nullptr || nextGroup->url.isEmpty()) continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate this group
|
|
||||||
auto group = NekoGui::profileManager->GetGroup(NekoGui::profileManager->groupsTabOrder[_order]);
|
|
||||||
if (group == nullptr) return;
|
|
||||||
|
|
||||||
// v2.2: listener is moved to GroupItem, no refresh here.
|
|
||||||
NekoGui_sub::groupUpdater->AsyncUpdate(group->url, group->id, [=] {
|
|
||||||
if (nextGroup != nullptr) UI_update_one_group(nextOrder);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -30,7 +30,3 @@ private slots:
|
|||||||
|
|
||||||
void on_update_all_clicked();
|
void on_update_all_clicked();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新所有订阅 关闭分组窗口时 更新动作继续执行
|
|
||||||
|
|
||||||
void UI_update_one_group(int _order);
|
|
||||||
|
|||||||
@@ -6,28 +6,30 @@
|
|||||||
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
|
|
||||||
|
#define ADJUST_SIZE runOnUiThread([=] { adjustSize(); adjustPosition(mainwindow); }, this);
|
||||||
|
|
||||||
DialogEditGroup::DialogEditGroup(const std::shared_ptr<NekoGui::Group> &ent, QWidget *parent) : QDialog(parent), ui(new Ui::DialogEditGroup) {
|
DialogEditGroup::DialogEditGroup(const std::shared_ptr<NekoGui::Group> &ent, QWidget *parent) : QDialog(parent), ui(new Ui::DialogEditGroup) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
this->ent = ent;
|
this->ent = ent;
|
||||||
|
|
||||||
connect(ui->type, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [=](int index) {
|
connect(ui->type, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [=](int index) {
|
||||||
ui->cat_sub->setHidden(index == 0);
|
ui->cat_sub->setHidden(index == 0);
|
||||||
|
ADJUST_SIZE
|
||||||
});
|
});
|
||||||
|
|
||||||
ui->name->setText(ent->name);
|
ui->name->setText(ent->name);
|
||||||
ui->archive->setChecked(ent->archive);
|
ui->archive->setChecked(ent->archive);
|
||||||
|
ui->skip_auto_update->setChecked(ent->skip_auto_update);
|
||||||
ui->url->setText(ent->url);
|
ui->url->setText(ent->url);
|
||||||
ui->type->setCurrentIndex(ent->url.isEmpty() ? 0 : 1);
|
ui->type->setCurrentIndex(ent->url.isEmpty() ? 0 : 1);
|
||||||
ui->type->currentIndexChanged(ui->type->currentIndex());
|
ui->type->currentIndexChanged(ui->type->currentIndex());
|
||||||
ui->manually_column_width->setChecked(ent->manually_column_width);
|
ui->manually_column_width->setChecked(ent->manually_column_width);
|
||||||
ui->copy_links->setVisible(false);
|
ui->cat_share->setVisible(false);
|
||||||
ui->copy_links_nkr->setVisible(false);
|
|
||||||
|
|
||||||
if (ent->id >= 0) { // already a group
|
if (ent->id >= 0) { // already a group
|
||||||
ui->type->setDisabled(true);
|
ui->type->setDisabled(true);
|
||||||
if (!ent->Profiles().isEmpty()) {
|
if (!ent->Profiles().isEmpty()) {
|
||||||
ui->copy_links->setVisible(true);
|
ui->cat_share->setVisible(true);
|
||||||
ui->copy_links_nkr->setVisible(true);
|
|
||||||
}
|
}
|
||||||
} else { // new group
|
} else { // new group
|
||||||
ui->front_proxy->hide();
|
ui->front_proxy->hide();
|
||||||
@@ -60,6 +62,8 @@ DialogEditGroup::DialogEditGroup(const std::shared_ptr<NekoGui::Group> &ent, QWi
|
|||||||
QApplication::clipboard()->setText(links.join("\n"));
|
QApplication::clipboard()->setText(links.join("\n"));
|
||||||
MessageBoxInfo(software_name, tr("Copied"));
|
MessageBoxInfo(software_name, tr("Copied"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ADJUST_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogEditGroup::~DialogEditGroup() {
|
DialogEditGroup::~DialogEditGroup() {
|
||||||
@@ -76,6 +80,7 @@ void DialogEditGroup::accept() {
|
|||||||
ent->name = ui->name->text();
|
ent->name = ui->name->text();
|
||||||
ent->url = ui->url->text();
|
ent->url = ui->url->text();
|
||||||
ent->archive = ui->archive->isChecked();
|
ent->archive = ui->archive->isChecked();
|
||||||
|
ent->skip_auto_update = ui->skip_auto_update->isChecked();
|
||||||
ent->manually_column_width = ui->manually_column_width->isChecked();
|
ent->manually_column_width = ui->manually_column_width->isChecked();
|
||||||
ent->front_proxy_id = CACHE.front_proxy;
|
ent->front_proxy_id = CACHE.front_proxy;
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
|
|||||||
@@ -7,62 +7,34 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>400</width>
|
||||||
<height>300</height>
|
<height>468</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Edit Group</string>
|
<string>Edit Group</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="cat_common" native="true">
|
<widget class="QGroupBox" name="cat_common">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Common</string>
|
||||||
|
</property>
|
||||||
<layout class="QGridLayout" name="main">
|
<layout class="QGridLayout" name="main">
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLineEdit" name="name"/>
|
<widget class="QLineEdit" name="name"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Name</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="manually_column_width">
|
|
||||||
<property name="text">
|
|
||||||
<string>Manually column width</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="archive">
|
|
||||||
<property name="text">
|
|
||||||
<string>Archive</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -91,6 +63,31 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="manually_column_width">
|
||||||
|
<property name="text">
|
||||||
|
<string>Manually column width</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="archive">
|
||||||
|
<property name="text">
|
||||||
|
<string>Archive</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
@@ -119,28 +116,11 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="cat_sub" native="true">
|
<widget class="QGroupBox" name="cat_sub">
|
||||||
<property name="sizePolicy">
|
<property name="title">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
<string>Subscription</string>
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QGridLayout" name="_2">
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -151,12 +131,21 @@
|
|||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="MyLineEdit" name="url"/>
|
<widget class="MyLineEdit" name="url"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="1" column="1">
|
||||||
|
<widget class="QCheckBox" name="skip_auto_update">
|
||||||
|
<property name="text">
|
||||||
|
<string>Skip automatic update</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
<widget class="QGroupBox" name="cat_share">
|
||||||
|
<property name="title">
|
||||||
|
<string>Share</string>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="copy_links">
|
<widget class="QPushButton" name="copy_links">
|
||||||
@@ -173,6 +162,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
@@ -198,6 +188,7 @@
|
|||||||
<tabstop>manually_column_width</tabstop>
|
<tabstop>manually_column_width</tabstop>
|
||||||
<tabstop>archive</tabstop>
|
<tabstop>archive</tabstop>
|
||||||
<tabstop>url</tabstop>
|
<tabstop>url</tabstop>
|
||||||
|
<tabstop>skip_auto_update</tabstop>
|
||||||
<tabstop>copy_links</tabstop>
|
<tabstop>copy_links</tabstop>
|
||||||
<tabstop>copy_links_nkr</tabstop>
|
<tabstop>copy_links_nkr</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
|
|||||||
@@ -434,6 +434,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||||||
connect(t, &QTimer::timeout, this, [&] { NekoGui_sys::logCounter.fetchAndStoreRelaxed(0); });
|
connect(t, &QTimer::timeout, this, [&] { NekoGui_sys::logCounter.fetchAndStoreRelaxed(0); });
|
||||||
t->start(1000);
|
t->start(1000);
|
||||||
|
|
||||||
|
TM_auto_update_subsctiption = new QTimer;
|
||||||
|
TM_auto_update_subsctiption_Reset_Minute = [&](int m) {
|
||||||
|
TM_auto_update_subsctiption->stop();
|
||||||
|
if (m >= 30) TM_auto_update_subsctiption->start(m * 60 * 1000);
|
||||||
|
};
|
||||||
|
connect(TM_auto_update_subsctiption, &QTimer::timeout, this, [&] { UI_update_all_groups(true); });
|
||||||
|
TM_auto_update_subsctiption_Reset_Minute(NekoGui::dataStore->sub_auto_update);
|
||||||
|
|
||||||
if (!NekoGui::dataStore->flag_tray) show();
|
if (!NekoGui::dataStore->flag_tray) show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user