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
193 lines
4.9 KiB
Dart
193 lines
4.9 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:dio/dio.dart';
|
|
import 'package:dio/io.dart';
|
|
import 'package:fl_clash/common/common.dart';
|
|
import 'package:fl_clash/models/models.dart';
|
|
import 'package:fl_clash/state.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
class Request {
|
|
late final Dio _dio;
|
|
late final Dio _clashDio;
|
|
String? userAgent;
|
|
|
|
Request() {
|
|
_dio = Dio(
|
|
BaseOptions(
|
|
headers: {
|
|
"User-Agent": browserUa,
|
|
},
|
|
),
|
|
);
|
|
_clashDio = Dio();
|
|
_clashDio.httpClientAdapter = IOHttpClientAdapter(createHttpClient: () {
|
|
final client = HttpClient();
|
|
client.findProxy = (Uri uri) {
|
|
client.userAgent = globalState.ua;
|
|
return FlClashHttpOverrides.handleFindProxy(uri);
|
|
};
|
|
return client;
|
|
});
|
|
}
|
|
|
|
Future<Response> getFileResponseForUrl(String url) async {
|
|
final response = await _clashDio.get(
|
|
url,
|
|
options: Options(
|
|
responseType: ResponseType.bytes,
|
|
),
|
|
);
|
|
return response;
|
|
}
|
|
|
|
Future<MemoryImage?> getImage(String url) async {
|
|
if (url.isEmpty) return null;
|
|
final response = await _dio.get<Uint8List>(
|
|
url,
|
|
options: Options(
|
|
responseType: ResponseType.bytes,
|
|
),
|
|
);
|
|
final data = response.data;
|
|
if (data == null) return null;
|
|
return MemoryImage(data);
|
|
}
|
|
|
|
Future<Map<String, dynamic>?> checkForUpdate() async {
|
|
final response = await _dio.get(
|
|
"https://api.github.com/repos/$repository/releases/latest",
|
|
options: Options(
|
|
responseType: ResponseType.json,
|
|
),
|
|
);
|
|
if (response.statusCode != 200) return null;
|
|
final data = response.data as Map<String, dynamic>;
|
|
final remoteVersion = data['tag_name'];
|
|
final version = globalState.packageInfo.version;
|
|
final hasUpdate =
|
|
utils.compareVersions(remoteVersion.replaceAll('v', ''), version) > 0;
|
|
if (!hasUpdate) return null;
|
|
return data;
|
|
}
|
|
|
|
final Map<String, IpInfo Function(Map<String, dynamic>)> _ipInfoSources = {
|
|
"https://ipwho.is/": IpInfo.fromIpwhoIsJson,
|
|
"https://api.ip.sb/geoip/": IpInfo.fromIpSbJson,
|
|
"https://ipapi.co/json/": IpInfo.fromIpApiCoJson,
|
|
"https://ipinfo.io/json/": IpInfo.fromIpInfoIoJson,
|
|
};
|
|
|
|
Future<IpInfo?> checkIp({CancelToken? cancelToken}) async {
|
|
for (final source in _ipInfoSources.entries) {
|
|
try {
|
|
final response = await Dio()
|
|
.get<Map<String, dynamic>>(
|
|
source.key,
|
|
cancelToken: cancelToken,
|
|
options: Options(
|
|
responseType: ResponseType.json,
|
|
),
|
|
)
|
|
.timeout(
|
|
Duration(
|
|
seconds: 30,
|
|
),
|
|
);
|
|
if (response.statusCode != 200 || response.data == null) {
|
|
continue;
|
|
}
|
|
if (response.data == null) {
|
|
continue;
|
|
}
|
|
return source.value(response.data!);
|
|
} catch (e) {
|
|
commonPrint.log("checkIp error ===> $e");
|
|
if (e is DioException && e.type == DioExceptionType.cancel) {
|
|
throw "cancelled";
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
Future<bool> pingHelper() async {
|
|
try {
|
|
final response = await _dio
|
|
.get(
|
|
"http://$localhost:$helperPort/ping",
|
|
options: Options(
|
|
responseType: ResponseType.plain,
|
|
),
|
|
)
|
|
.timeout(
|
|
const Duration(
|
|
milliseconds: 2000,
|
|
),
|
|
);
|
|
if (response.statusCode != HttpStatus.ok) {
|
|
return false;
|
|
}
|
|
return (response.data as String) == globalState.coreSHA256;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> startCoreByHelper(String arg) async {
|
|
try {
|
|
final response = await _dio
|
|
.post(
|
|
"http://$localhost:$helperPort/start",
|
|
data: json.encode({
|
|
"path": appPath.corePath,
|
|
"arg": arg,
|
|
}),
|
|
options: Options(
|
|
responseType: ResponseType.plain,
|
|
),
|
|
)
|
|
.timeout(
|
|
const Duration(
|
|
milliseconds: 2000,
|
|
),
|
|
);
|
|
if (response.statusCode != HttpStatus.ok) {
|
|
return false;
|
|
}
|
|
final data = response.data as String;
|
|
return data.isEmpty;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> stopCoreByHelper() async {
|
|
try {
|
|
final response = await _dio
|
|
.post(
|
|
"http://$localhost:$helperPort/stop",
|
|
options: Options(
|
|
responseType: ResponseType.plain,
|
|
),
|
|
)
|
|
.timeout(
|
|
const Duration(
|
|
milliseconds: 2000,
|
|
),
|
|
);
|
|
if (response.statusCode != HttpStatus.ok) {
|
|
return false;
|
|
}
|
|
final data = response.data as String;
|
|
return data.isEmpty;
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
final request = Request();
|