Update On Fri Sep 26 20:35:28 CEST 2025

This commit is contained in:
github-action[bot]
2025-09-26 20:35:28 +02:00
parent f39050f25e
commit 22c5f5fb97
33 changed files with 635 additions and 392 deletions
+1
View File
@@ -1132,3 +1132,4 @@ Update On Mon Sep 22 20:36:16 CEST 2025
Update On Tue Sep 23 20:37:30 CEST 2025
Update On Wed Sep 24 20:34:28 CEST 2025
Update On Thu Sep 25 20:42:08 CEST 2025
Update On Fri Sep 26 20:35:20 CEST 2025
+1 -1
View File
@@ -24,7 +24,7 @@ require (
github.com/metacubex/fswatch v0.1.1
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
github.com/metacubex/kcp-go v0.0.0-20250923001605-1ba6f691c45b
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295
github.com/metacubex/quic-go v0.54.1-0.20250926001022-e2a3ce003b3a
github.com/metacubex/randv2 v0.2.0
github.com/metacubex/restls-client-go v0.1.7
github.com/metacubex/sing v0.5.6
+2 -2
View File
@@ -112,8 +112,8 @@ github.com/metacubex/kcp-go v0.0.0-20250923001605-1ba6f691c45b h1:z7JLKjugnQ1qvD
github.com/metacubex/kcp-go v0.0.0-20250923001605-1ba6f691c45b/go.mod h1:HIJZW4QMhbBqXuqC1ly6Hn0TEYT2SzRw58ns1yGhXTs=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA=
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs=
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
github.com/metacubex/quic-go v0.54.1-0.20250926001022-e2a3ce003b3a h1:l7BWjOifmqM2zMi+AMrgIx1z4KJt0oY/6cHW11kA9IQ=
github.com/metacubex/quic-go v0.54.1-0.20250926001022-e2a3ce003b3a/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k=
@@ -11,7 +11,7 @@
"build": "tsc"
},
"dependencies": {
"@tanstack/react-query": "5.87.4",
"@tanstack/react-query": "5.90.2",
"@tauri-apps/api": "2.8.0",
"ahooks": "3.9.5",
"dayjs": "1.11.18",
@@ -19,7 +19,7 @@
"@mui/icons-material": "7.3.2",
"@mui/lab": "7.0.0-beta.17",
"@mui/material": "7.3.2",
"@mui/x-date-pickers": "8.11.3",
"@mui/x-date-pickers": "8.12.0",
"@nyanpasu/interface": "workspace:^",
"@nyanpasu/ui": "workspace:^",
"@tailwindcss/postcss": "4.1.13",
@@ -31,7 +31,7 @@
"country-code-emoji": "2.3.0",
"country-emoji": "1.5.6",
"dayjs": "1.11.18",
"framer-motion": "12.23.21",
"framer-motion": "12.23.22",
"i18next": "25.5.2",
"jotai": "2.14.0",
"json-schema": "0.4.0",
@@ -43,7 +43,7 @@
"react-error-boundary": "6.0.0",
"react-fast-marquee": "1.6.5",
"react-hook-form-mui": "8.0.0",
"react-i18next": "15.7.3",
"react-i18next": "15.7.4",
"react-markdown": "10.1.0",
"react-split-grid": "1.0.4",
"react-use": "17.6.0",
@@ -56,12 +56,12 @@
"@csstools/normalize.css": "12.1.1",
"@emotion/babel-plugin": "11.13.5",
"@emotion/react": "11.14.0",
"@iconify/json": "2.2.387",
"@iconify/json": "2.2.388",
"@monaco-editor/react": "4.7.0",
"@tanstack/react-query": "5.87.4",
"@tanstack/react-router": "1.131.50",
"@tanstack/react-router-devtools": "1.131.50",
"@tanstack/router-plugin": "1.131.50",
"@tanstack/react-query": "5.90.2",
"@tanstack/react-router": "1.132.7",
"@tanstack/react-router-devtools": "1.132.7",
"@tanstack/router-plugin": "1.132.7",
"@tauri-apps/plugin-clipboard-manager": "2.3.0",
"@tauri-apps/plugin-dialog": "2.4.0",
"@tauri-apps/plugin-fs": "2.4.2",
+2 -2
View File
@@ -23,11 +23,11 @@
"@vitejs/plugin-react": "5.0.3",
"ahooks": "3.9.5",
"d3": "7.9.0",
"framer-motion": "12.23.21",
"framer-motion": "12.23.22",
"react": "19.1.1",
"react-dom": "19.1.1",
"react-error-boundary": "6.0.0",
"react-i18next": "15.7.3",
"react-i18next": "15.7.4",
"react-use": "17.6.0",
"tailwindcss": "4.1.13",
"vite": "7.1.7",
+2 -2
View File
@@ -85,8 +85,8 @@
"eslint-plugin-react-compiler": "19.1.0-rc.2",
"eslint-plugin-react-hooks": "5.2.0",
"globals": "16.4.0",
"knip": "5.64.0",
"lint-staged": "16.2.0",
"knip": "5.64.1",
"lint-staged": "16.2.1",
"neostandard": "0.12.2",
"npm-run-all2": "8.0.4",
"postcss": "8.5.6",
+281 -253
View File
File diff suppressed because it is too large Load Diff
+19 -13
View File
@@ -517,30 +517,36 @@ endef
$(eval $(call KernelPackage,dsa))
define KernelPackage/dsa-tag-dsa
define KernelPackage/dsa-notag
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Marvell DSA type DSA and EDSA taggers
TITLE:=DSA No-op tag driver
DEPENDS:=+kmod-dsa
KCONFIG:= CONFIG_NET_DSA_TAG_DSA_COMMON \
CONFIG_NET_DSA_TAG_DSA \
CONFIG_NET_DSA_TAG_EDSA
FILES:=$(LINUX_DIR)/net/dsa/tag_dsa.ko
AUTOLOAD:=$(call AutoLoad,40,tag_dsa,1)
KCONFIG:=CONFIG_NET_DSA_TAG_NONE
FILES:=$(LINUX_DIR)/net/dsa/tag_none.ko
endef
define KernelPackage/dsa-tag-dsa/description
Kernel modules for Marvell DSA and EDSA tagging
define KernelPackage/dsa-notag/description
Kernel module support for switches which don't tag frames over the CPU port.
endef
$(eval $(call KernelPackage,dsa-tag-dsa))
$(eval $(call KernelPackage,dsa-notag))
define KernelPackage/dsa-mv88e6xxx
SUBMENU:=$(NETWORK_DEVICES_MENU)
TITLE:=Marvell MV88E6XXX DSA Switch
DEPENDS:=+kmod-dsa +kmod-ptp +kmod-phy-marvell +kmod-dsa-tag-dsa
KCONFIG:=CONFIG_NET_DSA_MV88E6XXX \
DEPENDS:=+kmod-dsa +kmod-ptp +kmod-phy-marvell
KCONFIG:= \
CONFIG_NET_DSA_TAG_DSA_COMMON \
CONFIG_NET_DSA_TAG_DSA \
CONFIG_NET_DSA_TAG_EDSA \
CONFIG_NET_DSA_MV88E6XXX \
CONFIG_NET_DSA_MV88E6XXX_LEDS=y \
CONFIG_NET_DSA_MV88E6XXX_PTP=y
FILES:=$(LINUX_DIR)/drivers/net/dsa/mv88e6xxx/mv88e6xxx.ko
FILES:= \
$(LINUX_DIR)/net/dsa/tag_dsa.ko \
$(LINUX_DIR)/drivers/net/dsa/mv88e6xxx/mv88e6xxx.ko
AUTOLOAD:=$(call AutoLoad,41,mv88e6xxx,1)
endef
@@ -9,7 +9,7 @@ proxies:
- name: mieru
type: mieru
server: 127.0.0.1
port: 8964
port: 4896,6489,8964-8965,9648
transport: TCP
udp: true
username: baozi
+1 -1
View File
@@ -9,7 +9,7 @@ proxies:
- name: mieru
type: mieru
server: 127.0.0.1
port: 8964
port: 4896,6489,8964-8965,9648
transport: TCP
udp: true
username: baozi
+1 -1
View File
@@ -24,7 +24,7 @@ require (
github.com/metacubex/fswatch v0.1.1
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
github.com/metacubex/kcp-go v0.0.0-20250923001605-1ba6f691c45b
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295
github.com/metacubex/quic-go v0.54.1-0.20250926001022-e2a3ce003b3a
github.com/metacubex/randv2 v0.2.0
github.com/metacubex/restls-client-go v0.1.7
github.com/metacubex/sing v0.5.6
+2 -2
View File
@@ -112,8 +112,8 @@ github.com/metacubex/kcp-go v0.0.0-20250923001605-1ba6f691c45b h1:z7JLKjugnQ1qvD
github.com/metacubex/kcp-go v0.0.0-20250923001605-1ba6f691c45b/go.mod h1:HIJZW4QMhbBqXuqC1ly6Hn0TEYT2SzRw58ns1yGhXTs=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA=
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs=
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
github.com/metacubex/quic-go v0.54.1-0.20250926001022-e2a3ce003b3a h1:l7BWjOifmqM2zMi+AMrgIx1z4KJt0oY/6cHW11kA9IQ=
github.com/metacubex/quic-go v0.54.1-0.20250926001022-e2a3ce003b3a/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k=
+7 -1
View File
@@ -67,7 +67,7 @@ Options:
The default proxy is a direct connection without proxying.
The last PROXY-URI is negotiated automatically for Naive padding.
If multiple proxies are specified, they must match the number of specified
Can be specified multiple times, but they must match the number of specified
LISTEN-URIs, and each LISTEN-URI is routed to the PROXY matched by position.
Limitations:
@@ -93,6 +93,7 @@ Options:
--host-resolver-rules="MAP proxy.example.com 1.2.3.4"
Statically resolves a domain name to an IP address.
Multiple rules are comma separated.
--resolver-range=CIDR
@@ -114,3 +115,8 @@ Options:
--no-post-quantum
Overrides the default and disables post-quantum key agreement.
--env=NAME=VALUE
Sets the environment variable NAME to the value VALUE. Can be specified
multiple times.
@@ -6,6 +6,7 @@
#include <algorithm>
#include <iostream>
#include "base/environment.h"
#include "base/strings/escape.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
@@ -285,6 +286,39 @@ bool NaiveConfig::Parse(const base::Value::Dict& value) {
no_post_quantum = true;
}
if (const base::Value* v = value.Find("env")) {
std::vector<std::string> env_strs;
if (const std::string* str = v->GetIfString(); str && !str->empty()) {
env_strs.push_back(*str);
} else if (const base::Value::List* strs = v->GetIfList()) {
for (const auto& str_e : *strs) {
if (const std::string* s = str_e.GetIfString(); s && !s->empty()) {
env_strs.push_back(*s);
} else {
std::cerr << "Invalid env element" << std::endl;
return false;
}
}
} else {
std::cerr << "Invalid env argument" << std::endl;
return false;
}
auto env = base::Environment::Create();
for (const std::string& str : env_strs) {
size_t equal_pos = str.find_first_of('=');
if (equal_pos != std::string::npos && equal_pos > 0 &&
equal_pos + 1 < str.size()) {
std::string env_name = str.substr(0, equal_pos);
std::string env_value = str.substr(equal_pos + 1);
if (!env->SetVar(env_name, env_value)) {
std::cerr << "Invalid env element " << str << std::endl;
}
} else {
std::cerr << "Invalid env element " << str << std::endl;
}
}
}
return true;
}
@@ -13,6 +13,7 @@
#include "base/at_exit.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/json/json_file_value_serializer.h"
@@ -533,7 +534,7 @@ int main(int argc, char* argv[]) {
naive_proxies.push_back(std::move(naive_proxy));
}
if (getenv("TEST_MARK_STARTUP") != nullptr) {
if (base::Environment::Create()->HasVar("TEST_MARK_STARTUP")) {
LOG(INFO) << "TEST_MARK_STARTUP";
}
base::RunLoop().Run();
+4 -4
View File
@@ -2801,9 +2801,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.11.2"
version = "1.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
dependencies = [
"aho-corasick",
"memchr",
@@ -2813,9 +2813,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.10"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
dependencies = [
"aho-corasick",
"memchr",
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
matrix:
configuration: [Release]
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout
+3 -1
View File
@@ -5,6 +5,7 @@
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.3.0" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.6" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.6" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.6" />
@@ -19,6 +20,7 @@
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageVersion Include="ReactiveUI.WPF" Version="20.4.1" />
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.10" />
<PackageVersion Include="Semi.Avalonia.AvaloniaEdit" Version="11.2.0.1" />
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.10" />
<PackageVersion Include="NLog" Version="6.0.4" />
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
@@ -27,4 +29,4 @@
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
</ItemGroup>
</Project>
</Project>
+8
View File
@@ -449,6 +449,14 @@ public class Global
"none"
];
public static readonly Dictionary<string, string> LogLevelColors = new()
{
{ "debug", "#6C757D" },
{ "info", "#2ECC71" },
{ "warning", "#FFA500" },
{ "error", "#E74C3C" },
};
public static readonly List<string> InboundTags =
[
"socks",
@@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using System.Reactive.Linq;
using System.Text;
using System.Text.RegularExpressions;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
@@ -9,9 +10,9 @@ namespace ServiceLib.ViewModels;
public class MsgViewModel : MyReactiveObject
{
private readonly ConcurrentQueue<string> _queueMsg = new();
private readonly int _numMaxMsg = 500;
private bool _lastMsgFilterNotAvailable;
private bool _blLockShow = false;
private volatile bool _lastMsgFilterNotAvailable;
private int _showLock = 0; // 0 = unlocked, 1 = locked
public int NumMaxMsg { get; } = 500;
[Reactive]
public string MsgFilter { get; set; }
@@ -33,46 +34,52 @@ public class MsgViewModel : MyReactiveObject
this.WhenAnyValue(
x => x.AutoRefresh,
y => y == true)
.Subscribe(c => { _config.MsgUIItem.AutoRefresh = AutoRefresh; });
.Subscribe(c => _config.MsgUIItem.AutoRefresh = AutoRefresh);
AppEvents.SendMsgViewRequested
.AsObservable()
//.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async content => await AppendQueueMsg(content));
.Subscribe(content => _ = AppendQueueMsg(content));
}
private async Task AppendQueueMsg(string msg)
{
//if (msg == Global.CommandClearMsg)
//{
// ClearMsg();
// return;
//}
if (AutoRefresh == false)
{
return;
}
_ = EnqueueQueueMsg(msg);
if (_blLockShow)
{
return;
}
EnqueueQueueMsg(msg);
if (!_config.UiItem.ShowInTaskbar)
{
return;
}
_blLockShow = true;
if (Interlocked.CompareExchange(ref _showLock, 1, 0) != 0)
{
return;
}
await Task.Delay(500);
var txt = string.Join("", _queueMsg.ToArray());
await _updateView?.Invoke(EViewAction.DispatcherShowMsg, txt);
try
{
await Task.Delay(500).ConfigureAwait(false);
_blLockShow = false;
var sb = new StringBuilder();
while (_queueMsg.TryDequeue(out var line))
{
sb.Append(line);
}
await _updateView?.Invoke(EViewAction.DispatcherShowMsg, sb.ToString());
}
finally
{
Interlocked.Exchange(ref _showLock, 0);
}
}
private async Task EnqueueQueueMsg(string msg)
private void EnqueueQueueMsg(string msg)
{
//filter msg
if (MsgFilter.IsNotEmpty() && !_lastMsgFilterNotAvailable)
@@ -91,26 +98,17 @@ public class MsgViewModel : MyReactiveObject
}
}
//Enqueue
if (_queueMsg.Count > _numMaxMsg)
{
for (int k = 0; k < _queueMsg.Count - _numMaxMsg; k++)
{
_queueMsg.TryDequeue(out _);
}
}
_queueMsg.Enqueue(msg);
if (!msg.EndsWith(Environment.NewLine))
{
_queueMsg.Enqueue(Environment.NewLine);
}
await Task.CompletedTask;
}
public void ClearMsg()
{
_queueMsg.Clear();
}
//public void ClearMsg()
//{
// _queueMsg.Clear();
//}
private void DoMsgFilter()
{
+1
View File
@@ -11,6 +11,7 @@
RequestedThemeVariant="Default">
<Application.Styles>
<semi:SemiTheme />
<semi:AvaloniaEditSemiTheme />
<StyleInclude Source="Assets/GlobalStyles.axaml" />
<StyleInclude Source="avares://Semi.Avalonia.DataGrid/Index.axaml" />
<dialogHost:DialogHostStyles />
@@ -0,0 +1,129 @@
using Avalonia.Media;
using AvaloniaEdit;
using AvaloniaEdit.Document;
using AvaloniaEdit.Rendering;
namespace v2rayN.Desktop.Common;
public class KeywordColorizer : DocumentColorizingTransformer
{
private readonly string[] _keywords;
private readonly Dictionary<string, IBrush> _brushMap;
public KeywordColorizer(IDictionary<string, IBrush> keywordBrushMap)
{
if (keywordBrushMap == null || keywordBrushMap.Count == 0)
{
throw new ArgumentException("keywordBrushMap must not be null or empty", nameof(keywordBrushMap));
}
_brushMap = new Dictionary<string, IBrush>(StringComparer.OrdinalIgnoreCase);
foreach (var kvp in keywordBrushMap)
{
if (string.IsNullOrEmpty(kvp.Key) || kvp.Value == null)
{
continue;
}
if (!_brushMap.ContainsKey(kvp.Key))
{
_brushMap[kvp.Key] = kvp.Value;
}
}
if (_brushMap.Count == 0)
{
throw new ArgumentException("keywordBrushMap must contain at least one non-empty key with a non-null brush", nameof(keywordBrushMap));
}
_keywords = _brushMap.Keys.ToArray();
}
protected override void ColorizeLine(DocumentLine line)
{
var text = CurrentContext.Document.GetText(line);
if (string.IsNullOrEmpty(text))
{
return;
}
foreach (var kw in _keywords)
{
if (string.IsNullOrEmpty(kw))
{
continue;
}
var searchStart = 0;
while (true)
{
var idx = text.IndexOf(kw, searchStart, StringComparison.OrdinalIgnoreCase);
if (idx < 0)
{
break;
}
var kwEndIndex = idx + kw.Length;
if (IsWordCharBefore(text, idx) || IsWordCharAfter(text, kwEndIndex))
{
searchStart = idx + Math.Max(1, kw.Length);
continue;
}
var start = line.Offset + idx;
var end = start + kw.Length;
if (_brushMap.TryGetValue(kw, out var brush) && brush != null)
{
ChangeLinePart(start, end, element => element.TextRunProperties.SetForegroundBrush(brush));
}
searchStart = idx + Math.Max(1, kw.Length);
}
}
}
private static bool IsWordCharBefore(string text, int idx)
{
if (idx <= 0)
{
return false;
}
var c = text[idx - 1];
return char.IsLetterOrDigit(c) || c == '_';
}
private static bool IsWordCharAfter(string text, int idx)
{
if (idx >= text.Length)
{
return false;
}
var c = text[idx];
return char.IsLetterOrDigit(c) || c == '_';
}
}
public static class TextEditorKeywordHighlighter
{
public static void Attach(TextEditor editor, IDictionary<string, IBrush> keywordBrushMap)
{
ArgumentNullException.ThrowIfNull(editor);
if (keywordBrushMap == null || keywordBrushMap.Count == 0)
{
return;
}
if (editor.TextArea?.TextView?.LineTransformers?.OfType<KeywordColorizer>().Any() == true)
{
return;
}
var colorizer = new KeywordColorizer(keywordBrushMap);
editor.TextArea.TextView.LineTransformers.Add(colorizer);
editor.TextArea.TextView.InvalidateVisual();
}
}
@@ -5,6 +5,7 @@ using Avalonia.Controls.Notifications;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
using Avalonia.Styling;
using AvaloniaEdit;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Semi.Avalonia;
@@ -112,7 +113,8 @@ public class ThemeSettingViewModel : MyReactiveObject
x.OfType<ContextMenu>(),
x.OfType<DataGridRow>(),
x.OfType<ListBoxItem>(),
x.OfType<HeaderedContentControl>()
x.OfType<HeaderedContentControl>(),
x.OfType<TextEditor>()
));
style.Add(new Setter()
{
@@ -153,7 +155,8 @@ public class ThemeSettingViewModel : MyReactiveObject
x.OfType<DataGridRow>(),
x.OfType<ListBoxItem>(),
x.OfType<HeaderedContentControl>(),
x.OfType<WindowNotificationManager>()
x.OfType<WindowNotificationManager>(),
x.OfType<TextEditor>()
));
style.Add(new Setter()
{
@@ -2,6 +2,7 @@
x:Class="v2rayN.Desktop.Views.MsgView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avaloniaEdit="clr-namespace:AvaloniaEdit;assembly=AvaloniaEdit"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
@@ -70,35 +71,36 @@
Theme="{DynamicResource SimpleToggleSwitch}" />
</WrapPanel>
<ScrollViewer x:Name="msgScrollViewer" VerticalScrollBarVisibility="Auto">
<SelectableTextBlock
Name="txtMsg"
Margin="{StaticResource Margin8}"
VerticalAlignment="Stretch"
Classes="TextArea"
TextAlignment="Left"
TextWrapping="Wrap">
<SelectableTextBlock.ContextMenu>
<ContextMenu>
<MenuItem
x:Name="menuMsgViewSelectAll"
Click="menuMsgViewSelectAll_Click"
Header="{x:Static resx:ResUI.menuMsgViewSelectAll}" />
<MenuItem
x:Name="menuMsgViewCopy"
Click="menuMsgViewCopy_Click"
Header="{x:Static resx:ResUI.menuMsgViewCopy}" />
<MenuItem
x:Name="menuMsgViewCopyAll"
Click="menuMsgViewCopyAll_Click"
Header="{x:Static resx:ResUI.menuMsgViewCopyAll}" />
<MenuItem
x:Name="menuMsgViewClear"
Click="menuMsgViewClear_Click"
Header="{x:Static resx:ResUI.menuMsgViewClear}" />
</ContextMenu>
</SelectableTextBlock.ContextMenu>
</SelectableTextBlock>
</ScrollViewer>
<avaloniaEdit:TextEditor
Name="txtMsg"
Margin="{StaticResource Margin8}"
IsReadOnly="True"
VerticalScrollBarVisibility="Auto"
WordWrap="True">
<avaloniaEdit:TextEditor.Options>
<avaloniaEdit:TextEditorOptions AllowScrollBelowDocument="False"/>
</avaloniaEdit:TextEditor.Options>
<avaloniaEdit:TextEditor.ContextFlyout>
<MenuFlyout>
<MenuItem
x:Name="menuMsgViewSelectAll"
Click="menuMsgViewSelectAll_Click"
Header="{x:Static resx:ResUI.menuMsgViewSelectAll}" />
<MenuItem
x:Name="menuMsgViewCopy"
Click="menuMsgViewCopy_Click"
Header="{x:Static resx:ResUI.menuMsgViewCopy}" />
<MenuItem
x:Name="menuMsgViewCopyAll"
Click="menuMsgViewCopyAll_Click"
Header="{x:Static resx:ResUI.menuMsgViewCopyAll}" />
<MenuItem
x:Name="menuMsgViewClear"
Click="menuMsgViewClear_Click"
Header="{x:Static resx:ResUI.menuMsgViewClear}" />
</MenuFlyout>
</avaloniaEdit:TextEditor.ContextFlyout>
</avaloniaEdit:TextEditor>
</DockPanel>
</UserControl>
@@ -1,6 +1,6 @@
using System.Reactive.Disposables;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.ReactiveUI;
using Avalonia.Threading;
using ReactiveUI;
@@ -10,13 +10,11 @@ namespace v2rayN.Desktop.Views;
public partial class MsgView : ReactiveUserControl<MsgViewModel>
{
private readonly ScrollViewer _scrollViewer;
//private const int KeepLines = 30;
public MsgView()
{
InitializeComponent();
_scrollViewer = this.FindControl<ScrollViewer>("msgScrollViewer");
ViewModel = new MsgViewModel(UpdateViewHandler);
this.WhenActivated(disposables =>
@@ -24,6 +22,11 @@ public partial class MsgView : ReactiveUserControl<MsgViewModel>
this.Bind(ViewModel, vm => vm.MsgFilter, v => v.cmbMsgFilter.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);
});
TextEditorKeywordHighlighter.Attach(txtMsg, Global.LogLevelColors.ToDictionary(
kv => kv.Key,
kv => (IBrush)new SolidColorBrush(Color.Parse(kv.Value))
));
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
@@ -34,9 +37,8 @@ public partial class MsgView : ReactiveUserControl<MsgViewModel>
if (obj is null)
return false;
Dispatcher.UIThread.Post(() =>
ShowMsg(obj),
DispatcherPriority.ApplicationIdle);
Dispatcher.UIThread.Post(() => ShowMsg(obj),
DispatcherPriority.ApplicationIdle);
break;
}
return await Task.FromResult(true);
@@ -44,23 +46,37 @@ public partial class MsgView : ReactiveUserControl<MsgViewModel>
private void ShowMsg(object msg)
{
txtMsg.Text = msg.ToString();
//var lineCount = txtMsg.LineCount;
//if (lineCount > ViewModel?.NumMaxMsg)
//{
// var cutLine = txtMsg.Document.GetLineByNumber(lineCount - KeepLines);
// txtMsg.Document.Remove(0, cutLine.Offset);
//}
if (txtMsg.LineCount > ViewModel?.NumMaxMsg)
{
ClearMsg();
}
txtMsg.AppendText(msg.ToString());
if (togScrollToEnd.IsChecked ?? true)
{
_scrollViewer?.ScrollToEnd();
txtMsg.ScrollToEnd();
}
}
public void ClearMsg()
{
ViewModel?.ClearMsg();
txtMsg.Text = "";
txtMsg.Clear();
txtMsg.AppendText("----- Message cleared -----\n");
}
private void menuMsgViewSelectAll_Click(object? sender, RoutedEventArgs e)
{
txtMsg.Focus();
txtMsg.SelectAll();
Dispatcher.UIThread.Post(() =>
{
txtMsg.TextArea.Focus();
txtMsg.SelectAll();
}, DispatcherPriority.Render);
}
private async void menuMsgViewCopy_Click(object? sender, RoutedEventArgs e)
@@ -10,7 +10,7 @@
mc:Ignorable="d">
<UserControl.Resources>
<sys:Double x:Key="QrcodeWidth">500</sys:Double>
<sys:Double x:Key="QrcodeWidth">400</sys:Double>
</UserControl.Resources>
<Grid Margin="32" RowDefinitions="Auto,Auto">
@@ -9,6 +9,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia.AvaloniaEdit" />
<PackageReference Include="Avalonia.Controls.DataGrid">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
@@ -17,6 +18,7 @@
<PackageReference Include="Avalonia.ReactiveUI" />
<PackageReference Include="MessageBox.Avalonia" />
<PackageReference Include="Semi.Avalonia" />
<PackageReference Include="Semi.Avalonia.AvaloniaEdit" />
<PackageReference Include="Semi.Avalonia.DataGrid">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
+7 -4
View File
@@ -47,19 +47,22 @@ public partial class MsgView
private void ShowMsg(object msg)
{
txtMsg.BeginChange();
txtMsg.Text = msg.ToString();
if (txtMsg.LineCount > ViewModel?.NumMaxMsg)
{
ClearMsg();
}
txtMsg.AppendText(msg.ToString());
if (togScrollToEnd.IsChecked ?? true)
{
txtMsg.ScrollToEnd();
}
txtMsg.EndChange();
}
public void ClearMsg()
{
ViewModel?.ClearMsg();
txtMsg.Clear();
txtMsg.AppendText("----- Message cleared -----\n");
}
private void menuMsgViewSelectAll_Click(object sender, System.Windows.RoutedEventArgs e)
+1 -1
View File
@@ -12,7 +12,7 @@
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<UserControl.Resources>
<sys:Double x:Key="QrcodeWidth">500</sys:Double>
<sys:Double x:Key="QrcodeWidth">400</sys:Double>
</UserControl.Resources>
<Grid Margin="32">
+4 -1
View File
@@ -514,7 +514,10 @@ class TwitchVodIE(TwitchBaseIE):
is_live = None
if thumbnail:
if re.findall(r'/404_processing_[^.?#]+\.png', thumbnail):
is_live, thumbnail = True, None
# False positive for is_live if info.get('broadcastType') == 'HIGHLIGHT'
# See https://github.com/yt-dlp/yt-dlp/issues/14455
is_live = info.get('broadcastType') == 'ARCHIVE'
thumbnail = None
else:
is_live = False
+9 -9
View File
@@ -99,7 +99,7 @@ INNERTUBE_CLIENTS = {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'WEB',
'clientVersion': '2.20250312.04.00',
'clientVersion': '2.20250925.01.00',
},
},
'INNERTUBE_CONTEXT_CLIENT_NAME': 1,
@@ -111,7 +111,7 @@ INNERTUBE_CLIENTS = {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'WEB',
'clientVersion': '2.20250312.04.00',
'clientVersion': '2.20250925.01.00',
'userAgent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15,gzip(gfe)',
},
},
@@ -123,7 +123,7 @@ INNERTUBE_CLIENTS = {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'WEB_EMBEDDED_PLAYER',
'clientVersion': '1.20250310.01.00',
'clientVersion': '1.20250923.21.00',
},
},
'INNERTUBE_CONTEXT_CLIENT_NAME': 56,
@@ -134,7 +134,7 @@ INNERTUBE_CLIENTS = {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'WEB_REMIX',
'clientVersion': '1.20250310.01.00',
'clientVersion': '1.20250922.03.00',
},
},
'INNERTUBE_CONTEXT_CLIENT_NAME': 67,
@@ -163,7 +163,7 @@ INNERTUBE_CLIENTS = {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'WEB_CREATOR',
'clientVersion': '1.20250312.03.01',
'clientVersion': '1.20250922.03.00',
},
},
'INNERTUBE_CONTEXT_CLIENT_NAME': 62,
@@ -225,11 +225,11 @@ INNERTUBE_CLIENTS = {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'ANDROID_VR',
'clientVersion': '1.62.27',
'clientVersion': '1.65.10',
'deviceMake': 'Oculus',
'deviceModel': 'Quest 3',
'androidSdkVersion': 32,
'userAgent': 'com.google.android.apps.youtube.vr.oculus/1.62.27 (Linux; U; Android 12L; eureka-user Build/SQ3A.220605.009.A1) gzip',
'userAgent': 'com.google.android.apps.youtube.vr.oculus/1.65.10 (Linux; U; Android 12L; eureka-user Build/SQ3A.220605.009.A1) gzip',
'osName': 'Android',
'osVersion': '12L',
},
@@ -274,7 +274,7 @@ INNERTUBE_CLIENTS = {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'MWEB',
'clientVersion': '2.20250311.03.00',
'clientVersion': '2.20250925.01.00',
# mweb previously did not require PO Token with this UA
'userAgent': 'Mozilla/5.0 (iPad; CPU OS 16_7_10 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1,gzip(gfe)',
},
@@ -304,7 +304,7 @@ INNERTUBE_CLIENTS = {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'TVHTML5',
'clientVersion': '7.20250312.16.00',
'clientVersion': '7.20250923.13.00',
'userAgent': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/Version',
},
},
+2 -2
View File
@@ -2920,7 +2920,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
if player_url and context == _PoTokenContext.GVS and not visitor_data and not self.is_authenticated:
self.report_warning(
f'Unable to fetch GVS PO Token for {client} client: Missing required Visitor Data. '
f'You may need to pass Visitor Data with --extractor-args "youtube:visitor_data=XXX"')
f'You may need to pass Visitor Data with --extractor-args "youtube:visitor_data=XXX"', only_once=True)
return
if context == _PoTokenContext.PLAYER and not video_id:
@@ -2943,7 +2943,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
if player_url and context == _PoTokenContext.GVS and not data_sync_id and self.is_authenticated:
self.report_warning(
f'Unable to fetch GVS PO Token for {client} client: Missing required Data Sync ID for account. '
f'You may need to pass a Data Sync ID with --extractor-args "youtube:data_sync_id=XXX"')
f'You may need to pass a Data Sync ID with --extractor-args "youtube:data_sync_id=XXX"', only_once=True)
return
po_token = self._fetch_po_token(