mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-01-13 19:50:28 +00:00
Merge pull request #162 from StarCitizenToolBox/feat/move_powershell_to_rust_impl
Feat/move powershell to rust impl
This commit is contained in:
commit
c5de9e2252
11
lib/app.dart
11
lib/app.dart
@ -22,7 +22,6 @@ import 'package:window_manager/window_manager.dart';
|
||||
import 'api/analytics.dart';
|
||||
import 'api/api.dart';
|
||||
import 'common/conf/url_conf.dart';
|
||||
import 'common/helper/system_helper.dart';
|
||||
import 'common/io/rs_http.dart';
|
||||
import 'common/rust/frb_generated.dart';
|
||||
import 'common/rust/api/win32_api.dart' as win32;
|
||||
@ -148,16 +147,6 @@ class AppGlobalModel extends _$AppGlobalModel {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// init powershell
|
||||
if (Platform.isWindows) {
|
||||
try {
|
||||
await SystemHelper.initPowershellPath();
|
||||
dPrint("---- Powershell init -----");
|
||||
} catch (e) {
|
||||
dPrint("powershell init failed : $e");
|
||||
}
|
||||
}
|
||||
|
||||
// get windows info
|
||||
WindowsDeviceInfo? windowsDeviceInfo;
|
||||
try {
|
||||
|
||||
@ -5,76 +5,31 @@ import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/win32_api.dart' as win32;
|
||||
|
||||
class SystemHelper {
|
||||
static String powershellPath = "powershell.exe";
|
||||
|
||||
static Future<void> initPowershellPath() async {
|
||||
try {
|
||||
var result = await Process.run(powershellPath, ["echo", "pong"]);
|
||||
if (!result.stdout.toString().startsWith("pong") && powershellPath == "powershell.exe") {
|
||||
throw "powershell check failed";
|
||||
}
|
||||
} catch (e) {
|
||||
Map<String, String> envVars = Platform.environment;
|
||||
final systemRoot = envVars["SYSTEMROOT"];
|
||||
if (systemRoot != null) {
|
||||
final autoSearchPath = "$systemRoot\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
|
||||
dPrint("auto search powershell path === $autoSearchPath");
|
||||
powershellPath = autoSearchPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> checkNvmePatchStatus() async {
|
||||
try {
|
||||
var result = await Process.run(SystemHelper.powershellPath, [
|
||||
"Get-ItemProperty",
|
||||
"-Path",
|
||||
"\"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\stornvme\\Parameters\\Device\"",
|
||||
"-Name",
|
||||
"\"ForcedPhysicalSectorSizeInBytes\"",
|
||||
]);
|
||||
dPrint("checkNvmePatchStatus result ==== ${result.stdout}");
|
||||
if (result.stderr == "" && result.stdout.toString().contains("{* 4095}")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return await win32.checkNvmePatchStatus();
|
||||
} catch (e) {
|
||||
dPrint("checkNvmePatchStatus error: $e");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> addNvmePatch() async {
|
||||
var result = await Process.run(powershellPath, [
|
||||
'New-ItemProperty',
|
||||
"-Path",
|
||||
"\"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\stornvme\\Parameters\\Device\"",
|
||||
"-Name",
|
||||
"ForcedPhysicalSectorSizeInBytes",
|
||||
"-PropertyType MultiString",
|
||||
"-Force -Value",
|
||||
"\"* 4095\"",
|
||||
]);
|
||||
dPrint("nvme_PhysicalBytes result == ${result.stdout}");
|
||||
return result.stderr;
|
||||
try {
|
||||
await win32.addNvmePatch();
|
||||
return "";
|
||||
} catch (e) {
|
||||
dPrint("addNvmePatch error: $e");
|
||||
return e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> doRemoveNvmePath() async {
|
||||
try {
|
||||
var result = await Process.run(powershellPath, [
|
||||
"Clear-ItemProperty",
|
||||
"-Path",
|
||||
"\"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\stornvme\\Parameters\\Device\"",
|
||||
"-Name",
|
||||
"\"ForcedPhysicalSectorSizeInBytes\"",
|
||||
]);
|
||||
dPrint("doRemoveNvmePath result ==== ${result.stdout}");
|
||||
if (result.stderr == "") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
await win32.removeNvmePatch();
|
||||
return true;
|
||||
} catch (e) {
|
||||
dPrint("doRemoveNvmePath error: $e");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -98,15 +53,17 @@ 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",
|
||||
]);
|
||||
if (r.stdout.toString().contains("RSI Launcher.exe")) {
|
||||
final start = r.stdout.toString().split("RSI Launcher.exe");
|
||||
if (skipEXE) {
|
||||
return start[0];
|
||||
try {
|
||||
final targetPath = await win32.resolveShortcut(lnkPath: rsiFilePath);
|
||||
if (targetPath.contains("RSI Launcher.exe")) {
|
||||
final start = targetPath.split("RSI Launcher.exe");
|
||||
if (skipEXE) {
|
||||
return start[0];
|
||||
}
|
||||
return "${start[0]}RSI Launcher.exe";
|
||||
}
|
||||
return "${start[0]}RSI Launcher.exe";
|
||||
} catch (e) {
|
||||
dPrint("resolveShortcut error: $e");
|
||||
}
|
||||
}
|
||||
return "";
|
||||
@ -147,45 +104,78 @@ class SystemHelper {
|
||||
}
|
||||
|
||||
static Future<int> getSystemMemorySizeGB() async {
|
||||
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;
|
||||
try {
|
||||
final memoryGb = await win32.getSystemMemorySizeGb();
|
||||
return memoryGb.toInt();
|
||||
} catch (e) {
|
||||
dPrint("getSystemMemorySizeGB error: $e");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> getSystemCimInstance(String win32InstanceName, {pathName = "Name"}) async {
|
||||
final r = await Process.run(powershellPath, ["(Get-CimInstance $win32InstanceName).$pathName"]);
|
||||
return r.stdout.toString().trim();
|
||||
// This method is deprecated, use getSystemInfo() instead
|
||||
try {
|
||||
final sysInfo = await win32.getSystemInfo();
|
||||
if (win32InstanceName.contains("OperatingSystem")) {
|
||||
return sysInfo.osName;
|
||||
} else if (win32InstanceName.contains("Processor")) {
|
||||
return sysInfo.cpuName;
|
||||
} else if (win32InstanceName.contains("VideoController")) {
|
||||
return sysInfo.gpuInfo;
|
||||
} else if (win32InstanceName.contains("DiskDrive")) {
|
||||
return sysInfo.diskInfo;
|
||||
}
|
||||
} catch (e) {
|
||||
dPrint("getSystemCimInstance error: $e");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static Future<String> getSystemName() async {
|
||||
final r = await Process.run(powershellPath, ["(Get-ComputerInfo | Select-Object -expand OsName)"]);
|
||||
return r.stdout.toString().trim();
|
||||
try {
|
||||
final sysInfo = await win32.getSystemInfo();
|
||||
return sysInfo.osName;
|
||||
} catch (e) {
|
||||
dPrint("getSystemName error: $e");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> getCpuName() async {
|
||||
final r = await Process.run(powershellPath, ["(Get-WmiObject -Class Win32_Processor).Name"]);
|
||||
return r.stdout.toString().trim();
|
||||
try {
|
||||
final sysInfo = await win32.getSystemInfo();
|
||||
return sysInfo.cpuName;
|
||||
} catch (e) {
|
||||
dPrint("getCpuName error: $e");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> getGpuInfo() async {
|
||||
const cmd = r"""
|
||||
$adapterMemory = (Get-ItemProperty -Path "HKLM:\SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0*" -Name "HardwareInformation.AdapterString", "HardwareInformation.qwMemorySize" -Exclude PSPath -ErrorAction SilentlyContinue)
|
||||
foreach ($adapter in $adapterMemory) {
|
||||
[PSCustomObject] @{
|
||||
Model=$adapter."HardwareInformation.AdapterString"
|
||||
"VRAM (GB)"=[math]::round($adapter."HardwareInformation.qwMemorySize"/1GB)
|
||||
}
|
||||
}
|
||||
""";
|
||||
final r = await Process.run(powershellPath, [cmd]);
|
||||
return r.stdout.toString().trim();
|
||||
try {
|
||||
// Try registry first for more accurate VRAM info
|
||||
final regInfo = await win32.getGpuInfoFromRegistry();
|
||||
if (regInfo.isNotEmpty) {
|
||||
return regInfo;
|
||||
}
|
||||
// Fallback to WMI
|
||||
final sysInfo = await win32.getSystemInfo();
|
||||
return sysInfo.gpuInfo;
|
||||
} catch (e) {
|
||||
dPrint("getGpuInfo error: $e");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> getDiskInfo() async {
|
||||
return (await Process.run(powershellPath, [
|
||||
"Get-PhysicalDisk | format-table BusType,FriendlyName,Size",
|
||||
])).stdout.toString().trim();
|
||||
try {
|
||||
final sysInfo = await win32.getSystemInfo();
|
||||
return sysInfo.diskInfo;
|
||||
} catch (e) {
|
||||
dPrint("getDiskInfo error: $e");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static Future<int> getDirLen(String path, {List<String>? skipPath}) async {
|
||||
@ -212,11 +202,12 @@ foreach ($adapter in $adapterMemory) {
|
||||
}
|
||||
|
||||
static Future<int> getNumberOfLogicalProcessors() async {
|
||||
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;
|
||||
try {
|
||||
return await win32.getNumberOfLogicalProcessors();
|
||||
} catch (e) {
|
||||
dPrint("getNumberOfLogicalProcessors error: $e");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String?> getCpuAffinity() async {
|
||||
@ -244,10 +235,11 @@ 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\"\"",
|
||||
]);
|
||||
try {
|
||||
await win32.openDirWithExplorer(path: path.toString(), isFile: isFile);
|
||||
} catch (e) {
|
||||
dPrint("openDir error: $e");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,9 +8,8 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||
part 'webview_api.freezed.dart';
|
||||
|
||||
// These functions are ignored because they are not marked as `pub`: `handle_command`, `load_app_icon`, `run_webview_loop`, `send_command`
|
||||
// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `UserEvent`, `WebViewCommand`, `WebViewInstance`
|
||||
// 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`, `clone`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`
|
||||
// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `WebViewCommand`
|
||||
// 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`, `clone`, `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt`
|
||||
|
||||
/// Create a new WebView window and return its ID
|
||||
String webviewCreate({required WebViewConfiguration config}) =>
|
||||
|
||||
@ -7,7 +7,7 @@ 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`: `get_process_path`
|
||||
// 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`, `fmt`
|
||||
// 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`, `clone`, `fmt`, `fmt`
|
||||
|
||||
Future<void> sendNotify({
|
||||
String? summary,
|
||||
@ -21,6 +21,35 @@ Future<void> sendNotify({
|
||||
appId: appId,
|
||||
);
|
||||
|
||||
/// Get system memory size in GB
|
||||
Future<BigInt> getSystemMemorySizeGb() =>
|
||||
RustLib.instance.api.crateApiWin32ApiGetSystemMemorySizeGb();
|
||||
|
||||
/// Get number of logical processors
|
||||
Future<int> getNumberOfLogicalProcessors() =>
|
||||
RustLib.instance.api.crateApiWin32ApiGetNumberOfLogicalProcessors();
|
||||
|
||||
/// Get all system information at once
|
||||
Future<SystemInfo> getSystemInfo() =>
|
||||
RustLib.instance.api.crateApiWin32ApiGetSystemInfo();
|
||||
|
||||
/// Get GPU info from registry (more accurate VRAM)
|
||||
Future<String> getGpuInfoFromRegistry() =>
|
||||
RustLib.instance.api.crateApiWin32ApiGetGpuInfoFromRegistry();
|
||||
|
||||
/// Resolve shortcut (.lnk) file to get target path
|
||||
Future<String> resolveShortcut({required String lnkPath}) =>
|
||||
RustLib.instance.api.crateApiWin32ApiResolveShortcut(lnkPath: lnkPath);
|
||||
|
||||
/// Open file explorer and select file/folder
|
||||
Future<void> openDirWithExplorer({
|
||||
required String path,
|
||||
required bool isFile,
|
||||
}) => RustLib.instance.api.crateApiWin32ApiOpenDirWithExplorer(
|
||||
path: path,
|
||||
isFile: isFile,
|
||||
);
|
||||
|
||||
Future<bool> setForegroundWindow({required String windowName}) => RustLib
|
||||
.instance
|
||||
.api
|
||||
@ -36,6 +65,55 @@ Future<List<ProcessInfo>> getProcessListByName({required String processName}) =>
|
||||
processName: processName,
|
||||
);
|
||||
|
||||
/// Kill processes by name
|
||||
Future<int> killProcessByName({required String processName}) => RustLib
|
||||
.instance
|
||||
.api
|
||||
.crateApiWin32ApiKillProcessByName(processName: processName);
|
||||
|
||||
/// Get disk physical sector size for performance
|
||||
Future<int> getDiskPhysicalSectorSize({required String driveLetter}) => RustLib
|
||||
.instance
|
||||
.api
|
||||
.crateApiWin32ApiGetDiskPhysicalSectorSize(driveLetter: driveLetter);
|
||||
|
||||
/// Create a desktop shortcut
|
||||
Future<void> createDesktopShortcut({
|
||||
required String targetPath,
|
||||
required String shortcutName,
|
||||
}) => RustLib.instance.api.crateApiWin32ApiCreateDesktopShortcut(
|
||||
targetPath: targetPath,
|
||||
shortcutName: shortcutName,
|
||||
);
|
||||
|
||||
/// Run a program with admin privileges (UAC)
|
||||
Future<void> runAsAdmin({required String program, required String args}) =>
|
||||
RustLib.instance.api.crateApiWin32ApiRunAsAdmin(
|
||||
program: program,
|
||||
args: args,
|
||||
);
|
||||
|
||||
/// Start a program (without waiting)
|
||||
Future<void> startProcess({
|
||||
required String program,
|
||||
required List<String> args,
|
||||
}) => RustLib.instance.api.crateApiWin32ApiStartProcess(
|
||||
program: program,
|
||||
args: args,
|
||||
);
|
||||
|
||||
/// Check if NVME patch is applied
|
||||
Future<bool> checkNvmePatchStatus() =>
|
||||
RustLib.instance.api.crateApiWin32ApiCheckNvmePatchStatus();
|
||||
|
||||
/// Add NVME patch to registry
|
||||
Future<void> addNvmePatch() =>
|
||||
RustLib.instance.api.crateApiWin32ApiAddNvmePatch();
|
||||
|
||||
/// Remove NVME patch from registry
|
||||
Future<void> removeNvmePatch() =>
|
||||
RustLib.instance.api.crateApiWin32ApiRemoveNvmePatch();
|
||||
|
||||
class ProcessInfo {
|
||||
final int pid;
|
||||
final String name;
|
||||
@ -59,3 +137,32 @@ class ProcessInfo {
|
||||
name == other.name &&
|
||||
path == other.path;
|
||||
}
|
||||
|
||||
/// System information struct
|
||||
class SystemInfo {
|
||||
final String osName;
|
||||
final String cpuName;
|
||||
final String gpuInfo;
|
||||
final String diskInfo;
|
||||
|
||||
const SystemInfo({
|
||||
required this.osName,
|
||||
required this.cpuName,
|
||||
required this.gpuInfo,
|
||||
required this.diskInfo,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
osName.hashCode ^ cpuName.hashCode ^ gpuInfo.hashCode ^ diskInfo.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is SystemInfo &&
|
||||
runtimeType == other.runtimeType &&
|
||||
osName == other.osName &&
|
||||
cpuName == other.cpuName &&
|
||||
gpuInfo == other.gpuInfo &&
|
||||
diskInfo == other.diskInfo;
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
||||
String get codegenVersion => '2.11.1';
|
||||
|
||||
@override
|
||||
int get rustContentHash => -1082688871;
|
||||
int get rustContentHash => 1161621087;
|
||||
|
||||
static const kDefaultExternalLibraryLoaderConfig =
|
||||
ExternalLibraryLoaderConfig(
|
||||
@ -82,8 +82,17 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
|
||||
}
|
||||
|
||||
abstract class RustLibApi extends BaseApi {
|
||||
Future<void> crateApiWin32ApiAddNvmePatch();
|
||||
|
||||
Future<bool> crateApiWin32ApiCheckNvmePatchStatus();
|
||||
|
||||
Future<void> crateApiOrtApiClearAllModels();
|
||||
|
||||
Future<void> crateApiWin32ApiCreateDesktopShortcut({
|
||||
required String targetPath,
|
||||
required String shortcutName,
|
||||
});
|
||||
|
||||
Future<List<String>> crateApiHttpApiDnsLookupIps({required String host});
|
||||
|
||||
Future<List<String>> crateApiHttpApiDnsLookupTxt({required String host});
|
||||
@ -97,11 +106,19 @@ abstract class RustLibApi extends BaseApi {
|
||||
bool? withCustomDns,
|
||||
});
|
||||
|
||||
Future<int> crateApiWin32ApiGetDiskPhysicalSectorSize({
|
||||
required String driveLetter,
|
||||
});
|
||||
|
||||
Future<String?> crateApiHttpApiGetFasterUrl({
|
||||
required List<String> urls,
|
||||
String? pathSuffix,
|
||||
});
|
||||
|
||||
Future<String> crateApiWin32ApiGetGpuInfoFromRegistry();
|
||||
|
||||
Future<int> crateApiWin32ApiGetNumberOfLogicalProcessors();
|
||||
|
||||
Future<List<ProcessInfo>> crateApiWin32ApiGetProcessListByName({
|
||||
required String processName,
|
||||
});
|
||||
@ -114,6 +131,12 @@ abstract class RustLibApi extends BaseApi {
|
||||
required String asarPath,
|
||||
});
|
||||
|
||||
Future<SystemInfo> crateApiWin32ApiGetSystemInfo();
|
||||
|
||||
Future<BigInt> crateApiWin32ApiGetSystemMemorySizeGb();
|
||||
|
||||
Future<int> crateApiWin32ApiKillProcessByName({required String processName});
|
||||
|
||||
Future<void> crateApiOrtApiLoadTranslationModel({
|
||||
required String modelPath,
|
||||
required String modelKey,
|
||||
@ -121,6 +144,11 @@ abstract class RustLibApi extends BaseApi {
|
||||
required bool useXnnpack,
|
||||
});
|
||||
|
||||
Future<void> crateApiWin32ApiOpenDirWithExplorer({
|
||||
required String path,
|
||||
required bool isFile,
|
||||
});
|
||||
|
||||
Future<void> crateApiUnp4KApiP4KClose();
|
||||
|
||||
Future<void> crateApiUnp4KApiP4KExtractToDisk({
|
||||
@ -138,11 +166,20 @@ abstract class RustLibApi extends BaseApi {
|
||||
|
||||
Future<void> crateApiUnp4KApiP4KOpen({required String p4KPath});
|
||||
|
||||
Future<void> crateApiWin32ApiRemoveNvmePatch();
|
||||
|
||||
Future<String> crateApiWin32ApiResolveShortcut({required String lnkPath});
|
||||
|
||||
Future<void> crateApiAsarApiRsiLauncherAsarDataWriteMainJs({
|
||||
required RsiLauncherAsarData that,
|
||||
required List<int> content,
|
||||
});
|
||||
|
||||
Future<void> crateApiWin32ApiRunAsAdmin({
|
||||
required String program,
|
||||
required String args,
|
||||
});
|
||||
|
||||
Future<void> crateApiWin32ApiSendNotify({
|
||||
String? summary,
|
||||
String? body,
|
||||
@ -164,6 +201,11 @@ abstract class RustLibApi extends BaseApi {
|
||||
required String workingDirectory,
|
||||
});
|
||||
|
||||
Future<void> crateApiWin32ApiStartProcess({
|
||||
required String program,
|
||||
required List<String> args,
|
||||
});
|
||||
|
||||
Future<String> crateApiOrtApiTranslateText({
|
||||
required String modelKey,
|
||||
required String text,
|
||||
@ -246,6 +288,50 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
required super.portManager,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<void> crateApiWin32ApiAddNvmePatch() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__win32_api__add_nvme_patch(port_);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiAddNvmePatchConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiAddNvmePatchConstMeta =>
|
||||
const TaskConstMeta(debugName: "add_nvme_patch", argNames: []);
|
||||
|
||||
@override
|
||||
Future<bool> crateApiWin32ApiCheckNvmePatchStatus() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__win32_api__check_nvme_patch_status(
|
||||
port_,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_bool,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiCheckNvmePatchStatusConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiCheckNvmePatchStatusConstMeta =>
|
||||
const TaskConstMeta(debugName: "check_nvme_patch_status", argNames: []);
|
||||
|
||||
@override
|
||||
Future<void> crateApiOrtApiClearAllModels() {
|
||||
return handler.executeNormal(
|
||||
@ -267,6 +353,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
TaskConstMeta get kCrateApiOrtApiClearAllModelsConstMeta =>
|
||||
const TaskConstMeta(debugName: "clear_all_models", argNames: []);
|
||||
|
||||
@override
|
||||
Future<void> crateApiWin32ApiCreateDesktopShortcut({
|
||||
required String targetPath,
|
||||
required String shortcutName,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(targetPath);
|
||||
var arg1 = cst_encode_String(shortcutName);
|
||||
return wire.wire__crate__api__win32_api__create_desktop_shortcut(
|
||||
port_,
|
||||
arg0,
|
||||
arg1,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiCreateDesktopShortcutConstMeta,
|
||||
argValues: [targetPath, shortcutName],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiCreateDesktopShortcutConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "create_desktop_shortcut",
|
||||
argNames: ["targetPath", "shortcutName"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<List<String>> crateApiHttpApiDnsLookupIps({required String host}) {
|
||||
return handler.executeNormal(
|
||||
@ -369,6 +488,37 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<int> crateApiWin32ApiGetDiskPhysicalSectorSize({
|
||||
required String driveLetter,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(driveLetter);
|
||||
return wire
|
||||
.wire__crate__api__win32_api__get_disk_physical_sector_size(
|
||||
port_,
|
||||
arg0,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_u_32,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiGetDiskPhysicalSectorSizeConstMeta,
|
||||
argValues: [driveLetter],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiGetDiskPhysicalSectorSizeConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "get_disk_physical_sector_size",
|
||||
argNames: ["driveLetter"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<String?> crateApiHttpApiGetFasterUrl({
|
||||
required List<String> urls,
|
||||
@ -402,6 +552,59 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
argNames: ["urls", "pathSuffix"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<String> crateApiWin32ApiGetGpuInfoFromRegistry() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__win32_api__get_gpu_info_from_registry(
|
||||
port_,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_String,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiGetGpuInfoFromRegistryConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiGetGpuInfoFromRegistryConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "get_gpu_info_from_registry",
|
||||
argNames: [],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<int> crateApiWin32ApiGetNumberOfLogicalProcessors() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire
|
||||
.wire__crate__api__win32_api__get_number_of_logical_processors(
|
||||
port_,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_u_32,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiGetNumberOfLogicalProcessorsConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiGetNumberOfLogicalProcessorsConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "get_number_of_logical_processors",
|
||||
argNames: [],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<List<ProcessInfo>> crateApiWin32ApiGetProcessListByName({
|
||||
required String processName,
|
||||
@ -492,6 +695,78 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
argNames: ["asarPath"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<SystemInfo> crateApiWin32ApiGetSystemInfo() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__win32_api__get_system_info(port_);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_system_info,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiGetSystemInfoConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiGetSystemInfoConstMeta =>
|
||||
const TaskConstMeta(debugName: "get_system_info", argNames: []);
|
||||
|
||||
@override
|
||||
Future<BigInt> crateApiWin32ApiGetSystemMemorySizeGb() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__win32_api__get_system_memory_size_gb(
|
||||
port_,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_u_64,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiGetSystemMemorySizeGbConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiGetSystemMemorySizeGbConstMeta =>
|
||||
const TaskConstMeta(debugName: "get_system_memory_size_gb", argNames: []);
|
||||
|
||||
@override
|
||||
Future<int> crateApiWin32ApiKillProcessByName({required String processName}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(processName);
|
||||
return wire.wire__crate__api__win32_api__kill_process_by_name(
|
||||
port_,
|
||||
arg0,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_u_32,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiKillProcessByNameConstMeta,
|
||||
argValues: [processName],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiKillProcessByNameConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "kill_process_by_name",
|
||||
argNames: ["processName"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> crateApiOrtApiLoadTranslationModel({
|
||||
required String modelPath,
|
||||
@ -531,6 +806,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
argNames: ["modelPath", "modelKey", "quantizationSuffix", "useXnnpack"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> crateApiWin32ApiOpenDirWithExplorer({
|
||||
required String path,
|
||||
required bool isFile,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(path);
|
||||
var arg1 = cst_encode_bool(isFile);
|
||||
return wire.wire__crate__api__win32_api__open_dir_with_explorer(
|
||||
port_,
|
||||
arg0,
|
||||
arg1,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiOpenDirWithExplorerConstMeta,
|
||||
argValues: [path, isFile],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiOpenDirWithExplorerConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "open_dir_with_explorer",
|
||||
argNames: ["path", "isFile"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> crateApiUnp4KApiP4KClose() {
|
||||
return handler.executeNormal(
|
||||
@ -679,6 +987,52 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
TaskConstMeta get kCrateApiUnp4KApiP4KOpenConstMeta =>
|
||||
const TaskConstMeta(debugName: "p4k_open", argNames: ["p4KPath"]);
|
||||
|
||||
@override
|
||||
Future<void> crateApiWin32ApiRemoveNvmePatch() {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
return wire.wire__crate__api__win32_api__remove_nvme_patch(port_);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiRemoveNvmePatchConstMeta,
|
||||
argValues: [],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiRemoveNvmePatchConstMeta =>
|
||||
const TaskConstMeta(debugName: "remove_nvme_patch", argNames: []);
|
||||
|
||||
@override
|
||||
Future<String> crateApiWin32ApiResolveShortcut({required String lnkPath}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(lnkPath);
|
||||
return wire.wire__crate__api__win32_api__resolve_shortcut(
|
||||
port_,
|
||||
arg0,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_String,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiResolveShortcutConstMeta,
|
||||
argValues: [lnkPath],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiResolveShortcutConstMeta =>
|
||||
const TaskConstMeta(debugName: "resolve_shortcut", argNames: ["lnkPath"]);
|
||||
|
||||
@override
|
||||
Future<void> crateApiAsarApiRsiLauncherAsarDataWriteMainJs({
|
||||
required RsiLauncherAsarData that,
|
||||
@ -713,6 +1067,38 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
argNames: ["that", "content"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> crateApiWin32ApiRunAsAdmin({
|
||||
required String program,
|
||||
required String args,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(program);
|
||||
var arg1 = cst_encode_String(args);
|
||||
return wire.wire__crate__api__win32_api__run_as_admin(
|
||||
port_,
|
||||
arg0,
|
||||
arg1,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiRunAsAdminConstMeta,
|
||||
argValues: [program, args],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiRunAsAdminConstMeta => const TaskConstMeta(
|
||||
debugName: "run_as_admin",
|
||||
argNames: ["program", "args"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> crateApiWin32ApiSendNotify({
|
||||
String? summary,
|
||||
@ -854,6 +1240,39 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
argNames: ["executable", "arguments", "workingDirectory", "streamSink"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<void> crateApiWin32ApiStartProcess({
|
||||
required String program,
|
||||
required List<String> args,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(program);
|
||||
var arg1 = cst_encode_list_String(args);
|
||||
return wire.wire__crate__api__win32_api__start_process(
|
||||
port_,
|
||||
arg0,
|
||||
arg1,
|
||||
);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_unit,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiWin32ApiStartProcessConstMeta,
|
||||
argValues: [program, args],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiWin32ApiStartProcessConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "start_process",
|
||||
argNames: ["program", "args"],
|
||||
);
|
||||
|
||||
@override
|
||||
Future<String> crateApiOrtApiTranslateText({
|
||||
required String modelKey,
|
||||
@ -1667,6 +2086,20 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
SystemInfo dco_decode_system_info(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
final arr = raw as List<dynamic>;
|
||||
if (arr.length != 4)
|
||||
throw Exception('unexpected arr length: expect 4 but see ${arr.length}');
|
||||
return SystemInfo(
|
||||
osName: dco_decode_String(arr[0]),
|
||||
cpuName: dco_decode_String(arr[1]),
|
||||
gpuInfo: dco_decode_String(arr[2]),
|
||||
diskInfo: dco_decode_String(arr[3]),
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
int dco_decode_u_16(dynamic raw) {
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
@ -2081,6 +2514,21 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
SystemInfo sse_decode_system_info(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var var_osName = sse_decode_String(deserializer);
|
||||
var var_cpuName = sse_decode_String(deserializer);
|
||||
var var_gpuInfo = sse_decode_String(deserializer);
|
||||
var var_diskInfo = sse_decode_String(deserializer);
|
||||
return SystemInfo(
|
||||
osName: var_osName,
|
||||
cpuName: var_cpuName,
|
||||
gpuInfo: var_gpuInfo,
|
||||
diskInfo: var_diskInfo,
|
||||
);
|
||||
}
|
||||
|
||||
@protected
|
||||
int sse_decode_u_16(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
@ -2556,6 +3004,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
sse_encode_opt_list_prim_u_8_strict(self.data, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_system_info(SystemInfo self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_String(self.osName, serializer);
|
||||
sse_encode_String(self.cpuName, serializer);
|
||||
sse_encode_String(self.gpuInfo, serializer);
|
||||
sse_encode_String(self.diskInfo, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
void sse_encode_u_16(int self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
|
||||
@ -126,6 +126,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
RustHttpResponse dco_decode_rust_http_response(dynamic raw);
|
||||
|
||||
@protected
|
||||
SystemInfo dco_decode_system_info(dynamic raw);
|
||||
|
||||
@protected
|
||||
int dco_decode_u_16(dynamic raw);
|
||||
|
||||
@ -274,6 +277,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
@protected
|
||||
RustHttpResponse sse_decode_rust_http_response(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
SystemInfo sse_decode_system_info(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
int sse_decode_u_16(SseDeserializer deserializer);
|
||||
|
||||
@ -588,6 +594,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
wireObj.data = cst_encode_opt_list_prim_u_8_strict(apiObj.data);
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_system_info(
|
||||
SystemInfo apiObj,
|
||||
wire_cst_system_info wireObj,
|
||||
) {
|
||||
wireObj.os_name = cst_encode_String(apiObj.osName);
|
||||
wireObj.cpu_name = cst_encode_String(apiObj.cpuName);
|
||||
wireObj.gpu_info = cst_encode_String(apiObj.gpuInfo);
|
||||
wireObj.disk_info = cst_encode_String(apiObj.diskInfo);
|
||||
}
|
||||
|
||||
@protected
|
||||
void cst_api_fill_to_wire_web_view_configuration(
|
||||
WebViewConfiguration apiObj,
|
||||
@ -829,6 +846,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_system_info(SystemInfo self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_u_16(int self, SseSerializer serializer);
|
||||
|
||||
@ -900,6 +920,30 @@ class RustLibWire implements BaseWire {
|
||||
late final _store_dart_post_cobject = _store_dart_post_cobjectPtr
|
||||
.asFunction<void Function(DartPostCObjectFnType)>();
|
||||
|
||||
void wire__crate__api__win32_api__add_nvme_patch(int port_) {
|
||||
return _wire__crate__api__win32_api__add_nvme_patch(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__add_nvme_patchPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__add_nvme_patch',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__add_nvme_patch =
|
||||
_wire__crate__api__win32_api__add_nvme_patchPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__win32_api__check_nvme_patch_status(int port_) {
|
||||
return _wire__crate__api__win32_api__check_nvme_patch_status(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__check_nvme_patch_statusPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__check_nvme_patch_status',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__check_nvme_patch_status =
|
||||
_wire__crate__api__win32_api__check_nvme_patch_statusPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__ort_api__clear_all_models(int port_) {
|
||||
return _wire__crate__api__ort_api__clear_all_models(port_);
|
||||
}
|
||||
@ -912,6 +956,40 @@ class RustLibWire implements BaseWire {
|
||||
_wire__crate__api__ort_api__clear_all_modelsPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__win32_api__create_desktop_shortcut(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> target_path,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> shortcut_name,
|
||||
) {
|
||||
return _wire__crate__api__win32_api__create_desktop_shortcut(
|
||||
port_,
|
||||
target_path,
|
||||
shortcut_name,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__create_desktop_shortcutPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__create_desktop_shortcut',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__create_desktop_shortcut =
|
||||
_wire__crate__api__win32_api__create_desktop_shortcutPtr
|
||||
.asFunction<
|
||||
void Function(
|
||||
int,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__http_api__dns_lookup_ips(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> host,
|
||||
@ -1004,6 +1082,33 @@ class RustLibWire implements BaseWire {
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__win32_api__get_disk_physical_sector_size(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> drive_letter,
|
||||
) {
|
||||
return _wire__crate__api__win32_api__get_disk_physical_sector_size(
|
||||
port_,
|
||||
drive_letter,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__get_disk_physical_sector_sizePtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_disk_physical_sector_size',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__get_disk_physical_sector_size =
|
||||
_wire__crate__api__win32_api__get_disk_physical_sector_sizePtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__http_api__get_faster_url(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_String> urls,
|
||||
@ -1036,6 +1141,34 @@ class RustLibWire implements BaseWire {
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__win32_api__get_gpu_info_from_registry(int port_) {
|
||||
return _wire__crate__api__win32_api__get_gpu_info_from_registry(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__get_gpu_info_from_registryPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_gpu_info_from_registry',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__get_gpu_info_from_registry =
|
||||
_wire__crate__api__win32_api__get_gpu_info_from_registryPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__win32_api__get_number_of_logical_processors(
|
||||
int port_,
|
||||
) {
|
||||
return _wire__crate__api__win32_api__get_number_of_logical_processors(
|
||||
port_,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__get_number_of_logical_processorsPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_number_of_logical_processors',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__get_number_of_logical_processors =
|
||||
_wire__crate__api__win32_api__get_number_of_logical_processorsPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__win32_api__get_process_list_by_name(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> process_name,
|
||||
@ -1117,6 +1250,57 @@ class RustLibWire implements BaseWire {
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__win32_api__get_system_info(int port_) {
|
||||
return _wire__crate__api__win32_api__get_system_info(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__get_system_infoPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_system_info',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__get_system_info =
|
||||
_wire__crate__api__win32_api__get_system_infoPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__win32_api__get_system_memory_size_gb(int port_) {
|
||||
return _wire__crate__api__win32_api__get_system_memory_size_gb(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__get_system_memory_size_gbPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_system_memory_size_gb',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__get_system_memory_size_gb =
|
||||
_wire__crate__api__win32_api__get_system_memory_size_gbPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__win32_api__kill_process_by_name(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> process_name,
|
||||
) {
|
||||
return _wire__crate__api__win32_api__kill_process_by_name(
|
||||
port_,
|
||||
process_name,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__kill_process_by_namePtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__kill_process_by_name',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__kill_process_by_name =
|
||||
_wire__crate__api__win32_api__kill_process_by_namePtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__ort_api__load_translation_model(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> model_path,
|
||||
@ -1159,6 +1343,36 @@ class RustLibWire implements BaseWire {
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__win32_api__open_dir_with_explorer(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> path,
|
||||
bool is_file,
|
||||
) {
|
||||
return _wire__crate__api__win32_api__open_dir_with_explorer(
|
||||
port_,
|
||||
path,
|
||||
is_file,
|
||||
);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__open_dir_with_explorerPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Bool,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__open_dir_with_explorer',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__open_dir_with_explorer =
|
||||
_wire__crate__api__win32_api__open_dir_with_explorerPtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>, bool)
|
||||
>();
|
||||
|
||||
void wire__crate__api__unp4k_api__p4k_close(int port_) {
|
||||
return _wire__crate__api__unp4k_api__p4k_close(port_);
|
||||
}
|
||||
@ -1278,6 +1492,42 @@ class RustLibWire implements BaseWire {
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__win32_api__remove_nvme_patch(int port_) {
|
||||
return _wire__crate__api__win32_api__remove_nvme_patch(port_);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__remove_nvme_patchPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int64)>>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__remove_nvme_patch',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__remove_nvme_patch =
|
||||
_wire__crate__api__win32_api__remove_nvme_patchPtr
|
||||
.asFunction<void Function(int)>();
|
||||
|
||||
void wire__crate__api__win32_api__resolve_shortcut(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> lnk_path,
|
||||
) {
|
||||
return _wire__crate__api__win32_api__resolve_shortcut(port_, lnk_path);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__resolve_shortcutPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>(
|
||||
'frbgen_starcitizen_doctor_wire__crate__api__win32_api__resolve_shortcut',
|
||||
);
|
||||
late final _wire__crate__api__win32_api__resolve_shortcut =
|
||||
_wire__crate__api__win32_api__resolve_shortcutPtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__asar_api__rsi_launcher_asar_data_write_main_js(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_rsi_launcher_asar_data> that,
|
||||
@ -1312,6 +1562,34 @@ class RustLibWire implements BaseWire {
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__win32_api__run_as_admin(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> program,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> args,
|
||||
) {
|
||||
return _wire__crate__api__win32_api__run_as_admin(port_, program, args);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__run_as_adminPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>
|
||||
>('frbgen_starcitizen_doctor_wire__crate__api__win32_api__run_as_admin');
|
||||
late final _wire__crate__api__win32_api__run_as_admin =
|
||||
_wire__crate__api__win32_api__run_as_adminPtr
|
||||
.asFunction<
|
||||
void Function(
|
||||
int,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__win32_api__send_notify(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> summary,
|
||||
@ -1443,6 +1721,34 @@ class RustLibWire implements BaseWire {
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__win32_api__start_process(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> program,
|
||||
ffi.Pointer<wire_cst_list_String> args,
|
||||
) {
|
||||
return _wire__crate__api__win32_api__start_process(port_, program, args);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__win32_api__start_processPtr =
|
||||
_lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_String>,
|
||||
)
|
||||
>
|
||||
>('frbgen_starcitizen_doctor_wire__crate__api__win32_api__start_process');
|
||||
late final _wire__crate__api__win32_api__start_process =
|
||||
_wire__crate__api__win32_api__start_processPtr
|
||||
.asFunction<
|
||||
void Function(
|
||||
int,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.Pointer<wire_cst_list_String>,
|
||||
)
|
||||
>();
|
||||
|
||||
void wire__crate__api__ort_api__translate_text(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> model_key,
|
||||
@ -2321,6 +2627,16 @@ final class wire_cst_rust_http_response extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> data;
|
||||
}
|
||||
|
||||
final class wire_cst_system_info extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> os_name;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> cpu_name;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> gpu_info;
|
||||
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> disk_info;
|
||||
}
|
||||
|
||||
final class wire_cst_web_view_navigation_state extends ffi.Struct {
|
||||
external ffi.Pointer<wire_cst_list_prim_u_8_strict> url;
|
||||
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/webview_api.dart' as rust_webview;
|
||||
import 'package:starcitizen_doctor/common/rust/api/webview_api.dart'
|
||||
as rust_webview;
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
|
||||
typedef OnWebMessageCallback = void Function(String message);
|
||||
@ -76,7 +77,9 @@ class RustWebViewController {
|
||||
Future<void> _loadScripts() async {
|
||||
try {
|
||||
_localizationScript = await rootBundle.loadString('assets/web_script.js');
|
||||
_requestInterceptorScript = await rootBundle.loadString('assets/request_interceptor.js');
|
||||
_requestInterceptorScript = await rootBundle.loadString(
|
||||
'assets/request_interceptor.js',
|
||||
);
|
||||
} catch (e) {
|
||||
dPrint("Failed to load scripts: $e");
|
||||
}
|
||||
@ -286,12 +289,16 @@ class RustWebViewController {
|
||||
}
|
||||
|
||||
/// 添加导航完成回调(用于在页面加载完成后注入脚本)
|
||||
void addOnNavigationCompletedCallback(OnNavigationCompletedCallback callback) {
|
||||
void addOnNavigationCompletedCallback(
|
||||
OnNavigationCompletedCallback callback,
|
||||
) {
|
||||
_navigationCompletedCallbacks.add(callback);
|
||||
}
|
||||
|
||||
/// 移除导航完成回调
|
||||
void removeOnNavigationCompletedCallback(OnNavigationCompletedCallback callback) {
|
||||
void removeOnNavigationCompletedCallback(
|
||||
OnNavigationCompletedCallback callback,
|
||||
) {
|
||||
_navigationCompletedCallbacks.remove(callback);
|
||||
}
|
||||
|
||||
@ -320,7 +327,9 @@ class RustWebViewController {
|
||||
/// 更新翻译词典
|
||||
void updateReplaceWords(List<Map<String, String>> words, bool enableCapture) {
|
||||
final jsonWords = json.encode(words);
|
||||
executeScript("WebLocalizationUpdateReplaceWords($jsonWords, $enableCapture)");
|
||||
executeScript(
|
||||
"WebLocalizationUpdateReplaceWords($jsonWords, $enableCapture)",
|
||||
);
|
||||
}
|
||||
|
||||
/// 执行 RSI 登录脚本
|
||||
|
||||
@ -6,6 +6,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/log_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/system_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/win32_api.dart' as win32;
|
||||
import 'package:starcitizen_doctor/common/utils/base_utils.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
import 'package:starcitizen_doctor/ui/home/home_ui_model.dart';
|
||||
@ -35,11 +36,11 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
}
|
||||
|
||||
Future<void> doFix(
|
||||
// ignore: avoid_build_context_in_providers
|
||||
BuildContext context,
|
||||
MapEntry<String, String> item) async {
|
||||
final checkResult =
|
||||
List<MapEntry<String, String>>.from(state.checkResult ?? []);
|
||||
// ignore: avoid_build_context_in_providers
|
||||
BuildContext context,
|
||||
MapEntry<String, String> item,
|
||||
) async {
|
||||
final checkResult = List<MapEntry<String, String>>.from(state.checkResult ?? []);
|
||||
state = state.copyWith(isFixing: true, isFixingString: "");
|
||||
switch (item.key) {
|
||||
case "unSupport_system":
|
||||
@ -49,13 +50,11 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
try {
|
||||
await Directory(item.value).create(recursive: true);
|
||||
if (!context.mounted) break;
|
||||
showToast(
|
||||
context, S.current.doctor_action_result_create_folder_success);
|
||||
showToast(context, S.current.doctor_action_result_create_folder_success);
|
||||
checkResult.remove(item);
|
||||
state = state.copyWith(checkResult: checkResult);
|
||||
} catch (e) {
|
||||
showToast(context,
|
||||
S.current.doctor_action_result_create_folder_fail(item.value, e));
|
||||
showToast(context, S.current.doctor_action_result_create_folder_fail(item.value, e));
|
||||
}
|
||||
break;
|
||||
case "nvme_PhysicalBytes":
|
||||
@ -71,8 +70,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
}
|
||||
break;
|
||||
case "eac_file_miss":
|
||||
showToast(context,
|
||||
S.current.doctor_info_result_verify_files_with_rsi_launcher);
|
||||
showToast(context, S.current.doctor_info_result_verify_files_with_rsi_launcher);
|
||||
break;
|
||||
case "eac_not_install":
|
||||
final eacJsonPath = "${item.value}\\Settings.json";
|
||||
@ -80,19 +78,16 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
final Map eacJson = json.decode(utf8.decode(eacJsonData));
|
||||
final eacID = eacJson["productid"];
|
||||
try {
|
||||
var result = await Process.run(
|
||||
"${item.value}\\EasyAntiCheat_EOS_Setup.exe", ["install", eacID]);
|
||||
var result = await Process.run("${item.value}\\EasyAntiCheat_EOS_Setup.exe", ["install", eacID]);
|
||||
dPrint("${item.value}\\EasyAntiCheat_EOS_Setup.exe install $eacID");
|
||||
if (result.stderr == "") {
|
||||
if (!context.mounted) break;
|
||||
showToast(
|
||||
context, S.current.doctor_action_result_game_start_success);
|
||||
showToast(context, S.current.doctor_action_result_game_start_success);
|
||||
checkResult.remove(item);
|
||||
state = state.copyWith(checkResult: checkResult);
|
||||
} else {
|
||||
if (!context.mounted) break;
|
||||
showToast(context,
|
||||
S.current.doctor_action_result_fix_fail(result.stderr));
|
||||
showToast(context, S.current.doctor_action_result_fix_fail(result.stderr));
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) break;
|
||||
@ -102,8 +97,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
case "cn_user_name":
|
||||
showToast(context, S.current.doctor_action_result_redirect_warning);
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
launchUrlString(
|
||||
"https://jingyan.baidu.com/article/59703552a318a08fc0074021.html");
|
||||
launchUrlString("https://jingyan.baidu.com/article/59703552a318a08fc0074021.html");
|
||||
break;
|
||||
default:
|
||||
showToast(context, S.current.doctor_action_result_issue_not_supported);
|
||||
@ -115,8 +109,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
// ignore: avoid_build_context_in_providers
|
||||
Future<void> doCheck(BuildContext context) async {
|
||||
if (state.isChecking) return;
|
||||
state = state.copyWith(
|
||||
isChecking: true, lastScreenInfo: S.current.doctor_action_analyzing);
|
||||
state = state.copyWith(isChecking: true, lastScreenInfo: S.current.doctor_action_analyzing);
|
||||
dPrint("-------- start docker check -----");
|
||||
if (!context.mounted) return;
|
||||
await _statCheck(context);
|
||||
@ -144,11 +137,8 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
final lastScreenInfo = S.current.doctor_action_result_analysis_no_issue;
|
||||
state = state.copyWith(checkResult: null, lastScreenInfo: lastScreenInfo);
|
||||
} else {
|
||||
final lastScreenInfo = S.current
|
||||
.doctor_action_result_analysis_issues_found(
|
||||
checkResult.length.toString());
|
||||
state = state.copyWith(
|
||||
checkResult: checkResult, lastScreenInfo: lastScreenInfo);
|
||||
final lastScreenInfo = S.current.doctor_action_result_analysis_issues_found(checkResult.length.toString());
|
||||
state = state.copyWith(checkResult: checkResult, lastScreenInfo: lastScreenInfo);
|
||||
}
|
||||
|
||||
if (scInstalledPath == "not_install" && (checkResult.isEmpty)) {
|
||||
@ -158,8 +148,11 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
}
|
||||
|
||||
// ignore: avoid_build_context_in_providers
|
||||
Future _checkGameRunningLog(BuildContext context, String scInstalledPath,
|
||||
List<MapEntry<String, String>> checkResult) async {
|
||||
Future _checkGameRunningLog(
|
||||
BuildContext context,
|
||||
String scInstalledPath,
|
||||
List<MapEntry<String, String>> checkResult,
|
||||
) async {
|
||||
if (scInstalledPath == "not_install") return;
|
||||
final lastScreenInfo = S.current.doctor_action_tip_checking_game_log;
|
||||
state = state.copyWith(lastScreenInfo: lastScreenInfo);
|
||||
@ -168,28 +161,27 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
final info = SCLoggerHelper.getGameRunningLogInfo(logs);
|
||||
if (info != null) {
|
||||
if (info.key != "_") {
|
||||
checkResult.add(MapEntry(
|
||||
S.current.doctor_action_info_game_abnormal_exit(info.key),
|
||||
info.value));
|
||||
checkResult.add(MapEntry(S.current.doctor_action_info_game_abnormal_exit(info.key), info.value));
|
||||
} else {
|
||||
checkResult.add(MapEntry(
|
||||
checkResult.add(
|
||||
MapEntry(
|
||||
S.current.doctor_action_info_game_abnormal_exit_unknown,
|
||||
S.current.doctor_action_info_info_feedback(info.value)));
|
||||
S.current.doctor_action_info_info_feedback(info.value),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: avoid_build_context_in_providers
|
||||
Future _checkEAC(BuildContext context, String scInstalledPath,
|
||||
List<MapEntry<String, String>> checkResult) async {
|
||||
Future _checkEAC(BuildContext context, String scInstalledPath, List<MapEntry<String, String>> checkResult) async {
|
||||
if (scInstalledPath == "not_install") return;
|
||||
final lastScreenInfo = S.current.doctor_action_info_checking_eac;
|
||||
state = state.copyWith(lastScreenInfo: lastScreenInfo);
|
||||
|
||||
final eacPath = "$scInstalledPath\\EasyAntiCheat";
|
||||
final eacJsonPath = "$eacPath\\Settings.json";
|
||||
if (!await Directory(eacPath).exists() ||
|
||||
!await File(eacJsonPath).exists()) {
|
||||
if (!await Directory(eacPath).exists() || !await File(eacJsonPath).exists()) {
|
||||
checkResult.add(const MapEntry("eac_file_miss", ""));
|
||||
return;
|
||||
}
|
||||
@ -212,17 +204,18 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
final _cnExp = RegExp(r"[^\x00-\xff]");
|
||||
|
||||
// ignore: avoid_build_context_in_providers
|
||||
Future _checkPreInstall(BuildContext context, String scInstalledPath,
|
||||
List<MapEntry<String, String>> checkResult) async {
|
||||
Future _checkPreInstall(
|
||||
BuildContext context,
|
||||
String scInstalledPath,
|
||||
List<MapEntry<String, String>> checkResult,
|
||||
) async {
|
||||
final lastScreenInfo = S.current.doctor_action_info_checking_runtime;
|
||||
state = state.copyWith(lastScreenInfo: lastScreenInfo);
|
||||
|
||||
if (!(Platform.operatingSystemVersion.contains("Windows 10") ||
|
||||
Platform.operatingSystemVersion.contains("Windows 11"))) {
|
||||
checkResult
|
||||
.add(MapEntry("unSupport_system", Platform.operatingSystemVersion));
|
||||
final lastScreenInfo = S.current.doctor_action_result_info_unsupported_os(
|
||||
Platform.operatingSystemVersion);
|
||||
checkResult.add(MapEntry("unSupport_system", Platform.operatingSystemVersion));
|
||||
final lastScreenInfo = S.current.doctor_action_result_info_unsupported_os(Platform.operatingSystemVersion);
|
||||
state = state.copyWith(lastScreenInfo: lastScreenInfo);
|
||||
await showToast(context, lastScreenInfo);
|
||||
}
|
||||
@ -236,12 +229,10 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
if (ramSize < 16) {
|
||||
checkResult.add(MapEntry("low_ram", "$ramSize"));
|
||||
}
|
||||
state = state.copyWith(
|
||||
lastScreenInfo: S.current.doctor_action_info_checking_install_info);
|
||||
state = state.copyWith(lastScreenInfo: S.current.doctor_action_info_checking_install_info);
|
||||
// 检查安装分区
|
||||
try {
|
||||
final listData = await SCLoggerHelper.getGameInstallPath(
|
||||
await SCLoggerHelper.getLauncherLogList() ?? []);
|
||||
final listData = await SCLoggerHelper.getGameInstallPath(await SCLoggerHelper.getLauncherLogList() ?? []);
|
||||
final p = [];
|
||||
final checkedPath = [];
|
||||
for (var installPath in listData) {
|
||||
@ -262,19 +253,16 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
}
|
||||
}
|
||||
|
||||
// call check
|
||||
// call check using Rust API
|
||||
for (var element in p) {
|
||||
var result = await Process.run('powershell', [
|
||||
"(fsutil fsinfo sectorinfo $element: | Select-String 'PhysicalBytesPerSectorForPerformance').ToString().Split(':')[1].Trim()"
|
||||
]);
|
||||
dPrint(
|
||||
"fsutil info sector info: ->>> ${result.stdout.toString().trim()}");
|
||||
if (result.stderr == "") {
|
||||
final rs = result.stdout.toString().trim();
|
||||
final physicalBytesPerSectorForPerformance = (int.tryParse(rs) ?? 0);
|
||||
try {
|
||||
final physicalBytesPerSectorForPerformance = await win32.getDiskPhysicalSectorSize(driveLetter: element);
|
||||
dPrint("disk sector info for $element: -> $physicalBytesPerSectorForPerformance");
|
||||
if (physicalBytesPerSectorForPerformance > 4096) {
|
||||
checkResult.add(MapEntry("nvme_PhysicalBytes", element));
|
||||
}
|
||||
} catch (e) {
|
||||
dPrint("getDiskPhysicalSectorSize error: $e");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@ -42,7 +42,7 @@ final class HomeGameDoctorUIModelProvider
|
||||
}
|
||||
|
||||
String _$homeGameDoctorUIModelHash() =>
|
||||
r'7035b501860e9d8c3fdfb91370311760120af115';
|
||||
r'8226e88797ecc68920f684a1dc072a340bca783a';
|
||||
|
||||
abstract class _$HomeGameDoctorUIModel extends $Notifier<HomeGameDoctorState> {
|
||||
HomeGameDoctorState build();
|
||||
|
||||
@ -12,7 +12,6 @@ import 'package:starcitizen_doctor/api/news_api.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/conf.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/url_conf.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/log_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/system_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/io/rs_http.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/win32_api.dart' as win32;
|
||||
import 'package:starcitizen_doctor/common/utils/async.dart';
|
||||
@ -323,7 +322,7 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
|
||||
if (ConstConf.isMSE) {
|
||||
if (state.isCurGameRunning) {
|
||||
await Process.run(SystemHelper.powershellPath, ["ps \"StarCitizen\" | kill"]);
|
||||
await win32.killProcessByName(processName: "StarCitizen");
|
||||
return;
|
||||
}
|
||||
AnalyticsApi.touch("gameLaunch");
|
||||
|
||||
@ -41,7 +41,7 @@ final class HomeUIModelProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$homeUIModelHash() => r'cc795e27213d02993459dd711de4a897c8491575';
|
||||
String _$homeUIModelHash() => r'c3affcfc99a0cd7e3587cc58f02dbdc24c4f8ae7';
|
||||
|
||||
abstract class _$HomeUIModel extends $Notifier<HomeUIModelState> {
|
||||
HomeUIModelState build();
|
||||
|
||||
@ -9,6 +9,7 @@ import 'package:hive_ce/hive.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/conf.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/system_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/win32_api.dart' as win32;
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/provider.dart';
|
||||
import 'package:starcitizen_doctor/widgets/widgets.dart';
|
||||
@ -50,14 +51,15 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
|
||||
Future<void> setGameLaunchECore(BuildContext context) async {
|
||||
final userBox = await Hive.openBox("app_conf");
|
||||
final defaultInput =
|
||||
userBox.get("gameLaunch_eCore_count", defaultValue: "0");
|
||||
final defaultInput = userBox.get("gameLaunch_eCore_count", defaultValue: "0");
|
||||
if (!context.mounted) return;
|
||||
final input = await showInputDialogs(context,
|
||||
title: S.current.setting_action_info_enter_cpu_core_to_ignore,
|
||||
content: S.current.setting_action_info_cpu_core_tip,
|
||||
initialValue: defaultInput,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly]);
|
||||
final input = await showInputDialogs(
|
||||
context,
|
||||
title: S.current.setting_action_info_enter_cpu_core_to_ignore,
|
||||
content: S.current.setting_action_info_cpu_core_tip,
|
||||
initialValue: defaultInput,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
);
|
||||
if (input == null) return;
|
||||
userBox.put("gameLaunch_eCore_count", input);
|
||||
_initState();
|
||||
@ -65,8 +67,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
|
||||
Future _updateGameLaunchECore() async {
|
||||
final userBox = await Hive.openBox("app_conf");
|
||||
final inputGameLaunchECore =
|
||||
userBox.get("gameLaunch_eCore_count", defaultValue: "0");
|
||||
final inputGameLaunchECore = userBox.get("gameLaunch_eCore_count", defaultValue: "0");
|
||||
state = state.copyWith(inputGameLaunchECore: inputGameLaunchECore);
|
||||
}
|
||||
|
||||
@ -102,9 +103,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
if (r == null || r.files.firstOrNull?.path == null) return;
|
||||
final fileName = r.files.first.path!;
|
||||
dPrint(fileName);
|
||||
final fileNameRegExp = RegExp(
|
||||
r"^(.*\\StarCitizen\\.*\\)Bin64\\StarCitizen\.exe$",
|
||||
caseSensitive: false);
|
||||
final fileNameRegExp = RegExp(r"^(.*\\StarCitizen\\.*\\)Bin64\\StarCitizen\.exe$", caseSensitive: false);
|
||||
if (fileNameRegExp.hasMatch(fileName)) {
|
||||
RegExp pathRegex = RegExp(r"\\[^\\]+\\Bin64\\StarCitizen\.exe$");
|
||||
String extractedPath = fileName.replaceFirst(pathRegex, '');
|
||||
@ -127,8 +126,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
final confBox = await Hive.openBox("app_conf");
|
||||
final customLauncherPath = confBox.get("custom_launcher_path");
|
||||
final customGamePath = confBox.get("custom_game_path");
|
||||
state = state.copyWith(
|
||||
customLauncherPath: customLauncherPath, customGamePath: customGamePath);
|
||||
state = state.copyWith(customLauncherPath: customLauncherPath, customGamePath: customGamePath);
|
||||
}
|
||||
|
||||
Future<void> delName(String key) async {
|
||||
@ -138,24 +136,21 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
}
|
||||
|
||||
Future _loadLocationCacheSize() async {
|
||||
final len1 = await SystemHelper.getDirLen(
|
||||
"${appGlobalState.applicationSupportDir}/Localizations");
|
||||
final len2 = await SystemHelper.getDirLen(
|
||||
"${appGlobalState.applicationSupportDir}/launcher_enhance_data");
|
||||
final len1 = await SystemHelper.getDirLen("${appGlobalState.applicationSupportDir}/Localizations");
|
||||
final len2 = await SystemHelper.getDirLen("${appGlobalState.applicationSupportDir}/launcher_enhance_data");
|
||||
final locationCacheSize = len1 + len2;
|
||||
state = state.copyWith(locationCacheSize: locationCacheSize);
|
||||
}
|
||||
|
||||
Future<void> cleanLocationCache(BuildContext context) async {
|
||||
final ok = await showConfirmDialogs(
|
||||
context,
|
||||
S.current.setting_action_info_confirm_clear_cache,
|
||||
Text(S.current.setting_action_info_clear_cache_warning));
|
||||
context,
|
||||
S.current.setting_action_info_confirm_clear_cache,
|
||||
Text(S.current.setting_action_info_clear_cache_warning),
|
||||
);
|
||||
if (ok == true) {
|
||||
final dir1 =
|
||||
Directory("${appGlobalState.applicationSupportDir}/Localizations");
|
||||
final dir2 = Directory(
|
||||
"${appGlobalState.applicationSupportDir}/launcher_enhance_data");
|
||||
final dir1 = Directory("${appGlobalState.applicationSupportDir}/Localizations");
|
||||
final dir2 = Directory("${appGlobalState.applicationSupportDir}/launcher_enhance_data");
|
||||
if (!context.mounted) return;
|
||||
if (await dir1.exists()) {
|
||||
if (!context.mounted) return;
|
||||
@ -172,36 +167,27 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
|
||||
Future<void> addShortCut(BuildContext context) async {
|
||||
if (ConstConf.isMSE) {
|
||||
showToast(
|
||||
context, S.current.setting_action_info_microsoft_version_limitation);
|
||||
showToast(context, S.current.setting_action_info_microsoft_version_limitation);
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
Process.run("explorer.exe", ["shell:AppsFolder"]);
|
||||
return;
|
||||
}
|
||||
dPrint(Platform.resolvedExecutable);
|
||||
final shortCuntName = S.current.app_shortcut_name;
|
||||
final script = """
|
||||
\$targetPath = "${Platform.resolvedExecutable}";
|
||||
\$shortcutPath = [System.IO.Path]::Combine([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::DesktopDirectory), "$shortCuntName");
|
||||
\$shell = New-Object -ComObject WScript.Shell
|
||||
\$shortcut = \$shell.CreateShortcut(\$shortcutPath)
|
||||
if (\$shortcut -eq \$null) {
|
||||
Write-Host "Failed to create shortcut."
|
||||
} else {
|
||||
\$shortcut.TargetPath = \$targetPath
|
||||
\$shortcut.Save()
|
||||
Write-Host "Shortcut created successfully."
|
||||
final shortcutName = S.current.app_shortcut_name;
|
||||
try {
|
||||
await win32.createDesktopShortcut(targetPath: Platform.resolvedExecutable, shortcutName: shortcutName);
|
||||
if (!context.mounted) return;
|
||||
showToast(context, S.current.setting_action_info_shortcut_created);
|
||||
} catch (e) {
|
||||
dPrint("createDesktopShortcut error: $e");
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "Failed to create shortcut: $e");
|
||||
}
|
||||
""";
|
||||
await Process.run(SystemHelper.powershellPath, [script]);
|
||||
if (!context.mounted) return;
|
||||
showToast(context, S.current.setting_action_info_shortcut_created);
|
||||
}
|
||||
|
||||
Future _loadToolSiteMirrorState() async {
|
||||
final userBox = await Hive.openBox("app_conf");
|
||||
final isEnableToolSiteMirrors =
|
||||
userBox.get("isEnableToolSiteMirrors", defaultValue: false);
|
||||
final isEnableToolSiteMirrors = userBox.get("isEnableToolSiteMirrors", defaultValue: false);
|
||||
state = state.copyWith(isEnableToolSiteMirrors: isEnableToolSiteMirrors);
|
||||
}
|
||||
|
||||
@ -213,8 +199,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
}
|
||||
|
||||
Future<void> showLogs() async {
|
||||
SystemHelper.openDir(getDPrintFile()?.absolute.path.replaceAll("/", "\\"),
|
||||
isFile: true);
|
||||
SystemHelper.openDir(getDPrintFile()?.absolute.path.replaceAll("/", "\\"), isFile: true);
|
||||
}
|
||||
|
||||
void onChangeUseInternalDNS(bool? b) {
|
||||
@ -225,8 +210,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
|
||||
Future _loadUseInternalDNS() async {
|
||||
final userBox = await Hive.openBox("app_conf");
|
||||
final isUseInternalDNS =
|
||||
userBox.get("isUseInternalDNS", defaultValue: false);
|
||||
final isUseInternalDNS = userBox.get("isUseInternalDNS", defaultValue: false);
|
||||
state = state.copyWith(isUseInternalDNS: isUseInternalDNS);
|
||||
}
|
||||
|
||||
@ -238,8 +222,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
|
||||
Future _loadOnnxXnnPackState() async {
|
||||
final userBox = await Hive.openBox("app_conf");
|
||||
final isEnableOnnxXnnPack =
|
||||
userBox.get("isEnableOnnxXnnPack", defaultValue: true);
|
||||
final isEnableOnnxXnnPack = userBox.get("isEnableOnnxXnnPack", defaultValue: true);
|
||||
state = state.copyWith(isEnableOnnxXnnPack: isEnableOnnxXnnPack);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ final class SettingsUIModelProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$settingsUIModelHash() => r'72947d5ed36290df865cb010b056dc632f5dccec';
|
||||
String _$settingsUIModelHash() => r'd34b1a2fac69d10f560d9a2e1a7431dd5a7954ca';
|
||||
|
||||
abstract class _$SettingsUIModel extends $Notifier<SettingsUIState> {
|
||||
SettingsUIState build();
|
||||
|
||||
@ -11,6 +11,7 @@ import 'package:starcitizen_doctor/app.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/conf.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/url_conf.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/system_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/win32_api.dart' as win32;
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
import 'package:starcitizen_doctor/widgets/widgets.dart';
|
||||
import 'package:html/parser.dart' as html_parser;
|
||||
@ -44,39 +45,36 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
|
||||
return Material(
|
||||
child: ContentDialog(
|
||||
title:
|
||||
Text(S.current.app_upgrade_title_new_version_found(targetVersion)),
|
||||
constraints:
|
||||
BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .55),
|
||||
title: Text(S.current.app_upgrade_title_new_version_found(targetVersion)),
|
||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .55),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 24, right: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (description.value == null) ...[
|
||||
Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const ProgressRing(),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.current
|
||||
.app_upgrade_info_getting_new_version_details)
|
||||
],
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 24, right: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (description.value == null) ...[
|
||||
Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const ProgressRing(),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.current.app_upgrade_info_getting_new_version_details),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
] else
|
||||
...makeMarkdownView(description.value!,
|
||||
attachmentsUrl: URLConf.giteaAttachmentsUrl),
|
||||
],
|
||||
] else
|
||||
...makeMarkdownView(description.value!, attachmentsUrl: URLConf.giteaAttachmentsUrl),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
),
|
||||
if (isUsingDiversion.value) ...[
|
||||
const SizedBox(height: 24),
|
||||
GestureDetector(
|
||||
@ -84,13 +82,12 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: .1),
|
||||
borderRadius: BorderRadius.circular(7)),
|
||||
color: Colors.white.withValues(alpha: .1),
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
),
|
||||
child: Text(
|
||||
S.current.app_upgrade_info_update_server_tip,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.white.withValues(alpha: .7)),
|
||||
style: TextStyle(fontSize: 14, color: Colors.white.withValues(alpha: .7)),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -99,14 +96,12 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
children: [
|
||||
Text(progress.value == 100
|
||||
? S.current.app_upgrade_info_installing
|
||||
: S.current.app_upgrade_info_downloading(
|
||||
progress.value.toStringAsFixed(2))),
|
||||
Expanded(
|
||||
child: ProgressBar(
|
||||
value: progress.value == 100 ? null : progress.value,
|
||||
)),
|
||||
Text(
|
||||
progress.value == 100
|
||||
? S.current.app_upgrade_info_installing
|
||||
: S.current.app_upgrade_info_downloading(progress.value.toStringAsFixed(2)),
|
||||
),
|
||||
Expanded(child: ProgressBar(value: progress.value == 100 ? null : progress.value)),
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -117,38 +112,40 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
: [
|
||||
if (downloadUrl.value.isNotEmpty)
|
||||
FilledButton(
|
||||
onPressed: () => _doUpgrade(
|
||||
context,
|
||||
appState,
|
||||
isUpgrading,
|
||||
appModel,
|
||||
downloadUrl,
|
||||
description,
|
||||
isUsingDiversion,
|
||||
progress),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 4, bottom: 4, left: 8, right: 8),
|
||||
child: Text(S.current.app_upgrade_action_update_now),
|
||||
)),
|
||||
onPressed: () => _doUpgrade(
|
||||
context,
|
||||
appState,
|
||||
isUpgrading,
|
||||
appModel,
|
||||
downloadUrl,
|
||||
description,
|
||||
isUsingDiversion,
|
||||
progress,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 4, bottom: 4, left: 8, right: 8),
|
||||
child: Text(S.current.app_upgrade_action_update_now),
|
||||
),
|
||||
),
|
||||
if (ConstConf.appVersionCode >= (minVersionCode ?? 0))
|
||||
Button(
|
||||
onPressed: () => _doCancel(context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 4, bottom: 4, left: 8, right: 8),
|
||||
child: Text(S.current.app_upgrade_action_next_time),
|
||||
)),
|
||||
onPressed: () => _doCancel(context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 4, bottom: 4, left: 8, right: 8),
|
||||
child: Text(S.current.app_upgrade_action_next_time),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _getUpdateInfo(
|
||||
BuildContext context,
|
||||
String targetVersion,
|
||||
ValueNotifier<String?> description,
|
||||
ValueNotifier<String> downloadUrl) async {
|
||||
BuildContext context,
|
||||
String targetVersion,
|
||||
ValueNotifier<String?> description,
|
||||
ValueNotifier<String> downloadUrl,
|
||||
) async {
|
||||
try {
|
||||
final r = await Api.getAppReleaseDataByVersionName(targetVersion);
|
||||
description.value = r["body"];
|
||||
@ -193,19 +190,19 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
Future<void> _doUpgrade(
|
||||
BuildContext context,
|
||||
AppGlobalState appState,
|
||||
ValueNotifier<bool> isUpgrading,
|
||||
AppGlobalModel appModel,
|
||||
ValueNotifier<String> downloadUrl,
|
||||
ValueNotifier<String?> description,
|
||||
ValueNotifier<bool> isUsingDiversion,
|
||||
ValueNotifier<double> progress) async {
|
||||
BuildContext context,
|
||||
AppGlobalState appState,
|
||||
ValueNotifier<bool> isUpgrading,
|
||||
AppGlobalModel appModel,
|
||||
ValueNotifier<String> downloadUrl,
|
||||
ValueNotifier<String?> description,
|
||||
ValueNotifier<bool> isUsingDiversion,
|
||||
ValueNotifier<double> progress,
|
||||
) async {
|
||||
if (ConstConf.isMSE) {
|
||||
launchUrlString("ms-windows-store://pdp/?productid=9NF3SWFWNKL1");
|
||||
await Future.delayed(const Duration(seconds: 3));
|
||||
if (ConstConf.appVersionCode <
|
||||
(appState.networkVersionData?.minVersionCode ?? 0)) {
|
||||
if (ConstConf.appVersionCode < (appState.networkVersionData?.minVersionCode ?? 0)) {
|
||||
exit(0);
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
@ -221,10 +218,10 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
final dio = Dio();
|
||||
if (diversionDownloadUrl.isNotEmpty) {
|
||||
try {
|
||||
final resp = await dio.head(diversionDownloadUrl,
|
||||
options: Options(
|
||||
sendTimeout: const Duration(seconds: 10),
|
||||
receiveTimeout: const Duration(seconds: 10)));
|
||||
final resp = await dio.head(
|
||||
diversionDownloadUrl,
|
||||
options: Options(sendTimeout: const Duration(seconds: 10), receiveTimeout: const Duration(seconds: 10)),
|
||||
);
|
||||
if (resp.statusCode == 200) {
|
||||
isUsingDiversion.value = true;
|
||||
url = diversionDownloadUrl;
|
||||
@ -236,10 +233,13 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
dPrint("diversionDownloadUrl err:$e");
|
||||
}
|
||||
}
|
||||
await dio.download(url, fileName,
|
||||
onReceiveProgress: (int count, int total) {
|
||||
progress.value = (count / total) * 100;
|
||||
});
|
||||
await dio.download(
|
||||
url,
|
||||
fileName,
|
||||
onReceiveProgress: (int count, int total) {
|
||||
progress.value = (count / total) * 100;
|
||||
},
|
||||
);
|
||||
} catch (_) {
|
||||
isUpgrading.value = false;
|
||||
progress.value = 0;
|
||||
@ -249,11 +249,7 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
try {
|
||||
final r = await (Process.run(
|
||||
SystemHelper.powershellPath, ["start", fileName, "/SILENT"]));
|
||||
if (r.stderr.toString().isNotEmpty) {
|
||||
throw r.stderr;
|
||||
}
|
||||
await win32.startProcess(program: fileName, args: ["/SILENT"]);
|
||||
exit(0);
|
||||
} catch (_) {
|
||||
isUpgrading.value = false;
|
||||
|
||||
@ -7,7 +7,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:starcitizen_doctor/api/analytics.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/system_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/io/rs_http.dart';
|
||||
import 'package:starcitizen_doctor/common/rust/api/win32_api.dart' as win32;
|
||||
import 'package:starcitizen_doctor/common/utils/async.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/base_utils.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
|
||||
class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
@ -15,12 +17,8 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
|
||||
static final _hostsMap = {
|
||||
"Recaptcha": ["www.recaptcha.net", "recaptcha.net"],
|
||||
S.current.tools_hosts_info_rsi_official_website: [
|
||||
"robertsspaceindustries.com"
|
||||
],
|
||||
S.current.tools_hosts_info_rsi_customer_service: [
|
||||
"support.robertsspaceindustries.com"
|
||||
],
|
||||
S.current.tools_hosts_info_rsi_official_website: ["robertsspaceindustries.com"],
|
||||
S.current.tools_hosts_info_rsi_customer_service: ["support.robertsspaceindustries.com"],
|
||||
};
|
||||
|
||||
@override
|
||||
@ -31,9 +29,7 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
|
||||
doHost(BuildContext context) async {
|
||||
if (workingMap.value.isEmpty) {
|
||||
final hasTrue =
|
||||
checkedMap.value.values.where((element) => element).firstOrNull !=
|
||||
null;
|
||||
final hasTrue = checkedMap.value.values.where((element) => element).firstOrNull != null;
|
||||
if (!hasTrue) {
|
||||
for (var k in _hostsMap.keys) {
|
||||
checkedMap.value[k] = true;
|
||||
@ -59,32 +55,29 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
}, []);
|
||||
|
||||
return ContentDialog(
|
||||
constraints:
|
||||
BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .55),
|
||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .55),
|
||||
title: Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
FluentIcons.back,
|
||||
size: 22,
|
||||
),
|
||||
onPressed:
|
||||
workingText.value.isEmpty ? Navigator.of(context).pop : null),
|
||||
icon: const Icon(FluentIcons.back, size: 22),
|
||||
onPressed: workingText.value.isEmpty ? Navigator.of(context).pop : null,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(S.current.tools_hosts_info_hosts_acceleration),
|
||||
const Spacer(),
|
||||
Button(
|
||||
onPressed: () => _openHostsFile(context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(3),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(FluentIcons.open_file),
|
||||
const SizedBox(width: 6),
|
||||
Text(S.current.tools_hosts_info_open_hosts_file),
|
||||
],
|
||||
),
|
||||
))
|
||||
onPressed: () => _openHostsFile(context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(3),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(FluentIcons.open_file),
|
||||
const SizedBox(width: 6),
|
||||
Text(S.current.tools_hosts_info_open_hosts_file),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
content: AnimatedSize(
|
||||
@ -111,10 +104,8 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.all(6),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final isEnable =
|
||||
checkedMap.value[_hostsMap.keys.elementAt(index)] ?? false;
|
||||
final workingState =
|
||||
workingMap.value[_hostsMap.keys.elementAt(index)];
|
||||
final isEnable = checkedMap.value[_hostsMap.keys.elementAt(index)] ?? false;
|
||||
final workingState = workingMap.value[_hostsMap.keys.elementAt(index)];
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
@ -124,23 +115,16 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
if (workingState == null)
|
||||
Icon(FontAwesomeIcons.xmark,
|
||||
size: 24, color: Colors.red),
|
||||
if (workingState == 0)
|
||||
const SizedBox(
|
||||
width: 24, height: 24, child: ProgressRing()),
|
||||
if (workingState == 1)
|
||||
Icon(FontAwesomeIcons.check,
|
||||
size: 24, color: Colors.green),
|
||||
if (workingState == null) Icon(FontAwesomeIcons.xmark, size: 24, color: Colors.red),
|
||||
if (workingState == 0) const SizedBox(width: 24, height: 24, child: ProgressRing()),
|
||||
if (workingState == 1) Icon(FontAwesomeIcons.check, size: 24, color: Colors.green),
|
||||
const SizedBox(width: 24),
|
||||
const SizedBox(width: 12),
|
||||
Text(_hostsMap.keys.elementAt(index)),
|
||||
const Spacer(),
|
||||
ToggleSwitch(
|
||||
onChanged: (value) {
|
||||
checkedMap.value[_hostsMap.keys.elementAt(index)] =
|
||||
value;
|
||||
checkedMap.value[_hostsMap.keys.elementAt(index)] = value;
|
||||
checkedMap.value = Map.from(checkedMap.value);
|
||||
},
|
||||
checked: isEnable,
|
||||
@ -156,8 +140,7 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
height: 86,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 42, width: 42, child: ProgressRing()),
|
||||
const SizedBox(height: 42, width: 42, child: ProgressRing()),
|
||||
const SizedBox(height: 12),
|
||||
Text(workingText.value),
|
||||
],
|
||||
@ -169,10 +152,8 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
child: FilledButton(
|
||||
onPressed: () => doHost(context),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 3, bottom: 3, left: 12, right: 12),
|
||||
child: Text(
|
||||
S.current.tools_hosts_action_one_click_acceleration),
|
||||
padding: const EdgeInsets.only(top: 3, bottom: 3, left: 12, right: 12),
|
||||
child: Text(S.current.tools_hosts_action_one_click_acceleration),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -183,17 +164,19 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
Future<void> _openHostsFile(BuildContext context) async {
|
||||
// 使用管理员权限调用记事本${S.current.tools_hosts_info_open_hosts_file}
|
||||
Process.run(SystemHelper.powershellPath, [
|
||||
"-Command",
|
||||
"Start-Process notepad.exe -Verb runAs -ArgumentList ${SystemHelper.getHostsFilePath()}"
|
||||
// ignore: use_build_context_synchronously
|
||||
]).unwrap(context: context);
|
||||
// 使用管理员权限调用记事本
|
||||
try {
|
||||
await win32.runAsAdmin(program: "notepad.exe", args: SystemHelper.getHostsFilePath());
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "Failed to open hosts file: $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, String>> _doCheckDns(
|
||||
ValueNotifier<Map<String, int?>> workingMap,
|
||||
ValueNotifier<Map<String, bool>> checkedMap) async {
|
||||
ValueNotifier<Map<String, int?>> workingMap,
|
||||
ValueNotifier<Map<String, bool>> checkedMap,
|
||||
) async {
|
||||
Map<String, String> result = {};
|
||||
final trueLen = checkedMap.value.values.where((element) => element).length;
|
||||
if (trueLen == 0) {
|
||||
@ -207,36 +190,37 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
}
|
||||
workingMap.value[siteName] = 0;
|
||||
workingMap.value = Map.from(workingMap.value);
|
||||
RSHttp.dnsLookupIps(siteHost).then((ips) async {
|
||||
int tryCount = ips.length;
|
||||
try {
|
||||
for (var ip in ips) {
|
||||
final resp =
|
||||
await RSHttp.head("https://$siteHost", withIpAddress: ip);
|
||||
dPrint(
|
||||
"[HostsBooster] host== $siteHost ip== $ip resp== ${resp.headers}");
|
||||
if (resp.headers.isNotEmpty) {
|
||||
if (result[siteName] == null) {
|
||||
result[siteName] = ip;
|
||||
workingMap.value[siteName] = 1;
|
||||
workingMap.value = Map.from(workingMap.value);
|
||||
break;
|
||||
RSHttp.dnsLookupIps(siteHost).then(
|
||||
(ips) async {
|
||||
int tryCount = ips.length;
|
||||
try {
|
||||
for (var ip in ips) {
|
||||
final resp = await RSHttp.head("https://$siteHost", withIpAddress: ip);
|
||||
dPrint("[HostsBooster] host== $siteHost ip== $ip resp== ${resp.headers}");
|
||||
if (resp.headers.isNotEmpty) {
|
||||
if (result[siteName] == null) {
|
||||
result[siteName] = ip;
|
||||
workingMap.value[siteName] = 1;
|
||||
workingMap.value = Map.from(workingMap.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
tryCount--;
|
||||
if (tryCount == 0) {
|
||||
workingMap.value[siteName] = null;
|
||||
workingMap.value = Map.from(workingMap.value);
|
||||
result[siteName] = "";
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
tryCount--;
|
||||
if (tryCount == 0) {
|
||||
workingMap.value[siteName] = null;
|
||||
workingMap.value = Map.from(workingMap.value);
|
||||
result[siteName] = "";
|
||||
}
|
||||
}
|
||||
}, onError: (e) {
|
||||
workingMap.value[siteName] = null;
|
||||
workingMap.value = Map.from(workingMap.value);
|
||||
result[siteName] = "";
|
||||
});
|
||||
},
|
||||
onError: (e) {
|
||||
workingMap.value[siteName] = null;
|
||||
workingMap.value = Map.from(workingMap.value);
|
||||
result[siteName] = "";
|
||||
},
|
||||
);
|
||||
}
|
||||
while (true) {
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
@ -265,16 +249,17 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
final domains = _hostsMap[kv.key] ?? <String>[];
|
||||
for (var domain in domains) {
|
||||
if (kv.value != "") {
|
||||
newHostsFileLines
|
||||
.add("${kv.value} $domain #StarCitizenToolBox");
|
||||
newHostsFileLines.add("${kv.value} $domain #StarCitizenToolBox");
|
||||
}
|
||||
}
|
||||
}
|
||||
await hostsFile.writeAsString(newHostsFileLines.join("\n"), flush: true);
|
||||
}
|
||||
|
||||
Future<void> _readHostsState(ValueNotifier<Map<String, int?>> workingMap,
|
||||
ValueNotifier<Map<String, bool>> checkedMap) async {
|
||||
Future<void> _readHostsState(
|
||||
ValueNotifier<Map<String, int?>> workingMap,
|
||||
ValueNotifier<Map<String, bool>> checkedMap,
|
||||
) async {
|
||||
workingMap.value.clear();
|
||||
final hostsFile = File(SystemHelper.getHostsFilePath());
|
||||
final hostsFileString = await hostsFile.readAsString();
|
||||
|
||||
97
rust/Cargo.lock
generated
97
rust/Cargo.lock
generated
@ -4117,6 +4117,7 @@ dependencies = [
|
||||
"walkdir",
|
||||
"win32job",
|
||||
"windows 0.62.2",
|
||||
"wmi",
|
||||
"wry",
|
||||
]
|
||||
|
||||
@ -5589,7 +5590,7 @@ dependencies = [
|
||||
"webview2-com-sys",
|
||||
"windows 0.61.3",
|
||||
"windows-core 0.61.2",
|
||||
"windows-implement",
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface",
|
||||
]
|
||||
|
||||
@ -5662,6 +5663,19 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddf874e74c7a99773e62b1c671427abf01a425e77c3d3fb9fb1e4883ea934529"
|
||||
dependencies = [
|
||||
"windows-collections 0.1.1",
|
||||
"windows-core 0.60.1",
|
||||
"windows-future 0.1.1",
|
||||
"windows-link 0.1.3",
|
||||
"windows-numerics 0.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.61.3"
|
||||
@ -5687,6 +5701,15 @@ dependencies = [
|
||||
"windows-numerics 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5467f79cc1ba3f52ebb2ed41dbb459b8e7db636cc3429458d9a852e15bc24dec"
|
||||
dependencies = [
|
||||
"windows-core 0.60.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.2.0"
|
||||
@ -5705,13 +5728,26 @@ dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.60.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247"
|
||||
dependencies = [
|
||||
"windows-implement 0.59.0",
|
||||
"windows-interface",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
@ -5724,13 +5760,23 @@ version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface",
|
||||
"windows-link 0.2.1",
|
||||
"windows-result 0.4.1",
|
||||
"windows-strings 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a787db4595e7eb80239b74ce8babfb1363d8e343ab072f2ffe901400c03349f0"
|
||||
dependencies = [
|
||||
"windows-core 0.60.1",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.2.1"
|
||||
@ -5753,6 +5799,17 @@ dependencies = [
|
||||
"windows-threading 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
@ -5787,6 +5844,16 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "005dea54e2f6499f2cee279b8f703b3cf3b5734a2d8d21867c8f44003182eeed"
|
||||
dependencies = [
|
||||
"windows-core 0.60.1",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.2.0"
|
||||
@ -5836,6 +5903,15 @@ dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.2"
|
||||
@ -6203,6 +6279,21 @@ version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
|
||||
[[package]]
|
||||
name = "wmi"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f902b4592b911109e7352bcfec7b754b07ec71e514d7dfa280eaef924c1cb08"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures",
|
||||
"log",
|
||||
"serde",
|
||||
"thiserror 2.0.17",
|
||||
"windows 0.60.0",
|
||||
"windows-core 0.60.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.6.2"
|
||||
|
||||
@ -47,9 +47,20 @@ windows = { version = "0.62.2", features = [
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
"Win32_System_Diagnostics_ToolHelp",
|
||||
"Win32_System_Threading",
|
||||
"Win32_Foundation"
|
||||
"Win32_Foundation",
|
||||
"Win32_System_SystemInformation",
|
||||
"Win32_System_Registry",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_UI_Shell",
|
||||
"Win32_System_Com",
|
||||
"Win32_System_Ole",
|
||||
"Win32_System_Variant",
|
||||
"Win32_Security",
|
||||
"Win32_System_IO",
|
||||
"Win32_System_Ioctl"
|
||||
] }
|
||||
win32job = "2.0.3"
|
||||
wmi = "0.15"
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(frb_expand)'] }
|
||||
|
||||
@ -26,6 +26,359 @@ pub fn send_notify(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get system memory size in GB
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_system_memory_size_gb() -> anyhow::Result<u64> {
|
||||
use windows::Win32::System::SystemInformation::{GlobalMemoryStatusEx, MEMORYSTATUSEX};
|
||||
use std::mem;
|
||||
|
||||
unsafe {
|
||||
let mut mem_status: MEMORYSTATUSEX = mem::zeroed();
|
||||
mem_status.dwLength = mem::size_of::<MEMORYSTATUSEX>() as u32;
|
||||
|
||||
GlobalMemoryStatusEx(&mut mem_status)?;
|
||||
|
||||
// Convert bytes to GB
|
||||
Ok(mem_status.ullTotalPhys / (1024 * 1024 * 1024))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn get_system_memory_size_gb() -> anyhow::Result<u64> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// Get number of logical processors
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_number_of_logical_processors() -> anyhow::Result<u32> {
|
||||
use windows::Win32::System::SystemInformation::{GetSystemInfo, SYSTEM_INFO};
|
||||
use std::mem;
|
||||
|
||||
unsafe {
|
||||
let mut sys_info: SYSTEM_INFO = mem::zeroed();
|
||||
GetSystemInfo(&mut sys_info);
|
||||
Ok(sys_info.dwNumberOfProcessors)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn get_number_of_logical_processors() -> anyhow::Result<u32> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// System information struct
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SystemInfo {
|
||||
pub os_name: String,
|
||||
pub cpu_name: String,
|
||||
pub gpu_info: String,
|
||||
pub disk_info: String,
|
||||
}
|
||||
|
||||
/// Get all system information at once
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_system_info() -> anyhow::Result<SystemInfo> {
|
||||
use wmi::{COMLibrary, WMIConnection};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[serde(rename = "Caption")]
|
||||
struct OsInfo {
|
||||
#[serde(rename = "Caption")]
|
||||
caption: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct CpuInfo {
|
||||
#[serde(rename = "Name")]
|
||||
name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct GpuInfo {
|
||||
#[serde(rename = "Name")]
|
||||
name: Option<String>,
|
||||
#[serde(rename = "AdapterRAM")]
|
||||
adapter_ram: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct DiskInfo {
|
||||
#[serde(rename = "MediaType")]
|
||||
media_type: Option<String>,
|
||||
#[serde(rename = "Model")]
|
||||
model: Option<String>,
|
||||
#[serde(rename = "Size")]
|
||||
size: Option<u64>,
|
||||
}
|
||||
|
||||
let com_con = COMLibrary::new()?;
|
||||
let wmi_con = WMIConnection::new(com_con)?;
|
||||
|
||||
// Get OS name using raw query
|
||||
let os_name = match wmi_con.raw_query::<OsInfo>("SELECT Caption FROM Win32_OperatingSystem") {
|
||||
Ok(results) => results.first()
|
||||
.and_then(|os| os.caption.clone())
|
||||
.unwrap_or_default(),
|
||||
Err(_) => String::new(),
|
||||
};
|
||||
|
||||
// Get CPU name using raw query
|
||||
let cpu_name = match wmi_con.raw_query::<CpuInfo>("SELECT Name FROM Win32_Processor") {
|
||||
Ok(results) => results.first()
|
||||
.and_then(|cpu| cpu.name.clone())
|
||||
.unwrap_or_default(),
|
||||
Err(_) => String::new(),
|
||||
};
|
||||
|
||||
// Get GPU info using raw query
|
||||
let gpu_info = match wmi_con.raw_query::<GpuInfo>("SELECT Name, AdapterRAM FROM Win32_VideoController") {
|
||||
Ok(results) => results.iter()
|
||||
.filter_map(|gpu| {
|
||||
gpu.name.as_ref().map(|name| {
|
||||
let vram_gb = gpu.adapter_ram.unwrap_or(0) / (1024 * 1024 * 1024);
|
||||
format!("{} ({} GB)", name, vram_gb)
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
Err(_) => String::new(),
|
||||
};
|
||||
|
||||
// Get Disk info using raw query
|
||||
let disk_info = match wmi_con.raw_query::<DiskInfo>("SELECT MediaType, Model, Size FROM Win32_DiskDrive") {
|
||||
Ok(results) => results.iter()
|
||||
.filter(|disk| disk.model.is_some())
|
||||
.map(|disk| {
|
||||
let size_gb = disk.size.unwrap_or(0) / (1024 * 1024 * 1024);
|
||||
format!("{}\t{}\t{} GB",
|
||||
disk.media_type.as_deref().unwrap_or(""),
|
||||
disk.model.as_deref().unwrap_or(""),
|
||||
size_gb)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
Err(_) => String::new(),
|
||||
};
|
||||
|
||||
Ok(SystemInfo {
|
||||
os_name,
|
||||
cpu_name,
|
||||
gpu_info,
|
||||
disk_info,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn get_system_info() -> anyhow::Result<SystemInfo> {
|
||||
Ok(SystemInfo {
|
||||
os_name: String::new(),
|
||||
cpu_name: String::new(),
|
||||
gpu_info: String::new(),
|
||||
disk_info: String::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get GPU info from registry (more accurate VRAM)
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
|
||||
use windows::Win32::System::Registry::{
|
||||
RegOpenKeyExW, RegQueryValueExW, RegEnumKeyExW, RegCloseKey,
|
||||
HKEY_LOCAL_MACHINE, KEY_READ, REG_VALUE_TYPE,
|
||||
};
|
||||
use windows::core::{HSTRING, PCWSTR};
|
||||
use std::mem;
|
||||
|
||||
let mut result = Vec::new();
|
||||
let base_path = HSTRING::from(r"SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}");
|
||||
|
||||
unsafe {
|
||||
let mut hkey = std::mem::zeroed();
|
||||
if RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
PCWSTR(base_path.as_ptr()),
|
||||
Some(0),
|
||||
KEY_READ,
|
||||
&mut hkey,
|
||||
).is_err() {
|
||||
return Ok(String::new());
|
||||
}
|
||||
|
||||
let mut index = 0u32;
|
||||
let mut key_name = [0u16; 256];
|
||||
|
||||
loop {
|
||||
let mut key_name_len = key_name.len() as u32;
|
||||
if RegEnumKeyExW(
|
||||
hkey,
|
||||
index,
|
||||
Some(windows::core::PWSTR::from_raw(key_name.as_mut_ptr())),
|
||||
&mut key_name_len,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
).is_err() {
|
||||
break;
|
||||
}
|
||||
|
||||
let subkey_name = String::from_utf16_lossy(&key_name[..key_name_len as usize]);
|
||||
|
||||
// Only process numbered subkeys (0000, 0001, etc.)
|
||||
if subkey_name.chars().all(|c| c.is_ascii_digit()) {
|
||||
let full_path = HSTRING::from(format!(
|
||||
r"SYSTEM\ControlSet001\Control\Class\{{4d36e968-e325-11ce-bfc1-08002be10318}}\{}",
|
||||
subkey_name
|
||||
));
|
||||
|
||||
let mut subkey = mem::zeroed();
|
||||
if RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
PCWSTR(full_path.as_ptr()),
|
||||
Some(0),
|
||||
KEY_READ,
|
||||
&mut subkey,
|
||||
).is_ok() {
|
||||
// Read adapter string
|
||||
let adapter_name = HSTRING::from("HardwareInformation.AdapterString");
|
||||
let mut adapter_buffer = [0u16; 512];
|
||||
let mut adapter_size = (adapter_buffer.len() * 2) as u32;
|
||||
let mut adapter_type = REG_VALUE_TYPE::default();
|
||||
|
||||
let adapter_string = if RegQueryValueExW(
|
||||
subkey,
|
||||
PCWSTR(adapter_name.as_ptr()),
|
||||
None,
|
||||
Some(&mut adapter_type),
|
||||
Some(adapter_buffer.as_mut_ptr() as *mut u8),
|
||||
Some(&mut adapter_size),
|
||||
).is_ok() {
|
||||
let len = (adapter_size as usize / 2).saturating_sub(1);
|
||||
String::from_utf16_lossy(&adapter_buffer[..len])
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
// Read memory size
|
||||
let mem_name = HSTRING::from("HardwareInformation.qwMemorySize");
|
||||
let mut mem_value: u64 = 0;
|
||||
let mut mem_size = std::mem::size_of::<u64>() as u32;
|
||||
let mut mem_type = REG_VALUE_TYPE::default();
|
||||
|
||||
let vram_gb = if RegQueryValueExW(
|
||||
subkey,
|
||||
PCWSTR(mem_name.as_ptr()),
|
||||
None,
|
||||
Some(&mut mem_type),
|
||||
Some(&mut mem_value as *mut u64 as *mut u8),
|
||||
Some(&mut mem_size),
|
||||
).is_ok() {
|
||||
mem_value / (1024 * 1024 * 1024)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if !adapter_string.is_empty() {
|
||||
result.push(format!("Model: {}\nVRAM (GB): {}", adapter_string, vram_gb));
|
||||
}
|
||||
|
||||
let _ = RegCloseKey(subkey);
|
||||
}
|
||||
}
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
let _ = RegCloseKey(hkey);
|
||||
}
|
||||
|
||||
Ok(result.join("\n\n"))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn get_gpu_info_from_registry() -> anyhow::Result<String> {
|
||||
Ok(String::new())
|
||||
}
|
||||
|
||||
/// Resolve shortcut (.lnk) file to get target path
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn resolve_shortcut(lnk_path: &str) -> anyhow::Result<String> {
|
||||
use windows::core::{HSTRING, Interface};
|
||||
use windows::Win32::System::Com::{
|
||||
CoCreateInstance, CoInitializeEx, CoUninitialize,
|
||||
CLSCTX_INPROC_SERVER, COINIT_APARTMENTTHREADED, STGM_READ,
|
||||
};
|
||||
use windows::Win32::UI::Shell::{IShellLinkW, ShellLink};
|
||||
use windows::Win32::System::Com::IPersistFile;
|
||||
|
||||
unsafe {
|
||||
// Initialize COM
|
||||
let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED);
|
||||
|
||||
let result = (|| -> anyhow::Result<String> {
|
||||
// Create ShellLink instance
|
||||
let shell_link: IShellLinkW = CoCreateInstance(
|
||||
&ShellLink,
|
||||
None,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
)?;
|
||||
|
||||
// Get IPersistFile interface
|
||||
let persist_file: IPersistFile = shell_link.cast()?;
|
||||
|
||||
// Load the shortcut file
|
||||
let lnk_path_w = HSTRING::from(lnk_path);
|
||||
persist_file.Load(windows::core::PCWSTR(lnk_path_w.as_ptr()), STGM_READ)?;
|
||||
|
||||
// Get target path
|
||||
let mut path_buffer = [0u16; 260];
|
||||
shell_link.GetPath(
|
||||
&mut path_buffer,
|
||||
std::ptr::null_mut(),
|
||||
0,
|
||||
)?;
|
||||
|
||||
let path = String::from_utf16_lossy(
|
||||
&path_buffer[..path_buffer.iter().position(|&c| c == 0).unwrap_or(path_buffer.len())]
|
||||
);
|
||||
|
||||
Ok(path)
|
||||
})();
|
||||
|
||||
CoUninitialize();
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn resolve_shortcut(_: &str) -> anyhow::Result<String> {
|
||||
Ok(String::new())
|
||||
}
|
||||
|
||||
/// Open file explorer and select file/folder
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn open_dir_with_explorer(path: &str, is_file: bool) -> anyhow::Result<()> {
|
||||
use std::process::Command;
|
||||
|
||||
if is_file {
|
||||
Command::new("explorer.exe")
|
||||
.args(["/select,", path])
|
||||
.spawn()?;
|
||||
} else {
|
||||
Command::new("explorer.exe")
|
||||
.args(["/select,", path])
|
||||
.spawn()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn open_dir_with_explorer(path: &str, is_file: bool) -> anyhow::Result<()> {
|
||||
println!("open_dir_with_explorer (unix): {} is_file={}", path, is_file);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn set_foreground_window(window_name: &str) -> anyhow::Result<bool> {
|
||||
@ -174,4 +527,398 @@ fn get_process_path(pid: u32) -> Option<String> {
|
||||
pub fn get_process_list_by_name(process_name: &str) -> anyhow::Result<Vec<ProcessInfo>> {
|
||||
println!("get_process_list_by_name (unix): {}", process_name);
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
/// Kill processes by name
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn kill_process_by_name(process_name: &str) -> anyhow::Result<u32> {
|
||||
use windows::Win32::Foundation::CloseHandle;
|
||||
use windows::Win32::System::Threading::{OpenProcess, TerminateProcess, PROCESS_TERMINATE};
|
||||
|
||||
let processes = get_process_list_by_name(process_name)?;
|
||||
let mut killed_count = 0u32;
|
||||
|
||||
for process in processes {
|
||||
unsafe {
|
||||
if let Ok(h_process) = OpenProcess(PROCESS_TERMINATE, false, process.pid) {
|
||||
if !h_process.is_invalid() {
|
||||
if TerminateProcess(h_process, 0).is_ok() {
|
||||
killed_count += 1;
|
||||
}
|
||||
let _ = CloseHandle(h_process);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(killed_count)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn kill_process_by_name(process_name: &str) -> anyhow::Result<u32> {
|
||||
println!("kill_process_by_name (unix): {}", process_name);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// Get disk physical sector size for performance
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_disk_physical_sector_size(drive_letter: &str) -> anyhow::Result<u32> {
|
||||
use windows::Win32::Storage::FileSystem::{
|
||||
CreateFileW, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING,
|
||||
};
|
||||
use windows::Win32::System::IO::DeviceIoControl;
|
||||
use windows::Win32::System::Ioctl::IOCTL_STORAGE_QUERY_PROPERTY;
|
||||
use windows::Win32::Foundation::CloseHandle;
|
||||
use windows::core::HSTRING;
|
||||
use std::mem;
|
||||
|
||||
// STORAGE_PROPERTY_QUERY structure
|
||||
#[repr(C)]
|
||||
struct StoragePropertyQuery {
|
||||
property_id: u32,
|
||||
query_type: u32,
|
||||
additional_parameters: [u8; 1],
|
||||
}
|
||||
|
||||
// STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR structure
|
||||
#[repr(C)]
|
||||
struct StorageAccessAlignmentDescriptor {
|
||||
version: u32,
|
||||
size: u32,
|
||||
bytes_per_cache_line: u32,
|
||||
bytes_offset_for_cache_alignment: u32,
|
||||
bytes_per_logical_sector: u32,
|
||||
bytes_per_physical_sector: u32,
|
||||
bytes_offset_for_sector_alignment: u32,
|
||||
}
|
||||
|
||||
let drive_path = format!(r"\\.\{}:", drive_letter.chars().next().unwrap_or('C'));
|
||||
let drive_path_w = HSTRING::from(&drive_path);
|
||||
|
||||
unsafe {
|
||||
let handle = CreateFileW(
|
||||
&drive_path_w,
|
||||
0, // No access needed, just query
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
None,
|
||||
OPEN_EXISTING,
|
||||
windows::Win32::Storage::FileSystem::FILE_FLAGS_AND_ATTRIBUTES(0),
|
||||
None,
|
||||
)?;
|
||||
|
||||
if handle.is_invalid() {
|
||||
return Err(anyhow::anyhow!("Failed to open drive"));
|
||||
}
|
||||
|
||||
// StorageAccessAlignmentProperty = 6
|
||||
let query = StoragePropertyQuery {
|
||||
property_id: 6,
|
||||
query_type: 0, // PropertyStandardQuery
|
||||
additional_parameters: [0],
|
||||
};
|
||||
|
||||
let mut descriptor: StorageAccessAlignmentDescriptor = mem::zeroed();
|
||||
let mut bytes_returned: u32 = 0;
|
||||
|
||||
let result = DeviceIoControl(
|
||||
handle,
|
||||
IOCTL_STORAGE_QUERY_PROPERTY,
|
||||
Some(&query as *const _ as *const std::ffi::c_void),
|
||||
mem::size_of::<StoragePropertyQuery>() as u32,
|
||||
Some(&mut descriptor as *mut _ as *mut std::ffi::c_void),
|
||||
mem::size_of::<StorageAccessAlignmentDescriptor>() as u32,
|
||||
Some(&mut bytes_returned),
|
||||
None,
|
||||
);
|
||||
|
||||
let _ = CloseHandle(handle);
|
||||
|
||||
if result.is_ok() {
|
||||
Ok(descriptor.bytes_per_physical_sector)
|
||||
} else {
|
||||
Err(anyhow::anyhow!("DeviceIoControl failed"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn get_disk_physical_sector_size(drive_letter: &str) -> anyhow::Result<u32> {
|
||||
println!("get_disk_physical_sector_size (unix): {}", drive_letter);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// Create a desktop shortcut
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn create_desktop_shortcut(target_path: &str, shortcut_name: &str) -> anyhow::Result<()> {
|
||||
use windows::core::{HSTRING, Interface, BSTR};
|
||||
use windows::Win32::System::Com::{
|
||||
CoCreateInstance, CoInitializeEx, CoUninitialize,
|
||||
CLSCTX_INPROC_SERVER, COINIT_APARTMENTTHREADED,
|
||||
};
|
||||
use windows::Win32::UI::Shell::{IShellLinkW, ShellLink, SHGetKnownFolderPath, FOLDERID_Desktop};
|
||||
use windows::Win32::System::Com::IPersistFile;
|
||||
|
||||
unsafe {
|
||||
let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED);
|
||||
|
||||
let result = (|| -> anyhow::Result<()> {
|
||||
// Get desktop path
|
||||
let desktop_path = SHGetKnownFolderPath(&FOLDERID_Desktop, windows::Win32::UI::Shell::KNOWN_FOLDER_FLAG(0), None)?;
|
||||
let desktop_str = desktop_path.to_string()?;
|
||||
|
||||
// Create ShellLink instance
|
||||
let shell_link: IShellLinkW = CoCreateInstance(
|
||||
&ShellLink,
|
||||
None,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
)?;
|
||||
|
||||
// Set target path
|
||||
let target_w = HSTRING::from(target_path);
|
||||
shell_link.SetPath(&target_w)?;
|
||||
|
||||
// Get IPersistFile interface
|
||||
let persist_file: IPersistFile = shell_link.cast()?;
|
||||
|
||||
// Create shortcut file path
|
||||
let shortcut_path = format!("{}\\{}", desktop_str, shortcut_name);
|
||||
let shortcut_w = BSTR::from(&shortcut_path);
|
||||
|
||||
// Save shortcut
|
||||
persist_file.Save(windows::core::PCWSTR(shortcut_w.as_ptr()), true)?;
|
||||
|
||||
Ok(())
|
||||
})();
|
||||
|
||||
CoUninitialize();
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn create_desktop_shortcut(target_path: &str, shortcut_name: &str) -> anyhow::Result<()> {
|
||||
println!("create_desktop_shortcut (unix): {} -> {}", target_path, shortcut_name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run a program with admin privileges (UAC)
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn run_as_admin(program: &str, args: &str) -> anyhow::Result<()> {
|
||||
use windows::core::HSTRING;
|
||||
use windows::Win32::UI::Shell::ShellExecuteW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
|
||||
|
||||
let operation = HSTRING::from("runas");
|
||||
let file = HSTRING::from(program);
|
||||
let parameters = HSTRING::from(args);
|
||||
|
||||
unsafe {
|
||||
let result = ShellExecuteW(
|
||||
None,
|
||||
&operation,
|
||||
&file,
|
||||
¶meters,
|
||||
None,
|
||||
SW_SHOWNORMAL,
|
||||
);
|
||||
|
||||
// ShellExecuteW returns a value > 32 on success
|
||||
if result.0 as usize > 32 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow::anyhow!("ShellExecuteW failed with code: {}", result.0 as usize))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn run_as_admin(program: &str, args: &str) -> anyhow::Result<()> {
|
||||
println!("run_as_admin (unix): {} {}", program, args);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Start a program (without waiting)
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn start_process(program: &str, args: Vec<String>) -> anyhow::Result<()> {
|
||||
use std::process::Command;
|
||||
|
||||
Command::new(program)
|
||||
.args(&args)
|
||||
.spawn()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn start_process(program: &str, args: Vec<String>) -> anyhow::Result<()> {
|
||||
println!("start_process (unix): {} {:?}", program, args);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// ============== NVME Patch Functions ==============
|
||||
#[cfg(target_os = "windows")]
|
||||
const NVME_REGISTRY_PATH: &str = r"SYSTEM\CurrentControlSet\Services\stornvme\Parameters\Device";
|
||||
#[cfg(target_os = "windows")]
|
||||
const NVME_VALUE_NAME: &str = "ForcedPhysicalSectorSizeInBytes";
|
||||
|
||||
/// Check if NVME patch is applied
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn check_nvme_patch_status() -> anyhow::Result<bool> {
|
||||
use windows::Win32::System::Registry::{
|
||||
RegOpenKeyExW, RegQueryValueExW, RegCloseKey,
|
||||
HKEY_LOCAL_MACHINE, KEY_READ, REG_VALUE_TYPE,
|
||||
};
|
||||
use windows::core::{HSTRING, PCWSTR};
|
||||
|
||||
unsafe {
|
||||
let path = HSTRING::from(NVME_REGISTRY_PATH);
|
||||
let mut hkey = std::mem::zeroed();
|
||||
|
||||
// Try to open the registry key
|
||||
if RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
PCWSTR(path.as_ptr()),
|
||||
Some(0),
|
||||
KEY_READ,
|
||||
&mut hkey,
|
||||
).is_err() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// Query the value
|
||||
let value_name = HSTRING::from(NVME_VALUE_NAME);
|
||||
let mut buffer = [0u8; 1024];
|
||||
let mut size = buffer.len() as u32;
|
||||
let mut value_type = REG_VALUE_TYPE::default();
|
||||
|
||||
let result = if RegQueryValueExW(
|
||||
hkey,
|
||||
PCWSTR(value_name.as_ptr()),
|
||||
None,
|
||||
Some(&mut value_type),
|
||||
Some(buffer.as_mut_ptr()),
|
||||
Some(&mut size),
|
||||
).is_ok() {
|
||||
// Check if the value contains "* 4095"
|
||||
// REG_MULTI_SZ is stored as null-terminated wide strings
|
||||
let data = String::from_utf16_lossy(
|
||||
std::slice::from_raw_parts(buffer.as_ptr() as *const u16, size as usize / 2)
|
||||
);
|
||||
data.contains("* 4095")
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let _ = RegCloseKey(hkey);
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn check_nvme_patch_status() -> anyhow::Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// Add NVME patch to registry
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn add_nvme_patch() -> anyhow::Result<()> {
|
||||
use windows::Win32::System::Registry::{
|
||||
RegOpenKeyExW, RegSetValueExW, RegCloseKey,
|
||||
HKEY_LOCAL_MACHINE, KEY_WRITE, REG_MULTI_SZ,
|
||||
};
|
||||
use windows::core::{HSTRING, PCWSTR};
|
||||
|
||||
unsafe {
|
||||
let path = HSTRING::from(NVME_REGISTRY_PATH);
|
||||
let mut hkey = std::mem::zeroed();
|
||||
|
||||
// Open the registry key with write access
|
||||
let open_result = RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
PCWSTR(path.as_ptr()),
|
||||
Some(0),
|
||||
KEY_WRITE,
|
||||
&mut hkey,
|
||||
);
|
||||
if open_result.is_err() {
|
||||
return Err(anyhow::anyhow!("Failed to open registry key: {:?}", open_result));
|
||||
}
|
||||
|
||||
// Prepare the value: "* 4095" as REG_MULTI_SZ (double null terminated)
|
||||
let value_str = "* 4095\0\0";
|
||||
let value_wide: Vec<u16> = value_str.encode_utf16().collect();
|
||||
let value_name = HSTRING::from(NVME_VALUE_NAME);
|
||||
|
||||
let result = RegSetValueExW(
|
||||
hkey,
|
||||
PCWSTR(value_name.as_ptr()),
|
||||
Some(0),
|
||||
REG_MULTI_SZ,
|
||||
Some(std::slice::from_raw_parts(
|
||||
value_wide.as_ptr() as *const u8,
|
||||
value_wide.len() * 2,
|
||||
)),
|
||||
);
|
||||
|
||||
let _ = RegCloseKey(hkey);
|
||||
|
||||
if result.is_err() {
|
||||
return Err(anyhow::anyhow!("Failed to set registry value: {:?}", result));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn add_nvme_patch() -> anyhow::Result<()> {
|
||||
Err(anyhow::anyhow!("NVME patch is only supported on Windows"))
|
||||
}
|
||||
|
||||
/// Remove NVME patch from registry
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn remove_nvme_patch() -> anyhow::Result<()> {
|
||||
use windows::Win32::System::Registry::{
|
||||
RegOpenKeyExW, RegDeleteValueW, RegCloseKey,
|
||||
HKEY_LOCAL_MACHINE, KEY_WRITE,
|
||||
};
|
||||
use windows::Win32::Foundation::ERROR_FILE_NOT_FOUND;
|
||||
use windows::core::{HSTRING, PCWSTR};
|
||||
|
||||
unsafe {
|
||||
let path = HSTRING::from(NVME_REGISTRY_PATH);
|
||||
let mut hkey = std::mem::zeroed();
|
||||
|
||||
// Open the registry key with write access
|
||||
let open_result = RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
PCWSTR(path.as_ptr()),
|
||||
Some(0),
|
||||
KEY_WRITE,
|
||||
&mut hkey,
|
||||
);
|
||||
if open_result.is_err() {
|
||||
return Err(anyhow::anyhow!("Failed to open registry key: {:?}", open_result));
|
||||
}
|
||||
|
||||
let value_name = HSTRING::from(NVME_VALUE_NAME);
|
||||
|
||||
let result = RegDeleteValueW(
|
||||
hkey,
|
||||
PCWSTR(value_name.as_ptr()),
|
||||
);
|
||||
|
||||
let _ = RegCloseKey(hkey);
|
||||
|
||||
// It's OK if the value doesn't exist
|
||||
if result.is_err() && result != ERROR_FILE_NOT_FOUND {
|
||||
return Err(anyhow::anyhow!("Failed to delete registry value: {:?}", result));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn remove_nvme_patch() -> anyhow::Result<()> {
|
||||
Err(anyhow::anyhow!("NVME patch is only supported on Windows"))
|
||||
}
|
||||
@ -37,7 +37,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
|
||||
default_rust_auto_opaque = RustAutoOpaqueNom,
|
||||
);
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1";
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -1082688871;
|
||||
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1161621087;
|
||||
|
||||
// Section: executor
|
||||
|
||||
@ -45,6 +45,48 @@ flutter_rust_bridge::frb_generated_default_handler!();
|
||||
|
||||
// Section: wire_funcs
|
||||
|
||||
fn wire__crate__api__win32_api__add_nvme_patch_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "add_nvme_patch",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::add_nvme_patch()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__check_nvme_patch_status_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "check_nvme_patch_status",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::check_nvme_patch_status()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__ort_api__clear_all_models_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
@ -66,6 +108,34 @@ fn wire__crate__api__ort_api__clear_all_models_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__create_desktop_shortcut_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
target_path: impl CstDecode<String>,
|
||||
shortcut_name: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "create_desktop_shortcut",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_target_path = target_path.cst_decode();
|
||||
let api_shortcut_name = shortcut_name.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::create_desktop_shortcut(
|
||||
&api_target_path,
|
||||
&api_shortcut_name,
|
||||
)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__http_api__dns_lookup_ips_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
host: impl CstDecode<String>,
|
||||
@ -156,6 +226,31 @@ fn wire__crate__api__http_api__fetch_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__get_disk_physical_sector_size_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
drive_letter: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "get_disk_physical_sector_size",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_drive_letter = drive_letter.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::get_disk_physical_sector_size(
|
||||
&api_drive_letter,
|
||||
)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__http_api__get_faster_url_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
urls: impl CstDecode<Vec<String>>,
|
||||
@ -183,6 +278,48 @@ fn wire__crate__api__http_api__get_faster_url_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__get_gpu_info_from_registry_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "get_gpu_info_from_registry",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::get_gpu_info_from_registry()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__get_number_of_logical_processors_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "get_number_of_logical_processors",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::get_number_of_logical_processors()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__get_process_list_by_name_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
process_name: impl CstDecode<String>,
|
||||
@ -257,6 +394,72 @@ fn wire__crate__api__asar_api__get_rsi_launcher_asar_data_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__get_system_info_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "get_system_info",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::get_system_info()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__get_system_memory_size_gb_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "get_system_memory_size_gb",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::get_system_memory_size_gb()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__kill_process_by_name_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
process_name: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "kill_process_by_name",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_process_name = process_name.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok =
|
||||
crate::api::win32_api::kill_process_by_name(&api_process_name)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__ort_api__load_translation_model_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
model_path: impl CstDecode<String>,
|
||||
@ -291,6 +494,32 @@ fn wire__crate__api__ort_api__load_translation_model_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__open_dir_with_explorer_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
path: impl CstDecode<String>,
|
||||
is_file: impl CstDecode<bool>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "open_dir_with_explorer",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_path = path.cst_decode();
|
||||
let api_is_file = is_file.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok =
|
||||
crate::api::win32_api::open_dir_with_explorer(&api_path, api_is_file)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__unp4k_api__p4k_close_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
@ -436,6 +665,50 @@ fn wire__crate__api__unp4k_api__p4k_open_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__remove_nvme_patch_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "remove_nvme_patch",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::remove_nvme_patch()?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__resolve_shortcut_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
lnk_path: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "resolve_shortcut",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_lnk_path = lnk_path.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok = crate::api::win32_api::resolve_shortcut(&api_lnk_path)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__asar_api__rsi_launcher_asar_data_write_main_js_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
that: impl CstDecode<crate::api::asar_api::RsiLauncherAsarData>,
|
||||
@ -466,6 +739,32 @@ fn wire__crate__api__asar_api__rsi_launcher_asar_data_write_main_js_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__run_as_admin_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
program: impl CstDecode<String>,
|
||||
args: impl CstDecode<String>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "run_as_admin",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_program = program.cst_decode();
|
||||
let api_args = args.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok =
|
||||
crate::api::win32_api::run_as_admin(&api_program, &api_args)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__send_notify_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
summary: impl CstDecode<Option<String>>,
|
||||
@ -590,6 +889,32 @@ fn wire__crate__api__rs_process__start_impl(
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__win32_api__start_process_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
program: impl CstDecode<String>,
|
||||
args: impl CstDecode<Vec<String>>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::DcoCodec, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
debug_name: "start_process",
|
||||
port: Some(port_),
|
||||
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
|
||||
},
|
||||
move || {
|
||||
let api_program = program.cst_decode();
|
||||
let api_args = args.cst_decode();
|
||||
move |context| {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || {
|
||||
let output_ok =
|
||||
crate::api::win32_api::start_process(&api_program, api_args)?;
|
||||
Ok(output_ok)
|
||||
})(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
fn wire__crate__api__ort_api__translate_text_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
model_key: impl CstDecode<String>,
|
||||
@ -1451,6 +1776,22 @@ impl SseDecode for crate::http_package::RustHttpResponse {
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for crate::api::win32_api::SystemInfo {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
let mut var_osName = <String>::sse_decode(deserializer);
|
||||
let mut var_cpuName = <String>::sse_decode(deserializer);
|
||||
let mut var_gpuInfo = <String>::sse_decode(deserializer);
|
||||
let mut var_diskInfo = <String>::sse_decode(deserializer);
|
||||
return crate::api::win32_api::SystemInfo {
|
||||
os_name: var_osName,
|
||||
cpu_name: var_cpuName,
|
||||
gpu_info: var_gpuInfo,
|
||||
disk_info: var_diskInfo,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl SseDecode for u16 {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
@ -1789,6 +2130,29 @@ impl flutter_rust_bridge::IntoIntoDart<crate::http_package::RustHttpResponse>
|
||||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart for crate::api::win32_api::SystemInfo {
|
||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||
[
|
||||
self.os_name.into_into_dart().into_dart(),
|
||||
self.cpu_name.into_into_dart().into_dart(),
|
||||
self.gpu_info.into_into_dart().into_dart(),
|
||||
self.disk_info.into_into_dart().into_dart(),
|
||||
]
|
||||
.into_dart()
|
||||
}
|
||||
}
|
||||
impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive
|
||||
for crate::api::win32_api::SystemInfo
|
||||
{
|
||||
}
|
||||
impl flutter_rust_bridge::IntoIntoDart<crate::api::win32_api::SystemInfo>
|
||||
for crate::api::win32_api::SystemInfo
|
||||
{
|
||||
fn into_into_dart(self) -> crate::api::win32_api::SystemInfo {
|
||||
self
|
||||
}
|
||||
}
|
||||
// Codec=Dco (DartCObject based), see doc to use other codecs
|
||||
impl flutter_rust_bridge::IntoDart for crate::api::webview_api::WebViewConfiguration {
|
||||
fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi {
|
||||
[
|
||||
@ -2159,6 +2523,16 @@ impl SseEncode for crate::http_package::RustHttpResponse {
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for crate::api::win32_api::SystemInfo {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<String>::sse_encode(self.os_name, serializer);
|
||||
<String>::sse_encode(self.cpu_name, serializer);
|
||||
<String>::sse_encode(self.gpu_info, serializer);
|
||||
<String>::sse_encode(self.disk_info, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
impl SseEncode for u16 {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
@ -2481,6 +2855,17 @@ mod io {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl CstDecode<crate::api::win32_api::SystemInfo> for wire_cst_system_info {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> crate::api::win32_api::SystemInfo {
|
||||
crate::api::win32_api::SystemInfo {
|
||||
os_name: self.os_name.cst_decode(),
|
||||
cpu_name: self.cpu_name.cst_decode(),
|
||||
gpu_info: self.gpu_info.cst_decode(),
|
||||
disk_info: self.disk_info.cst_decode(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl CstDecode<crate::api::webview_api::WebViewConfiguration> for wire_cst_web_view_configuration {
|
||||
// Codec=Cst (C-struct based), see doc to use other codecs
|
||||
fn cst_decode(self) -> crate::api::webview_api::WebViewConfiguration {
|
||||
@ -2637,6 +3022,21 @@ mod io {
|
||||
Self::new_with_null_ptr()
|
||||
}
|
||||
}
|
||||
impl NewWithNullPtr for wire_cst_system_info {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
Self {
|
||||
os_name: core::ptr::null_mut(),
|
||||
cpu_name: core::ptr::null_mut(),
|
||||
gpu_info: core::ptr::null_mut(),
|
||||
disk_info: core::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Default for wire_cst_system_info {
|
||||
fn default() -> Self {
|
||||
Self::new_with_null_ptr()
|
||||
}
|
||||
}
|
||||
impl NewWithNullPtr for wire_cst_web_view_configuration {
|
||||
fn new_with_null_ptr() -> Self {
|
||||
Self {
|
||||
@ -2685,6 +3085,20 @@ mod io {
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__add_nvme_patch(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__win32_api__add_nvme_patch_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__check_nvme_patch_status(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__win32_api__check_nvme_patch_status_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__ort_api__clear_all_models(
|
||||
port_: i64,
|
||||
@ -2692,6 +3106,15 @@ mod io {
|
||||
wire__crate__api__ort_api__clear_all_models_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__create_desktop_shortcut(
|
||||
port_: i64,
|
||||
target_path: *mut wire_cst_list_prim_u_8_strict,
|
||||
shortcut_name: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__api__win32_api__create_desktop_shortcut_impl(port_, target_path, shortcut_name)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__http_api__dns_lookup_ips(
|
||||
port_: i64,
|
||||
@ -2729,6 +3152,14 @@ mod io {
|
||||
)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_disk_physical_sector_size(
|
||||
port_: i64,
|
||||
drive_letter: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__api__win32_api__get_disk_physical_sector_size_impl(port_, drive_letter)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__http_api__get_faster_url(
|
||||
port_: i64,
|
||||
@ -2738,6 +3169,20 @@ mod io {
|
||||
wire__crate__api__http_api__get_faster_url_impl(port_, urls, path_suffix)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_gpu_info_from_registry(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__win32_api__get_gpu_info_from_registry_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_number_of_logical_processors(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__win32_api__get_number_of_logical_processors_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_process_list_by_name(
|
||||
port_: i64,
|
||||
@ -2762,6 +3207,28 @@ mod io {
|
||||
wire__crate__api__asar_api__get_rsi_launcher_asar_data_impl(port_, asar_path)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_system_info(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__win32_api__get_system_info_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__get_system_memory_size_gb(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__win32_api__get_system_memory_size_gb_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__kill_process_by_name(
|
||||
port_: i64,
|
||||
process_name: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__api__win32_api__kill_process_by_name_impl(port_, process_name)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__ort_api__load_translation_model(
|
||||
port_: i64,
|
||||
@ -2779,6 +3246,15 @@ mod io {
|
||||
)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__open_dir_with_explorer(
|
||||
port_: i64,
|
||||
path: *mut wire_cst_list_prim_u_8_strict,
|
||||
is_file: bool,
|
||||
) {
|
||||
wire__crate__api__win32_api__open_dir_with_explorer_impl(port_, path, is_file)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__p4k_close(port_: i64) {
|
||||
wire__crate__api__unp4k_api__p4k_close_impl(port_)
|
||||
@ -2823,6 +3299,21 @@ mod io {
|
||||
wire__crate__api__unp4k_api__p4k_open_impl(port_, p4k_path)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__remove_nvme_patch(
|
||||
port_: i64,
|
||||
) {
|
||||
wire__crate__api__win32_api__remove_nvme_patch_impl(port_)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__resolve_shortcut(
|
||||
port_: i64,
|
||||
lnk_path: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__api__win32_api__resolve_shortcut_impl(port_, lnk_path)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__asar_api__rsi_launcher_asar_data_write_main_js(
|
||||
port_: i64,
|
||||
@ -2832,6 +3323,15 @@ mod io {
|
||||
wire__crate__api__asar_api__rsi_launcher_asar_data_write_main_js_impl(port_, that, content)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__run_as_admin(
|
||||
port_: i64,
|
||||
program: *mut wire_cst_list_prim_u_8_strict,
|
||||
args: *mut wire_cst_list_prim_u_8_strict,
|
||||
) {
|
||||
wire__crate__api__win32_api__run_as_admin_impl(port_, program, args)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__send_notify(
|
||||
port_: i64,
|
||||
@ -2876,6 +3376,15 @@ mod io {
|
||||
)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__win32_api__start_process(
|
||||
port_: i64,
|
||||
program: *mut wire_cst_list_prim_u_8_strict,
|
||||
args: *mut wire_cst_list_String,
|
||||
) {
|
||||
wire__crate__api__win32_api__start_process_impl(port_, program, args)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__ort_api__translate_text(
|
||||
port_: i64,
|
||||
@ -3245,6 +3754,14 @@ mod io {
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_system_info {
|
||||
os_name: *mut wire_cst_list_prim_u_8_strict,
|
||||
cpu_name: *mut wire_cst_list_prim_u_8_strict,
|
||||
gpu_info: *mut wire_cst_list_prim_u_8_strict,
|
||||
disk_info: *mut wire_cst_list_prim_u_8_strict,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct wire_cst_web_view_configuration {
|
||||
title: *mut wire_cst_list_prim_u_8_strict,
|
||||
width: u32,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user