import 'dart:async'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:v2ray_box/v2ray_box.dart'; const MethodChannel _quickTileControlChannel = MethodChannel( 'vpn/quick_tile_control', ); final class _QuickTileController { final V2rayBox _box = V2rayBox(); bool _isInitialized = false; StreamSubscription? _statusSubscription; VpnStatus _lastStatus = VpnStatus.stopped; Future> handle(MethodCall call) async { switch (call.method) { case 'ping': return { 'success': true, 'ready': true, 'status': _lastStatus.name, 'connected': _isConnectedStatus(_lastStatus), }; case 'getStatus': return _statusPayload(); case 'toggleVpn': return _toggleVpn(call.arguments); default: return { 'success': false, 'connected': false, 'message': 'Unsupported method: ${call.method}', 'errorCode': 'unsupported_method', 'openApp': false, }; } } Future _ensureInitialized() async { if (_isInitialized) { return; } await _box.initialize(notificationStopButtonText: 'Stop'); _statusSubscription ??= _box.watchStatus().listen((status) { _lastStatus = status; }); _isInitialized = true; } bool _isConnectedStatus(VpnStatus status) { return status == VpnStatus.started; } Map _statusPayload() { return { 'success': true, 'ready': _isInitialized, 'status': _lastStatus.name, 'connected': _isConnectedStatus(_lastStatus), }; } Future> _toggleVpn(dynamic arguments) async { final args = arguments is Map ? Map.from(arguments) : {}; final String link = (args['link'] as String? ?? '').trim(); final String name = (args['name'] as String? ?? '').trim(); final bool proxyOnly = args['proxyOnly'] as bool? ?? false; final bool connected = args['connected'] as bool? ?? false; if (link.isEmpty) { return { 'success': false, 'connected': false, 'message': 'Config is empty', 'errorCode': 'empty_config', 'openApp': true, }; } try { await _ensureInitialized(); if (connected) { final bool stopped = await _box.disconnect(); return { 'success': stopped, 'connected': false, 'message': stopped ? null : 'Failed to disconnect', 'errorCode': stopped ? null : 'disconnect_failed', 'openApp': false, 'status': _lastStatus.name, }; } await _box.setServiceMode(proxyOnly ? VpnMode.proxy : VpnMode.vpn); final bool started = await _box.connect( link, name: name.isEmpty ? 'VPN' : name, ); return { 'success': started, 'connected': started, 'message': started ? null : 'Failed to connect', 'errorCode': started ? null : 'connect_failed', 'openApp': !started, 'status': _lastStatus.name, }; } catch (error) { return { 'success': false, 'connected': connected, 'message': 'Error: $error', 'errorCode': 'exception', 'openApp': true, 'status': _lastStatus.name, }; } } } @pragma('vm:entry-point') Future quickTileDispatcher() async { WidgetsFlutterBinding.ensureInitialized(); final controller = _QuickTileController(); _quickTileControlChannel.setMethodCallHandler(controller.handle); await Completer().future; }