Add linux deb dependencies Add backup recovery strategy select Support custom text scaling Optimize the display of different text scale Optimize windows setup experience Optimize startTun performance Optimize android tv experience Optimize default option Optimize computed text size Optimize hyperOS freeform window Add developer mode Update core Optimize more details
432 lines
9.3 KiB
Dart
432 lines
9.3 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
|
|
import 'package:fl_clash/clash/message.dart';
|
|
import 'package:fl_clash/common/common.dart';
|
|
import 'package:fl_clash/enum/enum.dart';
|
|
import 'package:fl_clash/models/models.dart';
|
|
|
|
mixin ClashInterface {
|
|
Future<bool> init(InitParams params);
|
|
|
|
Future<bool> preload();
|
|
|
|
Future<bool> shutdown();
|
|
|
|
Future<bool> get isInit;
|
|
|
|
Future<bool> forceGc();
|
|
|
|
FutureOr<String> validateConfig(String data);
|
|
|
|
Future<String> asyncTestDelay(String url, String proxyName);
|
|
|
|
FutureOr<String> updateConfig(UpdateConfigParams updateConfigParams);
|
|
|
|
FutureOr<String> getProxies();
|
|
|
|
FutureOr<String> changeProxy(ChangeProxyParams changeProxyParams);
|
|
|
|
Future<bool> startListener();
|
|
|
|
Future<bool> stopListener();
|
|
|
|
FutureOr<String> getExternalProviders();
|
|
|
|
FutureOr<String>? getExternalProvider(String externalProviderName);
|
|
|
|
Future<String> updateGeoData(UpdateGeoDataParams params);
|
|
|
|
Future<String> sideLoadExternalProvider({
|
|
required String providerName,
|
|
required String data,
|
|
});
|
|
|
|
Future<String> updateExternalProvider(String providerName);
|
|
|
|
FutureOr<String> getTraffic();
|
|
|
|
FutureOr<String> getTotalTraffic();
|
|
|
|
FutureOr<String> getCountryCode(String ip);
|
|
|
|
FutureOr<String> getMemory();
|
|
|
|
resetTraffic();
|
|
|
|
startLog();
|
|
|
|
stopLog();
|
|
|
|
Future<bool> crash();
|
|
|
|
FutureOr<String> getConnections();
|
|
|
|
FutureOr<bool> closeConnection(String id);
|
|
|
|
FutureOr<bool> closeConnections();
|
|
|
|
FutureOr<String> getProfile(String id);
|
|
|
|
Future<bool> setState(CoreState state);
|
|
}
|
|
|
|
mixin AndroidClashInterface {
|
|
Future<bool> setFdMap(int fd);
|
|
|
|
Future<bool> setProcessMap(ProcessMapItem item);
|
|
|
|
// Future<bool> stopTun();
|
|
|
|
Future<bool> updateDns(String value);
|
|
|
|
Future<AndroidVpnOptions?> getAndroidVpnOptions();
|
|
|
|
Future<String> getCurrentProfileName();
|
|
|
|
Future<DateTime?> getRunTime();
|
|
}
|
|
|
|
abstract class ClashHandlerInterface with ClashInterface {
|
|
Map<String, Completer> callbackCompleterMap = {};
|
|
|
|
Future<bool> nextHandleResult(ActionResult result, Completer? completer) =>
|
|
Future.value(false);
|
|
|
|
handleResult(ActionResult result) async {
|
|
final completer = callbackCompleterMap[result.id];
|
|
try {
|
|
switch (result.method) {
|
|
case ActionMethod.initClash:
|
|
case ActionMethod.shutdown:
|
|
case ActionMethod.getIsInit:
|
|
case ActionMethod.startListener:
|
|
case ActionMethod.resetTraffic:
|
|
case ActionMethod.closeConnections:
|
|
case ActionMethod.closeConnection:
|
|
case ActionMethod.stopListener:
|
|
case ActionMethod.setState:
|
|
case ActionMethod.crash:
|
|
completer?.complete(result.data as bool);
|
|
return;
|
|
case ActionMethod.changeProxy:
|
|
case ActionMethod.getProxies:
|
|
case ActionMethod.getTraffic:
|
|
case ActionMethod.getTotalTraffic:
|
|
case ActionMethod.asyncTestDelay:
|
|
case ActionMethod.getConnections:
|
|
case ActionMethod.getExternalProviders:
|
|
case ActionMethod.getExternalProvider:
|
|
case ActionMethod.validateConfig:
|
|
case ActionMethod.updateConfig:
|
|
case ActionMethod.updateGeoData:
|
|
case ActionMethod.updateExternalProvider:
|
|
case ActionMethod.sideLoadExternalProvider:
|
|
case ActionMethod.getCountryCode:
|
|
case ActionMethod.getMemory:
|
|
completer?.complete(result.data as String);
|
|
return;
|
|
case ActionMethod.message:
|
|
clashMessage.controller.add(result.data as String);
|
|
completer?.complete(true);
|
|
return;
|
|
default:
|
|
final isHandled = await nextHandleResult(result, completer);
|
|
if (isHandled) {
|
|
return;
|
|
}
|
|
completer?.complete(result.data);
|
|
}
|
|
} catch (_) {
|
|
commonPrint.log(result.id);
|
|
}
|
|
}
|
|
|
|
sendMessage(String message);
|
|
|
|
reStart();
|
|
|
|
FutureOr<bool> destroy();
|
|
|
|
Future<T> invoke<T>({
|
|
required ActionMethod method,
|
|
dynamic data,
|
|
Duration? timeout,
|
|
FutureOr<T> Function()? onTimeout,
|
|
}) async {
|
|
final id = "${method.name}#${utils.id}";
|
|
|
|
callbackCompleterMap[id] = Completer<T>();
|
|
|
|
dynamic defaultValue;
|
|
|
|
if (T == String) {
|
|
defaultValue = "";
|
|
}
|
|
if (T == bool) {
|
|
defaultValue = false;
|
|
}
|
|
|
|
sendMessage(
|
|
json.encode(
|
|
Action(
|
|
id: id,
|
|
method: method,
|
|
data: data,
|
|
defaultValue: defaultValue,
|
|
),
|
|
),
|
|
);
|
|
|
|
return (callbackCompleterMap[id] as Completer<T>).safeFuture(
|
|
timeout: timeout,
|
|
onLast: () {
|
|
callbackCompleterMap.remove(id);
|
|
},
|
|
onTimeout: onTimeout ??
|
|
() {
|
|
return defaultValue;
|
|
},
|
|
functionName: id,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> init(InitParams params) {
|
|
return invoke<bool>(
|
|
method: ActionMethod.initClash,
|
|
data: json.encode(params),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> setState(CoreState state) {
|
|
return invoke<bool>(
|
|
method: ActionMethod.setState,
|
|
data: json.encode(state),
|
|
);
|
|
}
|
|
|
|
@override
|
|
shutdown() async {
|
|
return await invoke<bool>(
|
|
method: ActionMethod.shutdown,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> get isInit {
|
|
return invoke<bool>(
|
|
method: ActionMethod.getIsInit,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> forceGc() {
|
|
return invoke<bool>(
|
|
method: ActionMethod.forceGc,
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> validateConfig(String data) {
|
|
return invoke<String>(
|
|
method: ActionMethod.validateConfig,
|
|
data: data,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<String> updateConfig(UpdateConfigParams updateConfigParams) async {
|
|
return await invoke<String>(
|
|
method: ActionMethod.updateConfig,
|
|
data: json.encode(updateConfigParams),
|
|
timeout: Duration(minutes: 2),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> crash() {
|
|
return invoke<bool>(
|
|
method: ActionMethod.crash,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<String> getProxies() {
|
|
return invoke<String>(
|
|
method: ActionMethod.getProxies,
|
|
timeout: Duration(seconds: 5),
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> changeProxy(ChangeProxyParams changeProxyParams) {
|
|
return invoke<String>(
|
|
method: ActionMethod.changeProxy,
|
|
data: json.encode(changeProxyParams),
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> getExternalProviders() {
|
|
return invoke<String>(
|
|
method: ActionMethod.getExternalProviders,
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> getExternalProvider(String externalProviderName) {
|
|
return invoke<String>(
|
|
method: ActionMethod.getExternalProvider,
|
|
data: externalProviderName,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<String> updateGeoData(UpdateGeoDataParams params) {
|
|
return invoke<String>(
|
|
method: ActionMethod.updateGeoData,
|
|
data: json.encode(params),
|
|
timeout: Duration(minutes: 1));
|
|
}
|
|
|
|
@override
|
|
Future<String> sideLoadExternalProvider({
|
|
required String providerName,
|
|
required String data,
|
|
}) {
|
|
return invoke<String>(
|
|
method: ActionMethod.sideLoadExternalProvider,
|
|
data: json.encode({
|
|
"providerName": providerName,
|
|
"data": data,
|
|
}),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<String> updateExternalProvider(String providerName) {
|
|
return invoke<String>(
|
|
method: ActionMethod.updateExternalProvider,
|
|
data: providerName,
|
|
timeout: Duration(minutes: 1),
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> getConnections() {
|
|
return invoke<String>(
|
|
method: ActionMethod.getConnections,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> closeConnections() {
|
|
return invoke<bool>(
|
|
method: ActionMethod.closeConnections,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> closeConnection(String id) {
|
|
return invoke<bool>(
|
|
method: ActionMethod.closeConnection,
|
|
data: id,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<String> getProfile(String id) {
|
|
return invoke<String>(
|
|
method: ActionMethod.getProfile,
|
|
data: id,
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> getTotalTraffic() {
|
|
return invoke<String>(
|
|
method: ActionMethod.getTotalTraffic,
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> getTraffic() {
|
|
return invoke<String>(
|
|
method: ActionMethod.getTraffic,
|
|
);
|
|
}
|
|
|
|
@override
|
|
resetTraffic() {
|
|
invoke(method: ActionMethod.resetTraffic);
|
|
}
|
|
|
|
@override
|
|
startLog() {
|
|
invoke(method: ActionMethod.startLog);
|
|
}
|
|
|
|
@override
|
|
stopLog() {
|
|
invoke<bool>(
|
|
method: ActionMethod.stopLog,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<bool> startListener() {
|
|
return invoke<bool>(
|
|
method: ActionMethod.startListener,
|
|
);
|
|
}
|
|
|
|
@override
|
|
stopListener() {
|
|
return invoke<bool>(
|
|
method: ActionMethod.stopListener,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<String> asyncTestDelay(String url, String proxyName) {
|
|
final delayParams = {
|
|
"proxy-name": proxyName,
|
|
"timeout": httpTimeoutDuration.inMilliseconds,
|
|
"test-url": url,
|
|
};
|
|
return invoke<String>(
|
|
method: ActionMethod.asyncTestDelay,
|
|
data: json.encode(delayParams),
|
|
timeout: Duration(
|
|
milliseconds: 6000,
|
|
),
|
|
onTimeout: () {
|
|
return json.encode(
|
|
Delay(
|
|
name: proxyName,
|
|
value: -1,
|
|
url: url,
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> getCountryCode(String ip) {
|
|
return invoke<String>(
|
|
method: ActionMethod.getCountryCode,
|
|
data: ip,
|
|
);
|
|
}
|
|
|
|
@override
|
|
FutureOr<String> getMemory() {
|
|
return invoke<String>(
|
|
method: ActionMethod.getMemory,
|
|
);
|
|
}
|
|
}
|