Update scheduled file cleanup in `TaskManager` to delete log and temp files older than 7 days instead of 1 month, reducing stale local data and tightening routine maintenance behavior.
Clear all auxiliary tab contents before applying a new grid orientation to prevent stale view reuse, and remove the delayed tab-index workaround. Also treat `ProfilesViewModel` as a transient view so its view is recreated like other dynamic tabs.
Add a `ConditionalWeakTable`-based view cache keyed by view model instance for `MsgViewModel`, `ClashProxiesViewModel`, and `ClashConnectionsViewModel` so repeated bindings reuse the same control. The locator now also handles missing registrations and null factory results more explicitly by returning descriptive `TextBlock` messages.
* Exposed the mux multiplexing settings in the core settings UI. Now it's possible to change the default concurrency value of 8 without editing config.json.
* Adjust
* Adjust
---------
Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
Checking for updates always dialed through the local proxy, which fails
exactly when an update may be needed most - when no working server is
available. Like the subscription-update menu, updating without the proxy
is now possible: the Check Update window gets an "Update via proxy"
toggle (persisted, on by default so existing behavior is unchanged),
honored by the check-only, update and geo-file flows, and by the
scheduled update check.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Support sing-box 1.14
* Unified format
* Support parallel dns
* Add `optimistic DNS caching` support
* Try fix serial multi DNS
* Add HttpClient support
#9930 made the Xray TUN inbound always request ::/0 in autoSystemRoutingTable
so that IPv6 stops bypassing the tunnel. That only helps a host which actually
holds a globally routable IPv6 address. On any other host it does harm.
With IPv6 disabled the TUN device gets no IPv6 address at all, the kernel
rejects the route with EACCES and the whole inbound fails to start:
Failed to start: app/proxyman/inbound: failed to start proxy > proxy/tun:
failed to add system route ::/0 > permission denied
With IPv6 enabled but no global address the route is accepted and the host
gains an IPv6 default route it cannot use. The TUN completes the TCP handshake
locally before dialing the outbound, so IPv6 destinations start to look
reachable and get picked, and the connection then dies at the outbound instead
of failing fast (#10051).
Neither host has IPv6 traffic that could bypass the tunnel, so ::/0 buys them
nothing. Detect a global IPv6 address once while building the config context
and drop ::/0 when there is none. Link-local and unique local addresses do not
count: they never reach the IPv6 internet.
Co-authored-by: liuclare <177657698+liuclare@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The Code Test workflow only has a pull_request trigger, so the suite
never runs against master itself: a direct push is untested, and a
merge can break tests even when the pull request's own check was
green, because checks run on the PR head rather than on the merged
result. Add a push trigger for master with the same paths filter.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
`Utils.ParseQueryString` already unescapes every value, and
`BaseFmt.GetQueryDecoded` unescaped it again. A value that still held a
valid percent sequence after the first pass decayed on the second: an
obfuscation password of `ob%41fs` is exported as `ob%2541fs` and imported
back as `obAfs`. Only well-formed sequences are affected, which is why the
damage is silent - `100%` and `66%ff` survive untouched.
The same function also split each pair on every `=`, and skipped the pair
unless exactly two halves came out. RFC 3986 lists `=` among the
sub-delimiters a query value may carry, so only the first one separates the
key from the value, and `HttpUtility.ParseQueryString` reads a query string
the same way. Splitting on all of them discarded a syntactically valid
pair: `?ech=AAj+DQAEAAAAAA==` was lost entirely, and so was a `plugin`
value in the non-canonical SIP002 spelling, since those are `;` separated
`key=value` lists.
v2rayN percent-encodes both on export, so its own links were never
affected; what changes is that the parser now follows the grammar instead
of discarding a pair it cannot split in two.
Splitting on the first `=` only, and reading the value the parser already
decoded, fixes both. `ParseQueryString` keeps decoding because
`ConfigHandler` reads its result directly.
`GetQueryDecoded` and `GetQueryValue` are now equivalent; they are left
separate to keep this change small, and can be collapsed if you prefer.
The Hysteria2 URI scheme makes the port optional: "The hostname and
optional port of the server. If the port is omitted, it defaults to 443."
`Hysteria2Fmt.Resolve` assigned `url.Port` straight through, and
`System.Uri` answers -1 for an unregistered scheme that carries no port,
so `hysteria2://password@hy2.example/` imported as a profile with
`Port = -1`. `ProfileItem.IsValid` rejects any port outside 1..65535, so
such a link produced a profile that could never be used, and nothing said
why.
-1 is the only value that means "the port was omitted"; a ':' with no
digits after it maps to -1 as well. An explicit ":0" parses as 0 and
keeps the fate it has today - rejected by `IsValid` - rather than being
redirected to a server the link never named.
`ResolveRealm` takes its port from `HyRealm.RendezvousPort` instead of
the URI, so it is unaffected.
The added tests cover both spellings of the scheme, with and without a
trailing slash, a bare ':', and the resulting profile's validity. Two of
them are controls: an explicit port is still preserved, and an explicit
":0" still does not turn into 443.
`FmtHandlerTests` round-tripped VMess, VLESS, Shadowsocks and SOCKS.
`FmtHandler.GetShareUri` dispatches ten protocols, so Trojan, Hysteria2,
TUIC, Anytls, WireGuard and Naive were exported and re-imported untested,
and `WireguardFmt` was covered in the `Resolve` direction only.
Each new test exports a profile, imports the result and asserts the fields
that protocol carries in its URI: the flow for Trojan, the uuid/password
pair and the congestion control for TUIC, the obfuscation password and the
port range for Hysteria2, the peer keys, reserved bytes, interface address
and MTU for WireGuard, and the credentials plus the insecure concurrency
for Naive.
`ShareUriSuite_ShouldCoverAndRoundTripEveryExportableProtocol` compares the
profile-factory map against `Global.ProtocolShares` and round-trips every
entry, so a newly exportable protocol cannot be added without a case here.
Three things a round trip alone cannot prove are asserted on the wire form
instead. The allow-insecure flag is spelled per protocol since #9888 -
`allowInsecure` and `insecure` for Trojan, `allow_insecure` for TUIC,
`insecure` for Anytls and Hysteria2 - so an exporter and an importer that
agreed on the wrong name would otherwise round-trip cleanly. The WireGuard
test pins the percent-encoding of the base64 keys and the brackets around
the IPv6 literal. Hysteria2 keeps `CertSha` unset on purpose: the importer
turns `AllowInsecure` on by itself when a `pinSHA256` is present, which
would mask an exporter that stopped emitting `insecure=1`.
Fixtures are deterministic and no longer plain ASCII: a fixed uuid for
TUIC, real 32-byte base64 keys and an IPv6 address for WireGuard, and
reserved and non-Latin characters in passwords and remarks.
`ExportThenImport` derives the expected scheme, because `NaiveFmt` emits
`naive+https://` or `naive+quic://` and never the `naive://` prefix that
`Global.ProtocolShares` records for that type - that entry is only read
when importing.
Follow-ups to #10007, none of which change what the test command does.
The `paths:` filter listed individual source folders rather than the
projects the suite builds, so a change anywhere else in that build
produced no check at all. Of the last 40 merged pull requests, 31 touch
the test build and 15 of those ran no tests. #9976 and #9932 edit
`ServiceLib/Common/`, which every test depends on, and neither shows a
single check. `Directory.Build.props` is the sharpest case: it sets
`TargetFramework` and the Release options for every project, so an edit
there can break the test build without producing a workflow run at all.
The filter now follows the project graph instead. `ServiceLib.Tests`
references `ServiceLib`, which references `ServiceLib.UdpTest`, and
`Directory.Build.*`, `Directory.Packages.props` and `global.json`
configure that build. It is shorter than the list it replaces, needs no
edit when a test is added or a class moves, and still skips UI and
documentation work: of those same 40 pull requests, 9 stay filtered out.
`global.json` belongs there for a different reason: it does not affect a
single line of the code under test, but it decides whether the tests run
at all, so a bad edit there silently reproduces the failure #10007 fixed.
The Checkout step needs neither `submodules: 'recursive'` nor
`fetch-depth: '0'`. `GlobalHotKeys` is pulled in by `v2rayN.Desktop`
only, and nothing in this job reads git history.
`global.json` also gained the final newline `.editorconfig` asks for with
`insert_final_newline = true` under `[*]`.
* i18n(ru): translate newly added UI strings
Translate the 3 strings missing from ResUI.ru.resx after the DNS
"Block AAAA Queries" toggle and the Xray-only certificate pinning
hint were introduced:
- TbXrayOnly, TbBlockAAAAQueries, TbBlockAAAAQueriesTips
Translated from the zh-Hans source and cross-checked against the
English resource. Russian regains full key parity with ResUI.resx
(583/583), and key ordering mirrors the English resource file.
Xray and the AAAA record type stay untranslated, matching the
established glossary; the phrasing follows the neighbouring
TbBlockSVCBHTTPSQueries label and the existing "При включении" tip pattern.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* i18n(ru): translate TbBlockSVCBHTTPSQueriesTips left in English
The key existed in ResUI.ru.resx but its value was the untranslated
English text, so the DNS settings window mixed Russian and English
in the row right above the newly translated "Block AAAA Queries".
Translated from the zh-Hans source, which says "availability
queries" (可用性查询); the Russian follows that wording rather than
the English "checks". ECH, HTTP/3 and Xray stay untranslated,
matching the established glossary, and the tip keeps the
"При включении …" pattern used by the surrounding tips.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* chore(deps): update CliWrap and TUnit
- CliWrap 3.10.4 -> 3.10.5
- TUnit 1.65.0 -> 1.65.38
- TUnit.Assertions.Should 1.65.0-beta -> 1.65.38-beta
TUnit.Assertions.Should is versioned in lockstep with TUnit and published with
a -beta suffix. Its 1.65.0-beta package depends on TUnit.Assertions 1.65.0-beta,
so it has to move together with TUnit to keep the whole TUnit stack resolved on
a single version (TUnit.Assertions 1.65.38 after this change).
* chore(deps): drop unused AwesomeAssertions and xunit.v3 pins
Since the migration to TUnit (c9e843aa) no project references AwesomeAssertions
or xunit.v3 any more, so these two PackageVersion entries no longer pin
anything: neither package appears in any project.assets.json, directly or
transitively.
Verified by restoring, building and publishing the whole solution with and
without the two entries: the resolved package graph (769 entries across all
projects) and the published output of every CI target - v2rayN win-x64,
v2rayN.Desktop win-x64 and linux-x64, AmazTool win-x64, all self-contained -
are byte-identical, and ServiceLib.Tests stays at 69/69.
* chore(deps): update xunit.v3 to 4.0.0 and drop the VSTest packages
xunit.v3 4.0.0 moves from Microsoft.Testing.Platform v1 to v2, and MTP v2 drops the VSTest bridge on the .NET 10 SDK, so anything routed through VSTest now fails before a single test runs.
Rather than bridging back to VSTest, the two VSTest-era packages are removed. The test project is already an executable carrying xunit's own in-process runner, so Microsoft.NET.Test.Sdk and xunit.runner.visualstudio have nothing left to contribute, and without them no opt-in file is needed anywhere.
No source or test changes are required: every 4.0.0 breaking change is in the extensibility and runner APIs, and the suite uses only [Fact], [Theory] and [InlineData].
* ci: run the tests directly and let versions float on their major
test.yml requested the 8.0.x SDK while every project targets net10.0, which an 8.0 SDK cannot build (NETSDK1045), and it invoked dotnet test, which needs the VSTest bridge that MTP v2 has dropped. It now runs the test executable, which needs no adapter and no test SDK.
All three setup-dotnet steps ask for 10.x with quality ga, so a new .NET 10 patch or feature band is picked up automatically while previews and release candidates stay out of builds. setup-dotnet and upload-artifact were the only actions pinned to an exact patch; they now track their major tag like the other seven.
* chore(deps): update NLog to 6.2.0
A minor release with no API change on the surface this project uses. Verified beyond compilation: Logging.Setup builds its FileTarget, and both SaveLog overloads write through it at runtime with the expected layout.