Support proxies search Support svg display Optimize config persistence Add some scenes auto close connections Update core Optimize more details
157 lines
3.9 KiB
Dart
157 lines
3.9 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:ffi';
|
|
import 'dart:io';
|
|
import 'dart:isolate';
|
|
import 'dart:ui';
|
|
|
|
import 'package:fl_clash/plugins/app.dart';
|
|
import 'package:fl_clash/plugins/tile.dart';
|
|
import 'package:fl_clash/plugins/vpn.dart';
|
|
import 'package:fl_clash/state.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import 'application.dart';
|
|
import 'clash/core.dart';
|
|
import 'clash/lib.dart';
|
|
import 'common/common.dart';
|
|
import 'models/models.dart';
|
|
|
|
Future<void> main() async {
|
|
globalState.isService = false;
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
final version = await system.version;
|
|
await clashCore.preload();
|
|
await globalState.initApp(version);
|
|
await android?.init();
|
|
await window?.init(version);
|
|
HttpOverrides.global = FlClashHttpOverrides();
|
|
runApp(ProviderScope(
|
|
child: const Application(),
|
|
));
|
|
}
|
|
|
|
@pragma('vm:entry-point')
|
|
Future<void> _service(List<String> flags) async {
|
|
globalState.isService = true;
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
final quickStart = flags.contains("quick");
|
|
final clashLibHandler = ClashLibHandler();
|
|
await globalState.init();
|
|
|
|
tile?.addListener(
|
|
_TileListenerWithService(
|
|
onStop: () async {
|
|
await app?.tip(appLocalizations.stopVpn);
|
|
clashLibHandler.stopListener();
|
|
await vpn?.stop();
|
|
exit(0);
|
|
},
|
|
),
|
|
);
|
|
|
|
vpn?.handleGetStartForegroundParams = () {
|
|
final traffic = clashLibHandler.getTraffic();
|
|
return json.encode({
|
|
"title": clashLibHandler.getCurrentProfileName(),
|
|
"content": "$traffic"
|
|
});
|
|
};
|
|
|
|
vpn?.addListener(
|
|
_VpnListenerWithService(
|
|
onDnsChanged: (String dns) {
|
|
clashLibHandler.updateDns(dns);
|
|
},
|
|
),
|
|
);
|
|
if (!quickStart) {
|
|
_handleMainIpc(clashLibHandler);
|
|
} else {
|
|
commonPrint.log("quick start");
|
|
await ClashCore.initGeo();
|
|
app?.tip(appLocalizations.startVpn);
|
|
final homeDirPath = await appPath.homeDirPath;
|
|
final version = await system.version;
|
|
final clashConfig = globalState.config.patchClashConfig.copyWith.tun(
|
|
enable: false,
|
|
);
|
|
Future(() async {
|
|
final profileId = globalState.config.currentProfileId;
|
|
if (profileId == null) {
|
|
return;
|
|
}
|
|
final params = await globalState.getSetupParams(
|
|
pathConfig: clashConfig,
|
|
);
|
|
final res = await clashLibHandler.quickStart(
|
|
InitParams(
|
|
homeDir: homeDirPath,
|
|
version: version,
|
|
),
|
|
params,
|
|
globalState.getCoreState(),
|
|
);
|
|
debugPrint(res);
|
|
if (res.isNotEmpty) {
|
|
await vpn?.stop();
|
|
exit(0);
|
|
}
|
|
await vpn?.start(
|
|
clashLibHandler.getAndroidVpnOptions(),
|
|
);
|
|
clashLibHandler.startListener();
|
|
});
|
|
}
|
|
}
|
|
|
|
_handleMainIpc(ClashLibHandler clashLibHandler) {
|
|
final sendPort = IsolateNameServer.lookupPortByName(mainIsolate);
|
|
if (sendPort == null) {
|
|
return;
|
|
}
|
|
final serviceReceiverPort = ReceivePort();
|
|
serviceReceiverPort.listen((message) async {
|
|
final res = await clashLibHandler.invokeAction(message);
|
|
sendPort.send(res);
|
|
});
|
|
sendPort.send(serviceReceiverPort.sendPort);
|
|
final messageReceiverPort = ReceivePort();
|
|
clashLibHandler.attachMessagePort(
|
|
messageReceiverPort.sendPort.nativePort,
|
|
);
|
|
messageReceiverPort.listen((message) {
|
|
sendPort.send(message);
|
|
});
|
|
}
|
|
|
|
@immutable
|
|
class _TileListenerWithService with TileListener {
|
|
final Function() _onStop;
|
|
|
|
const _TileListenerWithService({
|
|
required Function() onStop,
|
|
}) : _onStop = onStop;
|
|
|
|
@override
|
|
void onStop() {
|
|
_onStop();
|
|
}
|
|
}
|
|
|
|
@immutable
|
|
class _VpnListenerWithService with VpnListener {
|
|
final Function(String dns) _onDnsChanged;
|
|
|
|
const _VpnListenerWithService({
|
|
required Function(String dns) onDnsChanged,
|
|
}) : _onDnsChanged = onDnsChanged;
|
|
|
|
@override
|
|
void onDnsChanged(String dns) {
|
|
super.onDnsChanged(dns);
|
|
_onDnsChanged(dns);
|
|
}
|
|
}
|