feat(network): VPN bypass — bind to non-VPN net (wlan*/rmnet*) when tun detected + dev toggle

This commit is contained in:
klockky
2026-05-16 07:45:29 +03:00
parent 254afb1e95
commit 6e3cdc434d
5 changed files with 353 additions and 1 deletions
@@ -159,6 +159,73 @@ class _DebugMenuScreenState extends State<DebugMenuScreen> {
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),
child: appState == null
? const SizedBox.shrink()
: ValueListenableBuilder<bool>(
valueListenable: appState.vpnBypassEnabled,
builder: (context, bypassOn, _) {
return Container(
decoration: BoxDecoration(
color: cs.surfaceContainerHigh,
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 17,
),
child: Row(
children: [
Icon(
Symbols.vpn_key_off,
color: cs.onSurfaceVariant,
size: 22,
weight: 400,
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'Обход VPN',
style: TextStyle(
color: cs.onSurface,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 2),
Text(
'Если обнаружен VPN (tun-интерфейс), '
'подключаться напрямую через Wi-Fi или '
'моб. сеть в обход туннеля. Только Android',
style: TextStyle(
color: cs.onSurfaceVariant,
fontSize: 13,
),
),
],
),
),
Switch(
value: bypassOn,
onChanged: (v) {
appState.setVpnBypassEnabled(v);
},
),
],
),
),
);
},
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),