mirror of
https://ghfast.top/https://github.com/StarCitizenToolBox/app.git
synced 2025-06-28 14:54:45 +08:00
re init
This commit is contained in:
93
lib/common/conf.dart
Normal file
93
lib/common/conf.dart
Normal file
@ -0,0 +1,93 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flutter_acrylic/flutter_acrylic.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:starcitizen_doctor/api/api.dart';
|
||||
import 'package:starcitizen_doctor/data/app_version_data.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../base/ui.dart';
|
||||
|
||||
class AppConf {
|
||||
static const String appVersion = "2.9 Beta";
|
||||
static const int appVersionCode = 12;
|
||||
static const String appVersionDate = "2023-10-06";
|
||||
|
||||
static const String gitlabHomeUrl =
|
||||
"https://jihulab.com/StarCitizenCN_Community/StarCitizenDoctor";
|
||||
static const String gitlabLocalizationUrl =
|
||||
"https://jihulab.com/StarCitizenCN_Community/LocalizationData";
|
||||
static const String apiRepoPath =
|
||||
"https://jihulab.com/StarCitizenCN_Community/api/-/raw/main/";
|
||||
static const String gitlabApiPath = "https://jihulab.com/api/v4/";
|
||||
|
||||
static late final String applicationSupportDir;
|
||||
|
||||
static AppVersionData? networkVersionData;
|
||||
|
||||
static bool offlineMode = false;
|
||||
|
||||
static late final WindowsDeviceInfo windowsDeviceInfo;
|
||||
|
||||
static init() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
/// init device info
|
||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||
windowsDeviceInfo = await deviceInfo.windowsInfo;
|
||||
|
||||
/// init Data
|
||||
applicationSupportDir =
|
||||
(await getApplicationSupportDirectory()).absolute.path;
|
||||
dPrint("applicationSupportDir == $applicationSupportDir");
|
||||
try {
|
||||
Hive.init("$applicationSupportDir/db");
|
||||
await Hive.openBox("app_conf");
|
||||
} catch (e) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/// init windows
|
||||
await windowManager.ensureInitialized();
|
||||
windowManager.waitUntilReadyToShow().then((_) async {
|
||||
await windowManager.setSize(const Size(1280, 820));
|
||||
await windowManager.setMinimumSize(const Size(1280, 820));
|
||||
await windowManager.center(animate: true);
|
||||
await windowManager.setSkipTaskbar(false);
|
||||
await windowManager.setTitleBarStyle(
|
||||
TitleBarStyle.hidden,
|
||||
windowButtonVisibility: false,
|
||||
);
|
||||
await windowManager.show();
|
||||
await Window.initialize();
|
||||
if (windowsDeviceInfo.productName.contains("Windows 11")) {
|
||||
await Window.setEffect(
|
||||
effect: WindowEffect.acrylic,
|
||||
);
|
||||
}
|
||||
await Window.hideWindowControls();
|
||||
});
|
||||
await _checkUpdate();
|
||||
}
|
||||
|
||||
static String getUpgradePath() {
|
||||
return "${AppConf.applicationSupportDir}/._upgrade";
|
||||
}
|
||||
|
||||
static Future<void> _checkUpdate() async {
|
||||
// clean path
|
||||
final dir = Directory(getUpgradePath());
|
||||
if (await dir.exists()) {
|
||||
dir.delete(recursive: true);
|
||||
}
|
||||
try {
|
||||
networkVersionData = await Api.getAppVersion();
|
||||
dPrint(
|
||||
"lastVersion=${networkVersionData?.lastVersion} ${networkVersionData?.lastVersionCode}");
|
||||
} catch (e) {
|
||||
dPrint("_checkUpdate Error:$e");
|
||||
}
|
||||
}
|
||||
}
|
81
lib/common/helper/log_helper.dart
Normal file
81
lib/common/helper/log_helper.dart
Normal file
@ -0,0 +1,81 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import '../utils/base_utils.dart';
|
||||
|
||||
class SCLoggerHelper {
|
||||
static Future<String?> getLogFilePath() async {
|
||||
Map<String, String> envVars = Platform.environment;
|
||||
final appDataPath = envVars["appdata"];
|
||||
if (appDataPath == null) {
|
||||
return null;
|
||||
}
|
||||
final rsiLauncherPath = "$appDataPath\\rsilauncher";
|
||||
dPrint("rsiLauncherPath:$rsiLauncherPath");
|
||||
final jsonLogPath = "$rsiLauncherPath\\logs\\log.log";
|
||||
return jsonLogPath;
|
||||
}
|
||||
|
||||
static Future<String?> getShaderCachePath() async {
|
||||
Map<String, String> envVars = Platform.environment;
|
||||
final appDataPath = envVars["LOCALAPPDATA"];
|
||||
if (appDataPath == null) {
|
||||
return null;
|
||||
}
|
||||
final scCachePath = "$appDataPath\\Star Citizen";
|
||||
dPrint("getShaderCachePath === $scCachePath");
|
||||
return scCachePath;
|
||||
}
|
||||
|
||||
static Future<List?> getLauncherLogList() async {
|
||||
final jsonLogPath = await getLogFilePath();
|
||||
if (jsonLogPath == null) return null;
|
||||
var jsonString = utf8.decode(await File(jsonLogPath).readAsBytes());
|
||||
if (jsonString.endsWith("\n")) {
|
||||
jsonString = jsonString.substring(0, jsonString.length - 3);
|
||||
}
|
||||
if (jsonString.endsWith(" ")) {
|
||||
jsonString = jsonString.substring(0, jsonString.length - 3);
|
||||
}
|
||||
if (jsonString.endsWith(",")) {
|
||||
jsonString = jsonString.substring(0, jsonString.length - 3);
|
||||
}
|
||||
return json.decode("[$jsonString]");
|
||||
}
|
||||
|
||||
static Future<List<String>> getGameInstallPath(List listData,
|
||||
{bool checkExists = true,
|
||||
List<String> withVersion = const ["LIVE"]}) async {
|
||||
List<String> scInstallPaths = [];
|
||||
|
||||
for (var v in withVersion) {
|
||||
for (var i = listData.length - 1; i > 0; i--) {
|
||||
final m = listData[i];
|
||||
final info = m["[browser][info] "];
|
||||
if (info is String) {
|
||||
String installPath = "";
|
||||
if (info.contains("Installing Star Citizen $v")) {
|
||||
installPath = "${info.split(" at ")[1]}\\$v";
|
||||
}
|
||||
if (info.contains("Launching Star Citizen $v from")) {
|
||||
installPath = info
|
||||
.replaceAll("Launching Star Citizen $v from (", "")
|
||||
.replaceAll(")", "");
|
||||
}
|
||||
if (installPath.isNotEmpty && !scInstallPaths.contains(installPath)) {
|
||||
if (!checkExists) {
|
||||
dPrint("find installPath == $installPath");
|
||||
scInstallPaths.add(installPath);
|
||||
} else if (await File("$installPath/Bin64/StarCitizen.exe")
|
||||
.exists()) {
|
||||
dPrint("find installPath == $installPath");
|
||||
scInstallPaths.add(installPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scInstallPaths;
|
||||
}
|
||||
}
|
173
lib/common/helper/system_helper.dart
Normal file
173
lib/common/helper/system_helper.dart
Normal file
@ -0,0 +1,173 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:starcitizen_doctor/common/utils/base_utils.dart';
|
||||
|
||||
class SystemHelper {
|
||||
static Future<bool> checkNvmePatchStatus() async {
|
||||
try {
|
||||
var result = await Process.run('powershell.exe', [
|
||||
"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;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> addNvmePatch() async {
|
||||
var result = await Process.run('powershell.exe', [
|
||||
'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;
|
||||
}
|
||||
|
||||
static doRemoveNvmePath() async {
|
||||
try {
|
||||
var result = await Process.run('powershell.exe', [
|
||||
"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;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取 RSI 启动器 目录
|
||||
static Future<String> getRSILauncherPath() async {
|
||||
Map<String, String> envVars = Platform.environment;
|
||||
final programDataPath = envVars["programdata"];
|
||||
final rsiFilePath =
|
||||
"$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("powershell.exe", [
|
||||
"(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");
|
||||
return "${start[0]}RSI Launcher.exe";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static killRSILauncher() async {
|
||||
var psr = await Process.run(
|
||||
"powershell", ["ps", "\"RSI Launcher\"", "|select -expand id"]);
|
||||
if (psr.stderr == "") {
|
||||
for (var value in (psr.stdout ?? "").toString().split("\n")) {
|
||||
dPrint(value);
|
||||
if (value != "") {
|
||||
Process.killPid(int.parse(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Future<List<String>> getPID(String name) async {
|
||||
final r = await Process.run("powershell", ["(ps $name).Id"]);
|
||||
return r.stdout.toString().trim().split("\n");
|
||||
}
|
||||
|
||||
static checkAndLaunchRSILauncher(String path) async {
|
||||
// check running and kill
|
||||
await killRSILauncher();
|
||||
// launch
|
||||
final r = await Process.run("powershell", ["start", "\"$path\""]);
|
||||
dPrint(path);
|
||||
dPrint(r.stdout);
|
||||
dPrint(r.stderr);
|
||||
}
|
||||
|
||||
static Future<int> getSystemMemorySizeGB() async {
|
||||
final r = await Process.run("powershell", [
|
||||
"(Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb"
|
||||
]);
|
||||
return int.tryParse(r.stdout.toString().trim()) ?? 0;
|
||||
}
|
||||
|
||||
static Future<String> getSystemCimInstance(String win32InstanceName,
|
||||
{pathName = "Name"}) async {
|
||||
final r = await Process.run(
|
||||
"powershell", ["(Get-CimInstance $win32InstanceName).$pathName"]);
|
||||
return r.stdout.toString().trim();
|
||||
}
|
||||
|
||||
static Future<String> getSystemName() async {
|
||||
final r = await Process.run(
|
||||
"powershell", ["(Get-ComputerInfo | Select-Object -expand OsName)"]);
|
||||
return r.stdout.toString().trim();
|
||||
}
|
||||
|
||||
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("powershell", [cmd]);
|
||||
return r.stdout.toString().trim();
|
||||
}
|
||||
|
||||
static Future<String> getDiskInfo() async {
|
||||
return (await Process.run("powershell",
|
||||
["Get-PhysicalDisk | format-table BusType,FriendlyName,Size"]))
|
||||
.stdout
|
||||
.toString()
|
||||
.trim();
|
||||
}
|
||||
|
||||
static Future<int> getDirLen(String path, {List<String>? skipPath}) async {
|
||||
if (path == "") return 0;
|
||||
int totalSize = 0;
|
||||
try {
|
||||
final l = await Directory(path).list(recursive: true).toList();
|
||||
for (var element in l) {
|
||||
if (element is File) {
|
||||
bool skip = false;
|
||||
if (skipPath != null) {
|
||||
for (var value in skipPath) {
|
||||
if (element.absolute.path.startsWith(value)) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!skip) totalSize += await element.length();
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
return totalSize;
|
||||
}
|
||||
}
|
95
lib/common/utils/base_utils.dart
Normal file
95
lib/common/utils/base_utils.dart
Normal file
@ -0,0 +1,95 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
void dPrint(src) {
|
||||
if (kDebugMode) {
|
||||
print(src);
|
||||
}
|
||||
}
|
||||
|
||||
Future showToast(BuildContext context, String msg,
|
||||
{BoxConstraints? constraints}) async {
|
||||
return showBaseDialog(context,
|
||||
title: "提示",
|
||||
content: Text(msg),
|
||||
actions: [
|
||||
FilledButton(
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(top: 2, bottom: 2, left: 8, right: 8),
|
||||
child: Text('关闭'),
|
||||
),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
],
|
||||
constraints: constraints);
|
||||
}
|
||||
|
||||
Future<bool> showConfirmDialogs(
|
||||
BuildContext context, String title, Widget content,
|
||||
{String confirm = "确认",
|
||||
String cancel = "取消",
|
||||
BoxConstraints? constraints}) async {
|
||||
final r = await showBaseDialog(context,
|
||||
title: title,
|
||||
content: content,
|
||||
actions: [
|
||||
if (confirm.isNotEmpty)
|
||||
FilledButton(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 2, bottom: 2, left: 8, right: 8),
|
||||
child: Text(confirm),
|
||||
),
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
),
|
||||
if (cancel.isNotEmpty)
|
||||
Button(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 2, bottom: 2, left: 8, right: 8),
|
||||
child: Text(cancel),
|
||||
),
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
),
|
||||
],
|
||||
constraints: constraints);
|
||||
return r == true;
|
||||
}
|
||||
|
||||
Future showBaseDialog(BuildContext context,
|
||||
{required String title,
|
||||
required Widget content,
|
||||
List<Widget>? actions,
|
||||
BoxConstraints? constraints}) async {
|
||||
return await showDialog(
|
||||
context: context,
|
||||
builder: (context) => ContentDialog(
|
||||
title: Text(title),
|
||||
content: content,
|
||||
constraints: constraints ?? kDefaultContentDialogConstraints,
|
||||
actions: actions,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool stringIsNotEmpty(String? s) {
|
||||
return s != null && (s.isNotEmpty);
|
||||
}
|
||||
|
||||
Future<Uint8List?> widgetToPngImage(GlobalKey repaintBoundaryKey,
|
||||
{double pixelRatio = 3.0}) async {
|
||||
RenderRepaintBoundary? boundary = repaintBoundaryKey.currentContext
|
||||
?.findRenderObject() as RenderRepaintBoundary?;
|
||||
if (boundary == null) return null;
|
||||
|
||||
ui.Image image = await boundary.toImage(pixelRatio: pixelRatio);
|
||||
ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
||||
if (byteData == null) return null;
|
||||
var pngBytes = byteData.buffer.asUint8List();
|
||||
return pngBytes;
|
||||
}
|
||||
|
||||
double roundDoubleTo(double value, double precision) =>
|
||||
(value * precision).round() / precision;
|
Reference in New Issue
Block a user