mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-02-11 17:50:23 +00:00
feat: WASM web support
This commit is contained in:
@@ -6,9 +6,9 @@ import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
|
||||
class URLConf {
|
||||
/// HOME API
|
||||
static String gitApiHome = "https://git.scbox.xkeyc.cn";
|
||||
static String newsApiHome = "https://scbox.citizenwiki.cn";
|
||||
static const String analyticsApiHome = "https://scbox.org";
|
||||
static String gitApiHome = "https://ecdn.git.scbox.xkeyc.cn";
|
||||
static String newsApiHome = "https://ecdn.news.scbox.xkeyc.cn";
|
||||
static const String analyticsApiHome = "https://web-proxy.scbox.xkeyc.cn/analytics/analytics";
|
||||
|
||||
static bool isUrlCheckPass = false;
|
||||
|
||||
@@ -28,7 +28,7 @@ class URLConf {
|
||||
static const feedbackUrl = "https://support.citizenwiki.cn/all";
|
||||
static const feedbackFAQUrl = "https://support.citizenwiki.cn/t/sc-toolbox";
|
||||
static String nav42KitUrl =
|
||||
"https://payload.citizenwiki.cn/api/community-navs?sort=is_sponsored&depth=2&page=1&limit=1000";
|
||||
"https://ecdn.42nav.xkeyc.cn/api/community-navs?sort=is_sponsored&depth=2&page=1&limit=1000";
|
||||
|
||||
static String get devReleaseUrl => "$gitApiHome/SCToolBox/Release/releases";
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/conf.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
|
||||
class SCLoggerHelper {
|
||||
static Future<String?> getLogFilePath() async {
|
||||
if (!Platform.isWindows) return null;
|
||||
if (kIsWeb || !Platform.isWindows) return null;
|
||||
Map<String, String> envVars = Platform.environment;
|
||||
final appDataPath = envVars["appdata"];
|
||||
if (appDataPath == null) {
|
||||
@@ -31,7 +32,7 @@ class SCLoggerHelper {
|
||||
}
|
||||
|
||||
static Future<List?> getLauncherLogList() async {
|
||||
if (!Platform.isWindows) return [];
|
||||
if (kIsWeb || !Platform.isWindows) return [];
|
||||
try {
|
||||
final jsonLogPath = await getLogFilePath();
|
||||
if (jsonLogPath == null) throw "no file path";
|
||||
@@ -43,9 +44,11 @@ class SCLoggerHelper {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<List<String>> getGameInstallPath(List listData,
|
||||
{bool checkExists = true,
|
||||
List<String> withVersion = const ["LIVE"]}) async {
|
||||
static Future<List<String>> getGameInstallPath(
|
||||
List listData, {
|
||||
bool checkExists = true,
|
||||
List<String> withVersion = const ["LIVE"],
|
||||
}) async {
|
||||
List<String> scInstallPaths = [];
|
||||
|
||||
checkAndAddPath(String path, bool checkExists) async {
|
||||
@@ -55,8 +58,7 @@ class SCLoggerHelper {
|
||||
if (!checkExists) {
|
||||
dPrint("find installPath == $path");
|
||||
scInstallPaths.add(path);
|
||||
} else if (await File("$path/Bin64/StarCitizen.exe").exists() &&
|
||||
await File("$path/Data.p4k").exists()) {
|
||||
} else if (await File("$path/Bin64/StarCitizen.exe").exists() && await File("$path/Data.p4k").exists()) {
|
||||
dPrint("find installPath == $path");
|
||||
scInstallPaths.add(path);
|
||||
}
|
||||
@@ -73,8 +75,7 @@ class SCLoggerHelper {
|
||||
|
||||
try {
|
||||
for (var v in withVersion) {
|
||||
String pattern =
|
||||
r'([a-zA-Z]:\\\\[^\\\\]*\\\\[^\\\\]*\\\\StarCitizen\\\\' + v + r')';
|
||||
String pattern = r'([a-zA-Z]:\\\\[^\\\\]*\\\\[^\\\\]*\\\\StarCitizen\\\\' + v + r')';
|
||||
RegExp regExp = RegExp(pattern, caseSensitive: false);
|
||||
for (var i = listData.length - 1; i > 0; i--) {
|
||||
final line = listData[i];
|
||||
@@ -91,8 +92,7 @@ class SCLoggerHelper {
|
||||
for (var v in withVersion) {
|
||||
if (fileName.toString().endsWith(v)) {
|
||||
for (var nv in withVersion) {
|
||||
final nextName =
|
||||
"${fileName.toString().replaceAll("\\$v", "")}\\$nv";
|
||||
final nextName = "${fileName.toString().replaceAll("\\$v", "")}\\$nv";
|
||||
await checkAndAddPath(nextName, true);
|
||||
}
|
||||
}
|
||||
@@ -121,8 +121,7 @@ class SCLoggerHelper {
|
||||
if (!await logFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
return await logFile.readAsLines(
|
||||
encoding: const Utf8Codec(allowMalformed: true));
|
||||
return await logFile.readAsLines(encoding: const Utf8Codec(allowMalformed: true));
|
||||
}
|
||||
|
||||
static MapEntry<String, String>? getGameRunningLogInfo(List<String> logs) {
|
||||
@@ -138,47 +137,47 @@ class SCLoggerHelper {
|
||||
|
||||
static MapEntry<String, String>? _checkRunningLine(String line) {
|
||||
if (line.contains("STATUS_CRYENGINE_OUT_OF_SYSMEM")) {
|
||||
return MapEntry(S.current.doctor_game_error_low_memory,
|
||||
S.current.doctor_game_error_low_memory_info);
|
||||
return MapEntry(S.current.doctor_game_error_low_memory, S.current.doctor_game_error_low_memory_info);
|
||||
}
|
||||
if (line.contains("EXCEPTION_ACCESS_VIOLATION")) {
|
||||
return MapEntry(S.current.doctor_game_error_generic_info,
|
||||
"https://docs.qq.com/doc/DUURxUVhzTmZoY09Z");
|
||||
return MapEntry(S.current.doctor_game_error_generic_info, "https://docs.qq.com/doc/DUURxUVhzTmZoY09Z");
|
||||
}
|
||||
if (line.contains("DXGI_ERROR_DEVICE_REMOVED")) {
|
||||
return MapEntry(S.current.doctor_game_error_gpu_crash,
|
||||
"https://www.bilibili.com/read/cv19335199");
|
||||
return MapEntry(S.current.doctor_game_error_gpu_crash, "https://www.bilibili.com/read/cv19335199");
|
||||
}
|
||||
if (line.contains("Wakeup socket sendto error")) {
|
||||
return MapEntry(S.current.doctor_game_error_socket_error,
|
||||
S.current.doctor_game_error_socket_error_info);
|
||||
return MapEntry(S.current.doctor_game_error_socket_error, S.current.doctor_game_error_socket_error_info);
|
||||
}
|
||||
|
||||
if (line.contains("The requested operation requires elevated")) {
|
||||
return MapEntry(S.current.doctor_game_error_permissions_error,
|
||||
S.current.doctor_game_error_permissions_error_info);
|
||||
return MapEntry(
|
||||
S.current.doctor_game_error_permissions_error,
|
||||
S.current.doctor_game_error_permissions_error_info,
|
||||
);
|
||||
}
|
||||
if (line.contains(
|
||||
"The process cannot access the file because is is being used by another process")) {
|
||||
return MapEntry(S.current.doctor_game_error_game_process_error,
|
||||
S.current.doctor_game_error_game_process_error_info);
|
||||
if (line.contains("The process cannot access the file because is is being used by another process")) {
|
||||
return MapEntry(
|
||||
S.current.doctor_game_error_game_process_error,
|
||||
S.current.doctor_game_error_game_process_error_info,
|
||||
);
|
||||
}
|
||||
if (line.contains("0xc0000043")) {
|
||||
return MapEntry(S.current.doctor_game_error_game_damaged_file,
|
||||
S.current.doctor_game_error_game_damaged_file_info);
|
||||
return MapEntry(
|
||||
S.current.doctor_game_error_game_damaged_file,
|
||||
S.current.doctor_game_error_game_damaged_file_info,
|
||||
);
|
||||
}
|
||||
if (line.contains("option to verify the content of the Data.p4k file")) {
|
||||
return MapEntry(S.current.doctor_game_error_game_damaged_p4k_file,
|
||||
S.current.doctor_game_error_game_damaged_p4k_file_info);
|
||||
return MapEntry(
|
||||
S.current.doctor_game_error_game_damaged_p4k_file,
|
||||
S.current.doctor_game_error_game_damaged_p4k_file_info,
|
||||
);
|
||||
}
|
||||
if (line.contains("OUTOFMEMORY Direct3D could not allocate")) {
|
||||
return MapEntry(S.current.doctor_game_error_low_gpu_memory,
|
||||
S.current.doctor_game_error_low_gpu_memory_info);
|
||||
return MapEntry(S.current.doctor_game_error_low_gpu_memory, S.current.doctor_game_error_low_gpu_memory_info);
|
||||
}
|
||||
if (line.contains(
|
||||
"try disabling with r_vulkanDisableLayers = 1 in your user.cfg")) {
|
||||
return MapEntry(S.current.doctor_game_error_gpu_vulkan_crash,
|
||||
S.current.doctor_game_error_gpu_vulkan_crash_info);
|
||||
if (line.contains("try disabling with r_vulkanDisableLayers = 1 in your user.cfg")) {
|
||||
return MapEntry(S.current.doctor_game_error_gpu_vulkan_crash, S.current.doctor_game_error_gpu_vulkan_crash_info);
|
||||
}
|
||||
|
||||
/// Unknown
|
||||
|
||||
@@ -30,7 +30,7 @@ class SystemHelper {
|
||||
"-Path",
|
||||
"\"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\stornvme\\Parameters\\Device\"",
|
||||
"-Name",
|
||||
"\"ForcedPhysicalSectorSizeInBytes\""
|
||||
"\"ForcedPhysicalSectorSizeInBytes\"",
|
||||
]);
|
||||
dPrint("checkNvmePatchStatus result ==== ${result.stdout}");
|
||||
if (result.stderr == "" && result.stdout.toString().contains("{* 4095}")) {
|
||||
@@ -52,7 +52,7 @@ class SystemHelper {
|
||||
"ForcedPhysicalSectorSizeInBytes",
|
||||
"-PropertyType MultiString",
|
||||
"-Force -Value",
|
||||
"\"* 4095\""
|
||||
"\"* 4095\"",
|
||||
]);
|
||||
dPrint("nvme_PhysicalBytes result == ${result.stdout}");
|
||||
return result.stderr;
|
||||
@@ -65,7 +65,7 @@ class SystemHelper {
|
||||
"-Path",
|
||||
"\"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\stornvme\\Parameters\\Device\"",
|
||||
"-Name",
|
||||
"\"ForcedPhysicalSectorSizeInBytes\""
|
||||
"\"ForcedPhysicalSectorSizeInBytes\"",
|
||||
]);
|
||||
dPrint("doRemoveNvmePath result ==== ${result.stdout}");
|
||||
if (result.stderr == "") {
|
||||
@@ -97,8 +97,9 @@ class SystemHelper {
|
||||
"$programDataPath\\Microsoft\\Windows\\Start Menu\\Programs\\Roberts Space Industries\\RSI Launcher.lnk";
|
||||
final rsiLinkFile = File(rsiFilePath);
|
||||
if (await rsiLinkFile.exists()) {
|
||||
final r = await Process.run(SystemHelper.powershellPath,
|
||||
["(New-Object -ComObject WScript.Shell).CreateShortcut(\"$rsiFilePath\").targetpath"]);
|
||||
final r = await Process.run(SystemHelper.powershellPath, [
|
||||
"(New-Object -ComObject WScript.Shell).CreateShortcut(\"$rsiFilePath\").targetpath",
|
||||
]);
|
||||
if (r.stdout.toString().contains("RSI Launcher.exe")) {
|
||||
final start = r.stdout.toString().split("RSI Launcher.exe");
|
||||
if (skipEXE) {
|
||||
@@ -147,22 +148,15 @@ class SystemHelper {
|
||||
if (processorAffinity == null) {
|
||||
Process.run(path, []);
|
||||
} else {
|
||||
Process.run("cmd.exe", [
|
||||
'/C',
|
||||
'Start',
|
||||
'""',
|
||||
'/High',
|
||||
'/Affinity',
|
||||
processorAffinity,
|
||||
path,
|
||||
]);
|
||||
Process.run("cmd.exe", ['/C', 'Start', '""', '/High', '/Affinity', processorAffinity, path]);
|
||||
}
|
||||
dPrint(path);
|
||||
}
|
||||
|
||||
static Future<int> getSystemMemorySizeGB() async {
|
||||
final r = await Process.run(
|
||||
powershellPath, ["(Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb"]);
|
||||
final r = await Process.run(powershellPath, [
|
||||
"(Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb",
|
||||
]);
|
||||
return int.tryParse(r.stdout.toString().trim()) ?? 0;
|
||||
}
|
||||
|
||||
@@ -196,10 +190,9 @@ foreach ($adapter in $adapterMemory) {
|
||||
}
|
||||
|
||||
static Future<String> getDiskInfo() async {
|
||||
return (await Process.run(powershellPath, ["Get-PhysicalDisk | format-table BusType,FriendlyName,Size"]))
|
||||
.stdout
|
||||
.toString()
|
||||
.trim();
|
||||
return (await Process.run(powershellPath, [
|
||||
"Get-PhysicalDisk | format-table BusType,FriendlyName,Size",
|
||||
])).stdout.toString().trim();
|
||||
}
|
||||
|
||||
static Future<int> getDirLen(String path, {List<String>? skipPath}) async {
|
||||
@@ -226,8 +219,9 @@ foreach ($adapter in $adapterMemory) {
|
||||
}
|
||||
|
||||
static Future<int> getNumberOfLogicalProcessors() async {
|
||||
final cpuNumberResult =
|
||||
await Process.run(powershellPath, ["(Get-WmiObject -Class Win32_Processor).NumberOfLogicalProcessors"]);
|
||||
final cpuNumberResult = await Process.run(powershellPath, [
|
||||
"(Get-WmiObject -Class Win32_Processor).NumberOfLogicalProcessors",
|
||||
]);
|
||||
if (cpuNumberResult.exitCode != 0) return 0;
|
||||
return int.tryParse(cpuNumberResult.stdout.toString().trim()) ?? 0;
|
||||
}
|
||||
@@ -257,8 +251,10 @@ foreach ($adapter in $adapterMemory) {
|
||||
static Future openDir(dynamic path, {bool isFile = false}) async {
|
||||
dPrint("SystemHelper.openDir path === $path");
|
||||
if (Platform.isWindows) {
|
||||
await Process.run(
|
||||
SystemHelper.powershellPath, ["explorer.exe", isFile ? "/select,$path" : "\"/select,\"$path\"\""]);
|
||||
await Process.run(SystemHelper.powershellPath, [
|
||||
"explorer.exe",
|
||||
isFile ? "/select,$path" : "\"/select,\"$path\"\"",
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/conf.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/http_api.dart' as rust_http;
|
||||
import 'package:starcitizen_doctor/common/rust/api/http_api.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/http_package.dart';
|
||||
|
||||
class RSHttp {
|
||||
static late Dio _dio;
|
||||
static Map<String, String> _defaultHeaders = {};
|
||||
|
||||
static Future<void> init() async {
|
||||
await rust_http.setDefaultHeader(headers: {
|
||||
_defaultHeaders = {
|
||||
"User-Agent":
|
||||
"SCToolBox/${ConstConf.appVersion} (${ConstConf.appVersionCode})${ConstConf.isMSE ? "" : " DEV"} RSHttp"
|
||||
});
|
||||
"SCToolBox/${ConstConf.appVersion} (${ConstConf.appVersionCode})${ConstConf.isMSE ? "" : " DEV"} RSHttp",
|
||||
};
|
||||
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
headers: _defaultHeaders,
|
||||
responseType: ResponseType.bytes,
|
||||
validateStatus: (status) => true, // 接受所有状态码
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<RustHttpResponse> get(
|
||||
@@ -20,14 +30,13 @@ class RSHttp {
|
||||
String? withIpAddress,
|
||||
bool? withCustomDns,
|
||||
}) async {
|
||||
final r = await rust_http.fetch(
|
||||
method: MyMethod.gets,
|
||||
return await _fetch(
|
||||
method: 'GET',
|
||||
url: url,
|
||||
headers: headers,
|
||||
withIpAddress: withIpAddress,
|
||||
withCustomDns: withCustomDns,
|
||||
);
|
||||
return r;
|
||||
}
|
||||
|
||||
static Future<String> getText(
|
||||
@@ -36,10 +45,7 @@ class RSHttp {
|
||||
String? withIpAddress,
|
||||
bool? withCustomDns,
|
||||
}) async {
|
||||
final r = await get(url,
|
||||
headers: headers,
|
||||
withIpAddress: withIpAddress,
|
||||
withCustomDns: withCustomDns);
|
||||
final r = await get(url, headers: headers, withIpAddress: withIpAddress, withCustomDns: withCustomDns);
|
||||
if (r.data == null) return "";
|
||||
final str = utf8.decode(r.data!);
|
||||
return str;
|
||||
@@ -57,15 +63,14 @@ class RSHttp {
|
||||
headers ??= {};
|
||||
headers["Content-Type"] = contentType;
|
||||
}
|
||||
final r = await rust_http.fetch(
|
||||
method: MyMethod.post,
|
||||
return await _fetch(
|
||||
method: 'POST',
|
||||
url: url,
|
||||
headers: headers,
|
||||
inputData: data,
|
||||
data: data,
|
||||
withIpAddress: withIpAddress,
|
||||
withCustomDns: withCustomDns,
|
||||
);
|
||||
return r;
|
||||
}
|
||||
|
||||
static Future<RustHttpResponse> head(
|
||||
@@ -74,21 +79,81 @@ class RSHttp {
|
||||
String? withIpAddress,
|
||||
bool? withCustomDns,
|
||||
}) async {
|
||||
final r = await rust_http.fetch(
|
||||
method: MyMethod.head,
|
||||
return await _fetch(
|
||||
method: 'HEAD',
|
||||
url: url,
|
||||
headers: headers,
|
||||
withIpAddress: withIpAddress,
|
||||
withCustomDns: withCustomDns,
|
||||
);
|
||||
return r;
|
||||
}
|
||||
|
||||
static Future<List<String>> dnsLookupTxt(String host) async {
|
||||
return await rust_http.dnsLookupTxt(host: host);
|
||||
// TXT 记录查询在 Web 平台上无法实现,返回空列表
|
||||
return [];
|
||||
}
|
||||
|
||||
static Future<List<String>> dnsLookupIps(String host) async {
|
||||
return await rust_http.dnsLookupIps(host: host);
|
||||
// Web 平台无法直接查询 DNS,返回空列表
|
||||
// 在 Web 平台上,DNS 解析由浏览器自动处理
|
||||
return [];
|
||||
}
|
||||
|
||||
static Future<RustHttpResponse> _fetch({
|
||||
required String method,
|
||||
required String url,
|
||||
Map<String, String>? headers,
|
||||
Uint8List? data,
|
||||
String? withIpAddress,
|
||||
bool? withCustomDns,
|
||||
}) async {
|
||||
try {
|
||||
final mergedHeaders = {..._defaultHeaders, ...?headers};
|
||||
|
||||
final response = await _dio.request(
|
||||
url,
|
||||
data: data,
|
||||
options: Options(
|
||||
method: method,
|
||||
headers: mergedHeaders,
|
||||
responseType: ResponseType.bytes,
|
||||
validateStatus: (status) => true,
|
||||
),
|
||||
);
|
||||
|
||||
// 将 Dio Response 转换为 RustHttpResponse
|
||||
return RustHttpResponse(
|
||||
statusCode: response.statusCode ?? 0,
|
||||
headers: _convertHeaders(response.headers.map),
|
||||
url: response.realUri.toString(),
|
||||
contentLength: response.headers.value('content-length') != null
|
||||
? BigInt.from(int.parse(response.headers.value('content-length')!))
|
||||
: null,
|
||||
version: MyHttpVersion.httpUnknown,
|
||||
remoteAddr: response.realUri.host,
|
||||
data: response.data is Uint8List ? response.data : null,
|
||||
);
|
||||
} catch (e) {
|
||||
// 发生错误时返回默认响应
|
||||
return RustHttpResponse(
|
||||
statusCode: 0,
|
||||
headers: {},
|
||||
url: url,
|
||||
contentLength: null,
|
||||
version: MyHttpVersion.httpUnknown,
|
||||
remoteAddr: '',
|
||||
data: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static Map<String, String> _convertHeaders(Map<String, List<String>> headers) {
|
||||
final result = <String, String>{};
|
||||
headers.forEach((key, value) {
|
||||
if (value.isNotEmpty) {
|
||||
result[key] = value.join(', ');
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import '../frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
|
||||
Future<RsiLauncherAsarData> getRsiLauncherAsarData({
|
||||
required String asarPath,
|
||||
}) => RustLib.instance.api.crateApiAsarApiGetRsiLauncherAsarData(
|
||||
asarPath: asarPath,
|
||||
);
|
||||
|
||||
class RsiLauncherAsarData {
|
||||
final String asarPath;
|
||||
final String mainJsPath;
|
||||
final Uint8List mainJsContent;
|
||||
|
||||
const RsiLauncherAsarData({
|
||||
required this.asarPath,
|
||||
required this.mainJsPath,
|
||||
required this.mainJsContent,
|
||||
});
|
||||
|
||||
Future<void> writeMainJs({required List<int> content}) =>
|
||||
RustLib.instance.api.crateApiAsarApiRsiLauncherAsarDataWriteMainJs(
|
||||
that: this,
|
||||
content: content,
|
||||
);
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
asarPath.hashCode ^ mainJsPath.hashCode ^ mainJsContent.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is RsiLauncherAsarData &&
|
||||
runtimeType == other.runtimeType &&
|
||||
asarPath == other.asarPath &&
|
||||
mainJsPath == other.mainJsPath &&
|
||||
mainJsContent == other.mainJsContent;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import '../frb_generated.dart';
|
||||
import '../http_package.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
|
||||
// These functions are ignored because they are not marked as `pub`: `_my_method_to_hyper_method`
|
||||
|
||||
Future<void> setDefaultHeader({required Map<String, String> headers}) =>
|
||||
RustLib.instance.api.crateApiHttpApiSetDefaultHeader(headers: headers);
|
||||
|
||||
Future<RustHttpResponse> fetch({
|
||||
required MyMethod method,
|
||||
required String url,
|
||||
Map<String, String>? headers,
|
||||
Uint8List? inputData,
|
||||
String? withIpAddress,
|
||||
bool? withCustomDns,
|
||||
}) => RustLib.instance.api.crateApiHttpApiFetch(
|
||||
method: method,
|
||||
url: url,
|
||||
headers: headers,
|
||||
inputData: inputData,
|
||||
withIpAddress: withIpAddress,
|
||||
withCustomDns: withCustomDns,
|
||||
);
|
||||
|
||||
Future<List<String>> dnsLookupTxt({required String host}) =>
|
||||
RustLib.instance.api.crateApiHttpApiDnsLookupTxt(host: host);
|
||||
|
||||
Future<List<String>> dnsLookupIps({required String host}) =>
|
||||
RustLib.instance.api.crateApiHttpApiDnsLookupIps(host: host);
|
||||
|
||||
enum MyMethod { options, gets, post, put, delete, head, trace, connect, patch }
|
||||
@@ -1,50 +0,0 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import '../frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
|
||||
// These functions are ignored because they are not marked as `pub`: `_process_output`
|
||||
// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `RsProcess`
|
||||
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`
|
||||
|
||||
Stream<RsProcessStreamData> start({
|
||||
required String executable,
|
||||
required List<String> arguments,
|
||||
required String workingDirectory,
|
||||
}) => RustLib.instance.api.crateApiRsProcessStart(
|
||||
executable: executable,
|
||||
arguments: arguments,
|
||||
workingDirectory: workingDirectory,
|
||||
);
|
||||
|
||||
Future<void> write({required int rsPid, required String data}) =>
|
||||
RustLib.instance.api.crateApiRsProcessWrite(rsPid: rsPid, data: data);
|
||||
|
||||
class RsProcessStreamData {
|
||||
final RsProcessStreamDataType dataType;
|
||||
final String data;
|
||||
final int rsPid;
|
||||
|
||||
const RsProcessStreamData({
|
||||
required this.dataType,
|
||||
required this.data,
|
||||
required this.rsPid,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode => dataType.hashCode ^ data.hashCode ^ rsPid.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is RsProcessStreamData &&
|
||||
runtimeType == other.runtimeType &&
|
||||
dataType == other.dataType &&
|
||||
data == other.data &&
|
||||
rsPid == other.rsPid;
|
||||
}
|
||||
|
||||
enum RsProcessStreamDataType { output, error, exit }
|
||||
@@ -1,24 +1,15 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
// Web platform stub for win32_api
|
||||
// Windows API 在 Web 平台上不可用,提供空实现
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
/// 发送系统通知(Web 平台使用控制台输出)
|
||||
Future<void> sendNotify({String? summary, String? body, String? appName, String? appId}) async {
|
||||
print('Notification: $summary - $body');
|
||||
// Web 平台可以使用浏览器 Notification API
|
||||
// 但需要用户授权,这里简化处理
|
||||
}
|
||||
|
||||
import '../frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
|
||||
Future<void> sendNotify({
|
||||
String? summary,
|
||||
String? body,
|
||||
String? appName,
|
||||
String? appId,
|
||||
}) => RustLib.instance.api.crateApiWin32ApiSendNotify(
|
||||
summary: summary,
|
||||
body: body,
|
||||
appName: appName,
|
||||
appId: appId,
|
||||
);
|
||||
|
||||
Future<bool> setForegroundWindow({required String windowName}) => RustLib
|
||||
.instance
|
||||
.api
|
||||
.crateApiWin32ApiSetForegroundWindow(windowName: windowName);
|
||||
/// 设置窗口为前台(Web 平台不支持)
|
||||
Future<bool> setForegroundWindow({required String windowName}) async {
|
||||
print('setForegroundWindow not supported on web platform');
|
||||
return false;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,7 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
// HTTP 响应数据类
|
||||
// 原先由 flutter_rust_bridge 生成,现改为纯 Dart 实现
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import 'frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
import 'dart:typed_data';
|
||||
|
||||
enum MyHttpVersion { http09, http10, http11, http2, http3, httpUnknown }
|
||||
|
||||
|
||||
14
lib/common/utils/file_cache_utils_stub.dart
Normal file
14
lib/common/utils/file_cache_utils_stub.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
// Stub file for web platform - not used
|
||||
class FileCacheUtils {
|
||||
static Future<dynamic> getFile(String url) async {
|
||||
throw UnsupportedError('File operations are not supported on web platform');
|
||||
}
|
||||
|
||||
static Future<bool> clearCache(String url) async {
|
||||
throw UnsupportedError('File operations are not supported on web platform');
|
||||
}
|
||||
|
||||
static Future<void> clearAllCache() async {
|
||||
throw UnsupportedError('File operations are not supported on web platform');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user