SOCKS5 Reconnect re-attached to the session the device already held. It was the only path where a session began without an ad and without a nonce binding it to one, and supporting it cost three parameters - resume, release, resetSupportClaim - plus a carve-out in rule 4 that let _fetchActiveSession accept whatever nonce the server happened to return. It also wasn't the kindness it looked like. _handle_main calls create_or_replace with a fresh full window, so a new session hands the user *more* time, not less; re-attaching only preserved the remainder of a session whose proxy had just died. Reconnect now disconnects and connects again exactly as the button does, ad included. All four special cases are deleted and the nonce check is unconditional. Costs one rewarded ad to repair an orphaned proxy once ads are enabled. esef's call, and it buys a single way to start a session. Also fixes the 3.3.7 regression where Reconnect released the session and then asked for it back: there is no longer a path that does either. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
73d76c04f2
commit
571c07bca8
7 files changed
+75
-51
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:revoltvpn/logic/ad_manager.dart';
|
||||
import 'package:revoltvpn/logic/app_colors.dart';
|
||||
import 'package:revoltvpn/logic/connection_settings.dart';
|
||||
import 'package:revoltvpn/logic/local_socks_tester.dart';
|
||||
@@ -67,20 +68,27 @@ class _ConnectionModeTileState extends State<ConnectionModeTile> {
|
||||
widget.onChanged?.call(next);
|
||||
}
|
||||
|
||||
// Recovers an orphaned proxy: tear the runtime down and re-attach to the
|
||||
// session already held. No ad, no new session.
|
||||
// Recovers an orphaned proxy by ending the session and starting a new one,
|
||||
// exactly as the connect button does. Re-attaching to the session already
|
||||
// held was the one place a session began without an ad and without a nonce
|
||||
// to bind it to; a fresh one is the same path everywhere and hands back a
|
||||
// full window rather than the remainder of a broken one.
|
||||
Future<void> _reconnect() async {
|
||||
if (_reconnecting) return;
|
||||
final vpn = context.read<VpnConnection>();
|
||||
final timer = context.read<SessionTimer>();
|
||||
final ad = context.read<AdManager>();
|
||||
|
||||
setState(() => _reconnecting = true);
|
||||
try {
|
||||
await timer.disconnect(release: false);
|
||||
await timer.disconnect();
|
||||
if (!mounted) return;
|
||||
if (await vpn.connect(resume: true)) {
|
||||
final adNonce = await ad.showAd('main');
|
||||
if (adNonce == null && AdManager.adsEnabled) return;
|
||||
if (!mounted) return;
|
||||
if (await vpn.connect(adNonce: adNonce)) {
|
||||
if (!mounted) return;
|
||||
await timer.start(resetSupportClaim: false);
|
||||
await timer.start();
|
||||
}
|
||||
} finally {
|
||||
if (mounted) {
|
||||
|
||||
Reference in new issue
Block a user