mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-01-13 19:50:28 +00:00
feat: linux support
This commit is contained in:
parent
66ead87d47
commit
bba2dbd360
@ -8,7 +8,15 @@ import 'package:starcitizen_doctor/common/utils/log.dart';
|
|||||||
|
|
||||||
class SCLoggerHelper {
|
class SCLoggerHelper {
|
||||||
static Future<String?> getLogFilePath() async {
|
static Future<String?> getLogFilePath() async {
|
||||||
if (!Platform.isWindows) return null;
|
if (!Platform.isWindows) {
|
||||||
|
final wineUserPath = await getWineUserPath();
|
||||||
|
if (wineUserPath == null) return null;
|
||||||
|
// /home/xkeyc/Games/star-citizen/drive_c/users/xkeyc/AppData/Roaming/rsilauncher/
|
||||||
|
final rsiLauncherPath = "$wineUserPath/AppData/Roaming/rsilauncher";
|
||||||
|
dPrint("rsiLauncherPath Wine:$rsiLauncherPath");
|
||||||
|
final jsonLogPath = "$rsiLauncherPath/logs/log.log";
|
||||||
|
return jsonLogPath;
|
||||||
|
};
|
||||||
Map<String, String> envVars = Platform.environment;
|
Map<String, String> envVars = Platform.environment;
|
||||||
final appDataPath = envVars["appdata"];
|
final appDataPath = envVars["appdata"];
|
||||||
if (appDataPath == null) {
|
if (appDataPath == null) {
|
||||||
@ -21,6 +29,14 @@ class SCLoggerHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<String?> getShaderCachePath() async {
|
static Future<String?> getShaderCachePath() async {
|
||||||
|
if (!Platform.isWindows) {
|
||||||
|
final wineUserPath = await getWineUserPath();
|
||||||
|
if (wineUserPath == null) return null;
|
||||||
|
// /home/xkeyc/Games/star-citizen/drive_c/users/xkeyc/AppData/Local/star citizen/
|
||||||
|
final scCachePath = "$wineUserPath/AppData/Local/star citizen";
|
||||||
|
dPrint("getShaderCachePath Wine === $scCachePath");
|
||||||
|
return scCachePath;
|
||||||
|
}
|
||||||
Map<String, String> envVars = Platform.environment;
|
Map<String, String> envVars = Platform.environment;
|
||||||
final appDataPath = envVars["LOCALAPPDATA"];
|
final appDataPath = envVars["LOCALAPPDATA"];
|
||||||
if (appDataPath == null) {
|
if (appDataPath == null) {
|
||||||
@ -31,6 +47,23 @@ class SCLoggerHelper {
|
|||||||
return scCachePath;
|
return scCachePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<String?> getWineUserPath() async {
|
||||||
|
// get game path in hiveBox
|
||||||
|
final confBox = await Hive.openBox("app_conf");
|
||||||
|
final path = confBox.get("custom_game_path");
|
||||||
|
if (path?.isEmpty ?? true) return null;
|
||||||
|
// path eg: /home/xkeyc/Games/star-citizen/drive_c/Program Files/Roberts Space Industries/StarCitizen/LIVE/
|
||||||
|
// resolve wine c_drive path
|
||||||
|
final wineCDrivePath = path.toString().split('/drive_c/').first;
|
||||||
|
// scan wine user path == current_unix_user
|
||||||
|
final wineUserPath = "$wineCDrivePath/drive_c/users/${Platform.environment['USER']}";
|
||||||
|
// check exists
|
||||||
|
final wineUserDir = Directory(wineUserPath);
|
||||||
|
if (!await wineUserDir.exists()) return null;
|
||||||
|
dPrint("getWineUserPath === $wineUserPath");
|
||||||
|
return wineUserPath;
|
||||||
|
}
|
||||||
|
|
||||||
static Future<List?> getLauncherLogList() async {
|
static Future<List?> getLauncherLogList() async {
|
||||||
if (!Platform.isWindows) return [];
|
if (!Platform.isWindows) return [];
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:hive_ce/hive.dart';
|
import 'package:hive_ce/hive.dart';
|
||||||
|
import 'package:starcitizen_doctor/common/utils/base_utils.dart';
|
||||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||||
import 'package:starcitizen_doctor/common/rust/api/win32_api.dart' as win32;
|
import 'package:starcitizen_doctor/common/rust/api/win32_api.dart' as win32;
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ class SystemHelper {
|
|||||||
if (path != null && path != "") {
|
if (path != null && path != "") {
|
||||||
if (await File(path).exists()) {
|
if (await File(path).exists()) {
|
||||||
if (skipEXE) {
|
if (skipEXE) {
|
||||||
return "${path.toString().replaceAll("\\RSI Launcher.exe", "")}\\";
|
return "${path.toString().replaceAll("\\RSI Launcher.exe".platformPath, "")}\\".platformPath;
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
import 'package:fluent_ui/fluent_ui.dart';
|
||||||
@ -112,7 +113,7 @@ class MultiWindowManager {
|
|||||||
|
|
||||||
await Window.initialize();
|
await Window.initialize();
|
||||||
|
|
||||||
if (windowAppState.windowsVersion >= 10) {
|
if (Platform.isWindows && windowAppState.windowsVersion >= 10) {
|
||||||
await Window.setEffect(effect: WindowEffect.acrylic);
|
await Window.setEffect(effect: WindowEffect.acrylic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import 'package:path_provider/path_provider.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:starcitizen_doctor/api/analytics.dart';
|
import 'package:starcitizen_doctor/api/analytics.dart';
|
||||||
import 'package:starcitizen_doctor/common/helper/log_helper.dart';
|
import 'package:starcitizen_doctor/common/helper/log_helper.dart';
|
||||||
|
import 'package:starcitizen_doctor/common/utils/base_utils.dart';
|
||||||
import 'package:starcitizen_doctor/common/utils/log.dart';
|
import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||||
import 'package:starcitizen_doctor/data/app_unp4k_p4k_item_data.dart';
|
import 'package:starcitizen_doctor/data/app_unp4k_p4k_item_data.dart';
|
||||||
import 'package:starcitizen_doctor/ui/tools/tools_ui_model.dart';
|
import 'package:starcitizen_doctor/ui/tools/tools_ui_model.dart';
|
||||||
@ -80,7 +81,7 @@ class Unp4kCModel extends _$Unp4kCModel {
|
|||||||
|
|
||||||
void _init() async {
|
void _init() async {
|
||||||
final gamePath = getGamePath();
|
final gamePath = getGamePath();
|
||||||
final gameP4kPath = "$gamePath\\Data.p4k";
|
final gameP4kPath = "$gamePath\\Data.p4k".platformPath;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
state = state.copyWith(endMessage: S.current.tools_unp4k_msg_reading);
|
state = state.copyWith(endMessage: S.current.tools_unp4k_msg_reading);
|
||||||
|
|||||||
@ -30,13 +30,9 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
return ContentDialog(
|
return ContentDialog(
|
||||||
title: makeTitle(context, model, state),
|
title: makeTitle(context, model, state),
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxWidth: MediaQuery
|
maxWidth: MediaQuery.of(context).size.width * .7,
|
||||||
.of(context)
|
minHeight: MediaQuery.of(context).size.height * .9,
|
||||||
.size
|
),
|
||||||
.width * .7, minHeight: MediaQuery
|
|
||||||
.of(context)
|
|
||||||
.size
|
|
||||||
.height * .9),
|
|
||||||
content: Padding(
|
content: Padding(
|
||||||
padding: const EdgeInsets.only(left: 12, right: 12, top: 12),
|
padding: const EdgeInsets.only(left: 12, right: 12, top: 12),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
@ -44,132 +40,128 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
AnimatedSize(
|
AnimatedSize(
|
||||||
duration: const Duration(milliseconds: 130),
|
duration: const Duration(milliseconds: 130),
|
||||||
child: state.patchStatus?.key == true &&
|
child:
|
||||||
state.patchStatus?.value == S.current.home_action_info_game_built_in
|
state.patchStatus?.key == true &&
|
||||||
|
state.patchStatus?.value == S.current.home_action_info_game_built_in
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 12),
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
child: InfoBar(
|
child: InfoBar(
|
||||||
title: Text(S.current.home_action_info_warning),
|
title: Text(S.current.home_action_info_warning),
|
||||||
content: Text(S.current.localization_info_machine_translation_warning),
|
content: Text(S.current.localization_info_machine_translation_warning),
|
||||||
severity: InfoBarSeverity.info,
|
severity: InfoBarSeverity.info,
|
||||||
style: InfoBarThemeData(decoration: (severity) {
|
style: InfoBarThemeData(
|
||||||
return const BoxDecoration(color: Color.fromRGBO(155, 7, 7, 1.0));
|
decoration: (severity) {
|
||||||
}, iconColor: (severity) {
|
return const BoxDecoration(color: Color.fromRGBO(155, 7, 7, 1.0));
|
||||||
return Colors.white;
|
},
|
||||||
}),
|
iconColor: (severity) {
|
||||||
),
|
return Colors.white;
|
||||||
)
|
},
|
||||||
: SizedBox(
|
),
|
||||||
width: MediaQuery
|
),
|
||||||
.of(context)
|
)
|
||||||
.size
|
: SizedBox(width: MediaQuery.of(context).size.width),
|
||||||
.width,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
makeToolsListContainer(context, model, state),
|
makeToolsListContainer(context, model, state),
|
||||||
makeListContainer(
|
makeListContainer(S.current.localization_info_translation, [
|
||||||
S.current.localization_info_translation,
|
if (state.patchStatus == null)
|
||||||
[
|
makeLoading(context)
|
||||||
if (state.patchStatus == null)
|
else ...[
|
||||||
makeLoading(context)
|
const SizedBox(height: 6),
|
||||||
else
|
Row(
|
||||||
...[
|
children: [
|
||||||
const SizedBox(height: 6),
|
Center(
|
||||||
Row(
|
child: Text(
|
||||||
children: [
|
S.current.localization_info_enabled(
|
||||||
Center(
|
LocalizationUIModel.languageSupport[state.selectedLanguage] ?? "",
|
||||||
child: Text(S.current.localization_info_enabled(
|
),
|
||||||
LocalizationUIModel.languageSupport[state.selectedLanguage] ?? "")),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
ToggleSwitch(
|
|
||||||
checked: state.patchStatus?.key == true,
|
|
||||||
onChanged: model.updateLangCfg,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
),
|
||||||
Row(
|
const Spacer(),
|
||||||
|
ToggleSwitch(checked: state.patchStatus?.key == true, onChanged: model.updateLangCfg),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Text(
|
||||||
child: Row(
|
S.current.localization_info_installed_version(
|
||||||
children: [
|
"${state.patchStatus?.value ?? ""} ${(state.isInstalledAdvanced ?? false) ? S.current.home_localization_msg_version_advanced : ""}",
|
||||||
Text(S.current.localization_info_installed_version(
|
|
||||||
"${state.patchStatus?.value ?? ""} ${(state.isInstalledAdvanced ?? false) ? S
|
|
||||||
.current.home_localization_msg_version_advanced : ""}")),
|
|
||||||
SizedBox(width: 24),
|
|
||||||
if (state.installedCommunityInputMethodSupportVersion != null)
|
|
||||||
Text(
|
|
||||||
S.current.input_method_community_input_method_support_version(
|
|
||||||
state.installedCommunityInputMethodSupportVersion ?? "?"),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (state.patchStatus?.value != S.current.home_action_info_game_built_in)
|
SizedBox(width: 24),
|
||||||
Row(
|
if (state.installedCommunityInputMethodSupportVersion != null)
|
||||||
children: [
|
Text(
|
||||||
Button(
|
S.current.input_method_community_input_method_support_version(
|
||||||
onPressed: model.goFeedback,
|
state.installedCommunityInputMethodSupportVersion ?? "?",
|
||||||
child: Padding(
|
),
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(FluentIcons.feedback),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
Text(S.current.localization_action_translation_feedback),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Button(
|
|
||||||
onPressed: model.doDelIniFile(),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(FluentIcons.delete),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
Text(S.current.localization_action_uninstall_translation),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
),
|
||||||
Container(
|
if (state.patchStatus?.value != S.current.home_action_info_game_built_in)
|
||||||
color: Colors.white.withValues(alpha: .1),
|
Row(
|
||||||
height: 1,
|
children: [
|
||||||
),
|
Button(
|
||||||
const SizedBox(height: 12),
|
onPressed: model.goFeedback,
|
||||||
if (state.apiLocalizationData == null)
|
child: Padding(
|
||||||
makeLoading(context)
|
padding: const EdgeInsets.all(4),
|
||||||
else
|
child: Row(
|
||||||
if (state.apiLocalizationData!.isEmpty)
|
children: [
|
||||||
Center(
|
const Icon(FluentIcons.feedback),
|
||||||
child: Text(
|
const SizedBox(width: 6),
|
||||||
S.current.localization_info_no_translation_available,
|
Text(S.current.localization_action_translation_feedback),
|
||||||
style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: .8)),
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
else
|
const SizedBox(width: 16),
|
||||||
AlignedGridView.count(
|
Button(
|
||||||
crossAxisCount: 2,
|
onPressed: model.doDelIniFile(),
|
||||||
crossAxisSpacing: 12,
|
child: Padding(
|
||||||
mainAxisSpacing: 12,
|
padding: const EdgeInsets.all(4),
|
||||||
itemBuilder: (BuildContext context, int index) {
|
child: Row(
|
||||||
final item = state.apiLocalizationData!.entries.elementAt(index);
|
children: [
|
||||||
return makeRemoteList(context, model, item, state, index);
|
const Icon(FluentIcons.delete),
|
||||||
},
|
const SizedBox(width: 6),
|
||||||
shrinkWrap: true,
|
Text(S.current.localization_action_uninstall_translation),
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
],
|
||||||
itemCount: state.apiLocalizationData?.length ?? 0,
|
),
|
||||||
)
|
),
|
||||||
],
|
),
|
||||||
],
|
],
|
||||||
context),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Container(color: Colors.white.withValues(alpha: .1), height: 1),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
if (state.apiLocalizationData == null)
|
||||||
|
makeLoading(context)
|
||||||
|
else if (state.apiLocalizationData!.isEmpty)
|
||||||
|
Center(
|
||||||
|
child: Text(
|
||||||
|
S.current.localization_info_no_translation_available,
|
||||||
|
style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: .8)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
AlignedGridView.count(
|
||||||
|
crossAxisCount: 2,
|
||||||
|
crossAxisSpacing: 12,
|
||||||
|
mainAxisSpacing: 12,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final item = state.apiLocalizationData!.entries.elementAt(index);
|
||||||
|
return makeRemoteList(context, model, item, state, index);
|
||||||
|
},
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemCount: state.apiLocalizationData?.length ?? 0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
], context),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -177,8 +169,13 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget makeRemoteList(BuildContext context, LocalizationUIModel model, MapEntry<String, ScLocalizationData> item,
|
Widget makeRemoteList(
|
||||||
LocalizationUIState state, int index) {
|
BuildContext context,
|
||||||
|
LocalizationUIModel model,
|
||||||
|
MapEntry<String, ScLocalizationData> item,
|
||||||
|
LocalizationUIState state,
|
||||||
|
int index,
|
||||||
|
) {
|
||||||
final isWorking = state.workingVersion.isNotEmpty;
|
final isWorking = state.workingVersion.isNotEmpty;
|
||||||
final isMineWorking = state.workingVersion == item.key;
|
final isMineWorking = state.workingVersion == item.key;
|
||||||
final isInstalled = state.patchStatus?.value == item.key;
|
final isInstalled = state.patchStatus?.value == item.key;
|
||||||
@ -207,10 +204,7 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text("${item.value.info}", style: const TextStyle(fontSize: 19)),
|
||||||
"${item.value.info}",
|
|
||||||
style: const TextStyle(fontSize: 19),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
S.current.localization_info_version_number(item.value.versionName ?? ""),
|
S.current.localization_info_version_number(item.value.versionName ?? ""),
|
||||||
@ -230,40 +224,30 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isMineWorking)
|
if (isMineWorking)
|
||||||
const Padding(
|
const Padding(padding: EdgeInsets.only(right: 12), child: ProgressRing())
|
||||||
padding: EdgeInsets.only(right: 12),
|
else ...[
|
||||||
child: ProgressRing(),
|
Icon(
|
||||||
)
|
isInstalled
|
||||||
else
|
? FluentIcons.check_mark
|
||||||
...[
|
: isItemEnabled
|
||||||
Icon(
|
? FluentIcons.download
|
||||||
isInstalled
|
: FluentIcons.disable_updates,
|
||||||
? FluentIcons.check_mark
|
color: Colors.white.withValues(alpha: .8),
|
||||||
: isItemEnabled
|
size: 18,
|
||||||
? FluentIcons.download
|
),
|
||||||
: FluentIcons.disable_updates,
|
const SizedBox(width: 6),
|
||||||
color: Colors.white.withValues(alpha: .8),
|
Text(
|
||||||
size: 18,
|
isInstalled
|
||||||
),
|
? S.current.localization_info_installed
|
||||||
const SizedBox(width: 6),
|
: (isItemEnabled
|
||||||
Text(
|
? S.current.localization_action_install
|
||||||
isInstalled
|
: S.current.localization_info_unavailable),
|
||||||
? S.current.localization_info_installed
|
style: TextStyle(color: Colors.white.withValues(alpha: .8)),
|
||||||
: (isItemEnabled
|
),
|
||||||
? S.current.localization_action_install
|
const SizedBox(width: 6),
|
||||||
: S.current.localization_info_unavailable),
|
if ((!isInstalled) && isItemEnabled)
|
||||||
style: TextStyle(
|
Icon(FluentIcons.chevron_right, size: 14, color: Colors.white.withValues(alpha: .6)),
|
||||||
color: Colors.white.withValues(alpha: .8),
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
if ((!isInstalled) && isItemEnabled)
|
|
||||||
Icon(
|
|
||||||
FluentIcons.chevron_right,
|
|
||||||
size: 14,
|
|
||||||
color: Colors.white.withValues(alpha: .6),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (item.value.note != null) ...[
|
if (item.value.note != null) ...[
|
||||||
@ -272,10 +256,7 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
"${item.value.note}",
|
"${item.value.note}",
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(color: Colors.white.withValues(alpha: .4), fontSize: 13),
|
||||||
color: Colors.white.withValues(alpha: .4),
|
|
||||||
fontSize: 13,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@ -286,16 +267,20 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget makeListContainer(String title, List<Widget> children, BuildContext context,
|
Widget makeListContainer(
|
||||||
{List<Widget> actions = const [], bool gridViewMode = false, int gridViewCrossAxisCount = 2}) {
|
String title,
|
||||||
|
List<Widget> children,
|
||||||
|
BuildContext context, {
|
||||||
|
List<Widget> actions = const [],
|
||||||
|
bool gridViewMode = false,
|
||||||
|
int gridViewCrossAxisCount = 2,
|
||||||
|
}) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 12),
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
child: AnimatedSize(
|
child: AnimatedSize(
|
||||||
duration: const Duration(milliseconds: 130),
|
duration: const Duration(milliseconds: 130),
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(color: FluentTheme
|
decoration: BoxDecoration(color: FluentTheme.of(context).cardColor, borderRadius: BorderRadius.circular(7)),
|
||||||
.of(context)
|
|
||||||
.cardColor, borderRadius: BorderRadius.circular(7)),
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(top: 12, bottom: 12, left: 24, right: 24),
|
padding: const EdgeInsets.only(top: 12, bottom: 12, left: 24, right: 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -303,21 +288,13 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(title, style: const TextStyle(fontSize: 22)),
|
||||||
title,
|
|
||||||
style: const TextStyle(fontSize: 22),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
if (actions.isNotEmpty) ...actions,
|
if (actions.isNotEmpty) ...actions,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(height: 6),
|
||||||
height: 6,
|
Container(color: Colors.white.withValues(alpha: .1), height: 1),
|
||||||
),
|
|
||||||
Container(
|
|
||||||
color: Colors.white.withValues(alpha: .1),
|
|
||||||
height: 1,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
if (gridViewMode)
|
if (gridViewMode)
|
||||||
AlignedGridView.count(
|
AlignedGridView.count(
|
||||||
@ -332,7 +309,7 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
itemCount: children.length,
|
itemCount: children.length,
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
...children
|
...children,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -344,55 +321,46 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
Widget makeTitle(BuildContext context, LocalizationUIModel model, LocalizationUIState state) {
|
Widget makeTitle(BuildContext context, LocalizationUIModel model, LocalizationUIState state) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(icon: const Icon(FluentIcons.back, size: 22), onPressed: model.onBack(context)),
|
||||||
icon: const Icon(
|
|
||||||
FluentIcons.back,
|
|
||||||
size: 22,
|
|
||||||
),
|
|
||||||
onPressed: model.onBack(context)),
|
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Text(S.current.home_action_localization_management),
|
Text(S.current.home_action_localization_management),
|
||||||
const SizedBox(width: 24),
|
const SizedBox(width: 24),
|
||||||
Text(
|
Expanded(
|
||||||
"${model.getScInstallPath()}",
|
child: Text(
|
||||||
style: const TextStyle(fontSize: 13),
|
"${model.getScInstallPath()}",
|
||||||
|
style: const TextStyle(fontSize: 13),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
SizedBox(width: 24),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 36,
|
height: 36,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(S.current.localization_info_language, style: const TextStyle(fontSize: 16)),
|
||||||
S.current.localization_info_language,
|
|
||||||
style: const TextStyle(fontSize: 16),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
ComboBox<String>(
|
ComboBox<String>(
|
||||||
value: state.selectedLanguage,
|
value: state.selectedLanguage,
|
||||||
items: [
|
items: [
|
||||||
for (final lang in LocalizationUIModel.languageSupport.entries)
|
for (final lang in LocalizationUIModel.languageSupport.entries)
|
||||||
ComboBoxItem(
|
ComboBoxItem(value: lang.key, child: Text(lang.value)),
|
||||||
value: lang.key,
|
|
||||||
child: Text(lang.value),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
onChanged: state.workingVersion.isNotEmpty
|
onChanged: state.workingVersion.isNotEmpty
|
||||||
? null
|
? null
|
||||||
: (v) {
|
: (v) {
|
||||||
if (v == null) return;
|
if (v == null) return;
|
||||||
model.selectLang(v);
|
model.selectLang(v);
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Button(
|
Button(
|
||||||
onPressed: model.doRefresh(),
|
onPressed: model.doRefresh(),
|
||||||
child: const Padding(
|
child: const Padding(padding: EdgeInsets.all(6), child: Icon(FluentIcons.refresh)),
|
||||||
padding: EdgeInsets.all(6),
|
),
|
||||||
child: Icon(FluentIcons.refresh),
|
|
||||||
)),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -400,85 +368,77 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
|||||||
Widget makeToolsListContainer(BuildContext context, LocalizationUIModel model, LocalizationUIState state) {
|
Widget makeToolsListContainer(BuildContext context, LocalizationUIModel model, LocalizationUIState state) {
|
||||||
final toolsMenu = {
|
final toolsMenu = {
|
||||||
"launcher_mod": (
|
"launcher_mod": (
|
||||||
const Icon(FluentIcons.c_plus_plus, size: 24),
|
const Icon(FluentIcons.c_plus_plus, size: 24),
|
||||||
(S.current.home_localization_action_rsi_launcher_localization),
|
(S.current.home_localization_action_rsi_launcher_localization),
|
||||||
),
|
|
||||||
"advanced": (
|
|
||||||
const Icon(FluentIcons.queue_advanced, size: 24),
|
|
||||||
(S.current.home_localization_action_advanced),
|
|
||||||
),
|
),
|
||||||
|
"advanced": (const Icon(FluentIcons.queue_advanced, size: 24), (S.current.home_localization_action_advanced)),
|
||||||
"custom_files": (
|
"custom_files": (
|
||||||
const Icon(FluentIcons.custom_activity, size: 24),
|
const Icon(FluentIcons.custom_activity, size: 24),
|
||||||
(S.current.home_localization_action_install_customize),
|
(S.current.home_localization_action_install_customize),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
final enableTap = state.workingVersion.isEmpty;
|
final enableTap = state.workingVersion.isEmpty;
|
||||||
|
|
||||||
return makeListContainer(
|
return makeListContainer(
|
||||||
S.current.home_localization_title_localization_tools,
|
S.current.home_localization_title_localization_tools,
|
||||||
[
|
[
|
||||||
for (final item in toolsMenu.entries)
|
for (final item in toolsMenu.entries)
|
||||||
Tilt(
|
Tilt(
|
||||||
disable: !enableTap,
|
disable: !enableTap,
|
||||||
shadowConfig: const ShadowConfig(maxIntensity: .3),
|
shadowConfig: const ShadowConfig(maxIntensity: .3),
|
||||||
borderRadius: BorderRadius.circular(7),
|
borderRadius: BorderRadius.circular(7),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: enableTap
|
onTap: enableTap
|
||||||
? () async {
|
? () async {
|
||||||
switch (item.key) {
|
switch (item.key) {
|
||||||
case "launcher_mod":
|
case "launcher_mod":
|
||||||
ToolsUIModel.rsiEnhance(context);
|
ToolsUIModel.rsiEnhance(context);
|
||||||
break;
|
break;
|
||||||
case "advanced":
|
case "advanced":
|
||||||
context.push("/index/advanced_localization");
|
context.push("/index/advanced_localization");
|
||||||
break;
|
break;
|
||||||
case "custom_files":
|
case "custom_files":
|
||||||
final sb = await showDialog(
|
final sb = await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) => const LocalizationFromFileDialogUI(),
|
builder: (BuildContext context) => const LocalizationFromFileDialogUI(),
|
||||||
);
|
);
|
||||||
if (sb is (StringBuffer, bool)) {
|
if (sb is (StringBuffer, bool)) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
await model.installFormString(
|
await model.installFormString(
|
||||||
sb.$1,
|
sb.$1,
|
||||||
S.current.localization_info_custom_files,
|
S.current.localization_info_custom_files,
|
||||||
isEnableCommunityInputMethod: sb.$2,
|
isEnableCommunityInputMethod: sb.$2,
|
||||||
context: context,
|
context: context,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
: null,
|
||||||
}
|
child: Container(
|
||||||
: null,
|
decoration: BoxDecoration(
|
||||||
child: Container(
|
color: FluentTheme.of(context).cardColor,
|
||||||
decoration: BoxDecoration(
|
borderRadius: BorderRadius.circular(7),
|
||||||
color: FluentTheme
|
),
|
||||||
.of(context)
|
padding: const EdgeInsets.all(12),
|
||||||
.cardColor,
|
child: Row(
|
||||||
borderRadius: BorderRadius.circular(7),
|
children: [
|
||||||
),
|
item.value.$1,
|
||||||
padding: const EdgeInsets.all(12),
|
const SizedBox(width: 12),
|
||||||
child: Row(
|
Text(item.value.$2),
|
||||||
children: [
|
const SizedBox(width: 12),
|
||||||
item.value.$1,
|
const Spacer(),
|
||||||
const SizedBox(width: 12),
|
Icon(FluentIcons.chevron_right, size: 14, color: Colors.white.withValues(alpha: .6)),
|
||||||
Text(item.value.$2),
|
],
|
||||||
const SizedBox(width: 12),
|
|
||||||
const Spacer(),
|
|
||||||
Icon(
|
|
||||||
FluentIcons.chevron_right,
|
|
||||||
size: 14,
|
|
||||||
color: Colors.white.withValues(alpha: .6),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
context,
|
],
|
||||||
gridViewMode: true,
|
context,
|
||||||
gridViewCrossAxisCount: 3);
|
gridViewMode: true,
|
||||||
|
gridViewCrossAxisCount: 3,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,13 +48,12 @@ abstract class LocalizationUIState with _$LocalizationUIState {
|
|||||||
class LocalizationUIModel extends _$LocalizationUIModel {
|
class LocalizationUIModel extends _$LocalizationUIModel {
|
||||||
static const languageSupport = {"chinese_(simplified)": NoL10n.langZHS, "chinese_(traditional)": NoL10n.langZHT};
|
static const languageSupport = {"chinese_(simplified)": NoL10n.langZHS, "chinese_(traditional)": NoL10n.langZHT};
|
||||||
|
|
||||||
Directory get _downloadDir => Directory("${appGlobalState.applicationSupportDir}\\Localizations");
|
Directory get _downloadDir => Directory("${appGlobalState.applicationSupportDir}\\Localizations".platformPath);
|
||||||
|
|
||||||
Directory getDownloadDir() => _downloadDir;
|
Directory getDownloadDir() => _downloadDir;
|
||||||
|
|
||||||
Directory get _scDataDir => Directory("${ref.read(homeUIModelProvider).scInstalledPath}\\data");
|
Directory get _scDataDir => Directory("${ref.read(homeUIModelProvider).scInstalledPath}\\data".platformPath);
|
||||||
|
File get _cfgFile => File("${_scDataDir.absolute.path}\\system.cfg".platformPath);
|
||||||
File get _cfgFile => File("${_scDataDir.absolute.path}\\system.cfg");
|
|
||||||
|
|
||||||
StreamSubscription? _customizeDirListenSub;
|
StreamSubscription? _customizeDirListenSub;
|
||||||
|
|
||||||
@ -155,7 +154,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void checkUserCfg(BuildContext context) async {
|
void checkUserCfg(BuildContext context) async {
|
||||||
final userCfgFile = File("$_scInstallPath\\USER.cfg");
|
final userCfgFile = File("$_scInstallPath\\USER.cfg".platformPath);
|
||||||
if (await userCfgFile.exists()) {
|
if (await userCfgFile.exists()) {
|
||||||
final cfgString = await userCfgFile.readAsString();
|
final cfgString = await userCfgFile.readAsString();
|
||||||
if (cfgString.contains("g_language") && !cfgString.contains("g_language=${state.selectedLanguage}")) {
|
if (cfgString.contains("g_language") && !cfgString.contains("g_language=${state.selectedLanguage}")) {
|
||||||
@ -241,7 +240,9 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
|
|
||||||
VoidCallback? doDelIniFile() {
|
VoidCallback? doDelIniFile() {
|
||||||
return () async {
|
return () async {
|
||||||
final iniFile = File("${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini");
|
final iniFile = File(
|
||||||
|
"${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini".platformPath,
|
||||||
|
);
|
||||||
if (await iniFile.exists()) await iniFile.delete();
|
if (await iniFile.exists()) await iniFile.delete();
|
||||||
await updateLangCfg(false);
|
await updateLangCfg(false);
|
||||||
await _updateStatus();
|
await _updateStatus();
|
||||||
@ -249,7 +250,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getCustomizeFileName(String path) {
|
String getCustomizeFileName(String path) {
|
||||||
return path.split("\\").last;
|
return path.split("\\".platformPath).last;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> installFormString(
|
Future<void> installFormString(
|
||||||
@ -261,7 +262,9 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
BuildContext? context,
|
BuildContext? context,
|
||||||
}) async {
|
}) async {
|
||||||
dPrint("LocalizationUIModel -> installFormString $versionName");
|
dPrint("LocalizationUIModel -> installFormString $versionName");
|
||||||
final iniFile = File("${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini");
|
final iniFile = File(
|
||||||
|
"${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini".platformPath,
|
||||||
|
);
|
||||||
if (versionName.isNotEmpty) {
|
if (versionName.isNotEmpty) {
|
||||||
if (!globalIni.toString().endsWith("\n")) {
|
if (!globalIni.toString().endsWith("\n")) {
|
||||||
globalIni.write("\n");
|
globalIni.write("\n");
|
||||||
@ -323,7 +326,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, String>?> getCommunityInputMethodSupportData() async {
|
Future<Map<String, String>?> getCommunityInputMethodSupportData() async {
|
||||||
final iniPath = "${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini";
|
final iniPath = "${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini".platformPath;
|
||||||
final iniFile = File(iniPath);
|
final iniFile = File(iniPath);
|
||||||
if (!await iniFile.exists()) {
|
if (!await iniFile.exists()) {
|
||||||
return {};
|
return {};
|
||||||
@ -351,7 +354,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<(String, String)> getIniContentWithoutCommunityInputMethodSupportData() async {
|
Future<(String, String)> getIniContentWithoutCommunityInputMethodSupportData() async {
|
||||||
final iniPath = "${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini";
|
final iniPath = "${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini".platformPath;
|
||||||
final iniFile = File(iniPath);
|
final iniFile = File(iniPath);
|
||||||
if (!await iniFile.exists()) {
|
if (!await iniFile.exists()) {
|
||||||
return ("", "");
|
return ("", "");
|
||||||
@ -383,7 +386,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
}) async {
|
}) async {
|
||||||
AnalyticsApi.touch("install_localization");
|
AnalyticsApi.touch("install_localization");
|
||||||
|
|
||||||
final savePath = File("${_downloadDir.absolute.path}\\${value.versionName}.sclang");
|
final savePath = File("${_downloadDir.absolute.path}\\${value.versionName}.sclang".platformPath);
|
||||||
try {
|
try {
|
||||||
state = state.copyWith(workingVersion: value.versionName!);
|
state = state.copyWith(workingVersion: value.versionName!);
|
||||||
if (!await savePath.exists()) {
|
if (!await savePath.exists()) {
|
||||||
@ -488,7 +491,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateStatus() async {
|
Future<void> _updateStatus() async {
|
||||||
final iniPath = "${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini";
|
final iniPath = "${_scDataDir.absolute.path}\\Localization\\${state.selectedLanguage}\\global.ini".platformPath;
|
||||||
final patchStatus = MapEntry(
|
final patchStatus = MapEntry(
|
||||||
await _getLangCfgEnableLang(lang: state.selectedLanguage!),
|
await _getLangCfgEnableLang(lang: state.selectedLanguage!),
|
||||||
await _getInstalledIniVersion(iniPath),
|
await _getInstalledIniVersion(iniPath),
|
||||||
@ -535,7 +538,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
if (gamePath.isEmpty) {
|
if (gamePath.isEmpty) {
|
||||||
gamePath = _scInstallPath;
|
gamePath = _scInstallPath;
|
||||||
}
|
}
|
||||||
final cfgFile = File("${_scDataDir.absolute.path}\\system.cfg");
|
final cfgFile = File("${_scDataDir.absolute.path}\\system.cfg".platformPath);
|
||||||
if (!await cfgFile.exists()) return false;
|
if (!await cfgFile.exists()) return false;
|
||||||
final str = (await cfgFile.readAsString()).replaceAll(" ", "");
|
final str = (await cfgFile.readAsString()).replaceAll(" ", "");
|
||||||
return str.contains("sys_languages=$lang") &&
|
return str.contains("sys_languages=$lang") &&
|
||||||
@ -573,13 +576,13 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
|||||||
|
|
||||||
for (var scInstallPath in homeState.scInstallPaths) {
|
for (var scInstallPath in homeState.scInstallPaths) {
|
||||||
// 读取游戏安装文件夹
|
// 读取游戏安装文件夹
|
||||||
final scDataDir = Directory("$scInstallPath\\data\\Localization");
|
final scDataDir = Directory("$scInstallPath\\data\\Localization".platformPath);
|
||||||
// 扫描目录确认已安装的语言
|
// 扫描目录确认已安装的语言
|
||||||
final dirList = await scDataDir.list().toList();
|
final dirList = await scDataDir.list().toList();
|
||||||
for (var element in dirList) {
|
for (var element in dirList) {
|
||||||
for (var lang in languageSupport.keys) {
|
for (var lang in languageSupport.keys) {
|
||||||
if (element.path.contains(lang) && await _getLangCfgEnableLang(lang: lang, gamePath: scInstallPath)) {
|
if (element.path.contains(lang) && await _getLangCfgEnableLang(lang: lang, gamePath: scInstallPath)) {
|
||||||
final installedVersion = await _getInstalledIniVersion("${element.path}\\global.ini");
|
final installedVersion = await _getInstalledIniVersion("${element.path}\\global.ini".platformPath);
|
||||||
if (installedVersion == S.current.home_action_info_game_built_in ||
|
if (installedVersion == S.current.home_action_info_game_built_in ||
|
||||||
installedVersion == S.current.localization_info_custom_files) {
|
installedVersion == S.current.localization_info_custom_files) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -104,11 +104,11 @@ class SettingsUIModel extends _$SettingsUIModel {
|
|||||||
final fileName = r.files.first.path!.platformPath;
|
final fileName = r.files.first.path!.platformPath;
|
||||||
dPrint(fileName);
|
dPrint(fileName);
|
||||||
final fileNameRegExp = RegExp(
|
final fileNameRegExp = RegExp(
|
||||||
r'^(.*\\StarCitizen\\.*\\)Bin64\\StarCitizen\.exe$'.platformPath,
|
r'^(.*[/\\]starcitizen[/\\].*[/\\])bin64[/\\]starcitizen\.exe$',
|
||||||
caseSensitive: false,
|
caseSensitive: false,
|
||||||
);
|
);
|
||||||
if (fileNameRegExp.hasMatch(fileName)) {
|
if (fileNameRegExp.hasMatch(fileName)) {
|
||||||
RegExp pathRegex = RegExp(r'\\[^\\]+\\Bin64\\StarCitizen\.exe$'.platformPath, caseSensitive: false);
|
RegExp pathRegex = RegExp(r'[/\\][^/\\]+[/\\]bin64[/\\]starcitizen\.exe$', caseSensitive: false);
|
||||||
String extractedPath = fileName.replaceFirst(pathRegex, '');
|
String extractedPath = fileName.replaceFirst(pathRegex, '');
|
||||||
await _saveCustomPath("custom_game_path", extractedPath);
|
await _saveCustomPath("custom_game_path", extractedPath);
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
|
|||||||
@ -70,8 +70,11 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
workingText.value = S.current.tools_rsi_launcher_enhance_working_msg1;
|
workingText.value = S.current.tools_rsi_launcher_enhance_working_msg1;
|
||||||
if ((await SystemHelper.getPID("RSI Launcher")).isNotEmpty) {
|
if ((await SystemHelper.getPID("RSI Launcher")).isNotEmpty) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
showToast(context, S.current.tools_action_info_rsi_launcher_running_warning,
|
showToast(
|
||||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .35));
|
context,
|
||||||
|
S.current.tools_action_info_rsi_launcher_running_warning,
|
||||||
|
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .35),
|
||||||
|
);
|
||||||
workingText.value = "";
|
workingText.value = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -92,16 +95,16 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
|
|
||||||
return ContentDialog(
|
return ContentDialog(
|
||||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .48),
|
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .48),
|
||||||
title: Row(children: [
|
title: Row(
|
||||||
IconButton(
|
children: [
|
||||||
icon: const Icon(
|
IconButton(
|
||||||
FluentIcons.back,
|
icon: const Icon(FluentIcons.back, size: 22),
|
||||||
size: 22,
|
onPressed: workingText.value.isEmpty ? Navigator.of(context).pop : null,
|
||||||
),
|
),
|
||||||
onPressed: workingText.value.isEmpty ? Navigator.of(context).pop : null),
|
const SizedBox(width: 12),
|
||||||
const SizedBox(width: 12),
|
Text(S.current.tools_rsi_launcher_enhance_title),
|
||||||
Text(S.current.tools_rsi_launcher_enhance_title),
|
],
|
||||||
]),
|
),
|
||||||
content: AnimatedSize(
|
content: AnimatedSize(
|
||||||
duration: const Duration(milliseconds: 130),
|
duration: const Duration(milliseconds: 130),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -112,17 +115,16 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
InfoBar(
|
InfoBar(
|
||||||
title: const SizedBox(),
|
title: const SizedBox(),
|
||||||
content: Text(S.current.home_localization_action_rsi_launcher_no_game_path_msg),
|
content: Text(S.current.home_localization_action_rsi_launcher_no_game_path_msg),
|
||||||
style: InfoBarThemeData(decoration: (severity) {
|
style: InfoBarThemeData(
|
||||||
return BoxDecoration(
|
decoration: (severity) {
|
||||||
color: Colors.orange,
|
return BoxDecoration(color: Colors.orange);
|
||||||
);
|
},
|
||||||
}, iconColor: (severity) {
|
iconColor: (severity) {
|
||||||
return Colors.white;
|
return Colors.white;
|
||||||
}),
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(
|
|
||||||
height: 12,
|
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
],
|
],
|
||||||
if (workingText.value.isNotEmpty) ...[
|
if (workingText.value.isNotEmpty) ...[
|
||||||
Center(
|
Center(
|
||||||
@ -144,19 +146,17 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
S.current.tools_rsi_launcher_enhance_msg_version(assarState.value?.version ?? ""),
|
S.current.tools_rsi_launcher_enhance_msg_version(assarState.value?.version ?? ""),
|
||||||
style: TextStyle(
|
style: TextStyle(color: Colors.white.withValues(alpha: .6)),
|
||||||
color: Colors.white.withValues(alpha: .6),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
S.current.tools_rsi_launcher_enhance_msg_patch_status((assarState.value?.isPatchInstalled ?? false)
|
S.current.tools_rsi_launcher_enhance_msg_patch_status(
|
||||||
? S.current.localization_info_installed
|
(assarState.value?.isPatchInstalled ?? false)
|
||||||
: S.current.tools_action_info_not_installed),
|
? S.current.localization_info_installed
|
||||||
style: TextStyle(
|
: S.current.tools_action_info_not_installed,
|
||||||
color: Colors.white.withValues(alpha: .6),
|
|
||||||
),
|
),
|
||||||
)
|
style: TextStyle(color: Colors.white.withValues(alpha: .6)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (assarState.value?.serverData.isEmpty ?? true) ...[
|
if (assarState.value?.serverData.isEmpty ?? true) ...[
|
||||||
@ -165,6 +165,84 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
if (assarState.value?.enabledLocalization != null)
|
if (assarState.value?.enabledLocalization != null)
|
||||||
Container(
|
Container(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: FluentTheme.of(context).cardColor,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(S.current.tools_rsi_launcher_enhance_title_localization),
|
||||||
|
const SizedBox(height: 3),
|
||||||
|
Text(
|
||||||
|
S.current.tools_rsi_launcher_enhance_subtitle_localization,
|
||||||
|
style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: .6)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ComboBox(
|
||||||
|
items: [
|
||||||
|
for (final key in supportLocalizationMap.keys)
|
||||||
|
ComboBoxItem(value: key, child: Text(supportLocalizationMap[key]!)),
|
||||||
|
],
|
||||||
|
value: assarState.value?.enabledLocalization,
|
||||||
|
onChanged: (v) {
|
||||||
|
assarState.value = assarState.value!.copyWith(enabledLocalization: v);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 3),
|
||||||
|
if (assarState.value?.enableDownloaderBoost != null) ...[
|
||||||
|
IconButton(
|
||||||
|
icon: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 3, bottom: 3),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(expandEnhance.value ? FluentIcons.chevron_up : FluentIcons.chevron_down),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(
|
||||||
|
expandEnhance.value
|
||||||
|
? S.current.tools_rsi_launcher_enhance_action_fold
|
||||||
|
: S.current.tools_rsi_launcher_enhance_action_expand,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
if (!expandEnhance.value) {
|
||||||
|
final userOK = await showConfirmDialogs(
|
||||||
|
context,
|
||||||
|
S.current.tools_rsi_launcher_enhance_note_title,
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [Text(S.current.tools_rsi_launcher_enhance_note_msg)],
|
||||||
|
),
|
||||||
|
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .55),
|
||||||
|
);
|
||||||
|
if (!userOK) return;
|
||||||
|
}
|
||||||
|
expandEnhance.value = !expandEnhance.value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (expandEnhance.value)
|
||||||
|
Container(
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -174,111 +252,38 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
|
||||||
Text(S.current.tools_rsi_launcher_enhance_title_localization),
|
|
||||||
const SizedBox(height: 3),
|
|
||||||
Text(
|
|
||||||
S.current.tools_rsi_launcher_enhance_subtitle_localization,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
color: Colors.white.withValues(alpha: .6),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
ComboBox(
|
|
||||||
items: [
|
|
||||||
for (final key in supportLocalizationMap.keys)
|
|
||||||
ComboBoxItem(value: key, child: Text(supportLocalizationMap[key]!))
|
|
||||||
],
|
|
||||||
value: assarState.value?.enabledLocalization,
|
|
||||||
onChanged: (v) {
|
|
||||||
assarState.value = assarState.value!.copyWith(enabledLocalization: v);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
const SizedBox(height: 3),
|
|
||||||
if (assarState.value?.enableDownloaderBoost != null) ...[
|
|
||||||
IconButton(
|
|
||||||
icon: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 3, bottom: 3),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(expandEnhance.value ? FluentIcons.chevron_up : FluentIcons.chevron_down),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Text(expandEnhance.value
|
|
||||||
? S.current.tools_rsi_launcher_enhance_action_fold
|
|
||||||
: S.current.tools_rsi_launcher_enhance_action_expand),
|
|
||||||
],
|
|
||||||
))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () async {
|
|
||||||
if (!expandEnhance.value) {
|
|
||||||
final userOK = await showConfirmDialogs(
|
|
||||||
context,
|
|
||||||
S.current.tools_rsi_launcher_enhance_note_title,
|
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
children: [
|
||||||
Text(S.current.tools_rsi_launcher_enhance_note_msg),
|
Text(S.current.tools_rsi_launcher_enhance_title_download_booster),
|
||||||
|
const SizedBox(height: 3),
|
||||||
|
Text(
|
||||||
|
S.current.tools_rsi_launcher_enhance_subtitle_download_booster,
|
||||||
|
style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: .6)),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * .55));
|
),
|
||||||
if (!userOK) return;
|
|
||||||
}
|
|
||||||
expandEnhance.value = !expandEnhance.value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (expandEnhance.value)
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: FluentTheme.of(context).cardColor,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: Row(children: [
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(S.current.tools_rsi_launcher_enhance_title_download_booster),
|
|
||||||
const SizedBox(height: 3),
|
|
||||||
Text(
|
|
||||||
S.current.tools_rsi_launcher_enhance_subtitle_download_booster,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
color: Colors.white.withValues(alpha: .6),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
ToggleSwitch(
|
ToggleSwitch(
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
assarState.value = assarState.value?.copyWith(enableDownloaderBoost: value);
|
assarState.value = assarState.value?.copyWith(enableDownloaderBoost: value);
|
||||||
},
|
},
|
||||||
checked: assarState.value?.enableDownloaderBoost ?? false,
|
checked: assarState.value?.enableDownloaderBoost ?? false,
|
||||||
)
|
),
|
||||||
])),
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Center(
|
Center(
|
||||||
child: FilledButton(
|
child: FilledButton(
|
||||||
onPressed: doInstall,
|
onPressed: doInstall,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
|
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 6),
|
||||||
child: Text(S.current.tools_rsi_launcher_enhance_action_install),
|
child: Text(S.current.tools_rsi_launcher_enhance_action_install),
|
||||||
))),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
@ -300,7 +305,7 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
dPrint("[RsiLauncherEnhanceDialogUI] rsiLauncherPath ==== $lPath");
|
dPrint("[RsiLauncherEnhanceDialogUI] rsiLauncherPath ==== $lPath");
|
||||||
final dataPath = "${lPath}resources\\app.asar";
|
final dataPath = "${lPath}resources\\app.asar".platformPath;
|
||||||
dPrint("[RsiLauncherEnhanceDialogUI] rsiLauncherDataPath ==== $dataPath");
|
dPrint("[RsiLauncherEnhanceDialogUI] rsiLauncherDataPath ==== $dataPath");
|
||||||
try {
|
try {
|
||||||
final data = await asar_api.getRsiLauncherAsarData(asarPath: dataPath);
|
final data = await asar_api.getRsiLauncherAsarData(asarPath: dataPath);
|
||||||
@ -333,7 +338,10 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<String> _loadEnhanceData(
|
Future<String> _loadEnhanceData(
|
||||||
BuildContext context, WidgetRef ref, ValueNotifier<RSILauncherStateData?> assarState) async {
|
BuildContext context,
|
||||||
|
WidgetRef ref,
|
||||||
|
ValueNotifier<RSILauncherStateData?> assarState,
|
||||||
|
) async {
|
||||||
final globalModel = ref.read(appGlobalModelProvider);
|
final globalModel = ref.read(appGlobalModelProvider);
|
||||||
final enhancePath = "${globalModel.applicationSupportDir}/launcher_enhance_data";
|
final enhancePath = "${globalModel.applicationSupportDir}/launcher_enhance_data";
|
||||||
|
|
||||||
@ -418,11 +426,13 @@ class RsiLauncherEnhanceDialogUI extends HookConsumerWidget {
|
|||||||
for (final line in serverScriptLines) {
|
for (final line in serverScriptLines) {
|
||||||
final lineTrim = line.trim();
|
final lineTrim = line.trim();
|
||||||
if (lineTrim.startsWith(SC_TOOLBOX_ENABLED_LOCALIZATION_SCRIPT_START)) {
|
if (lineTrim.startsWith(SC_TOOLBOX_ENABLED_LOCALIZATION_SCRIPT_START)) {
|
||||||
scriptBuffer
|
scriptBuffer.writeln(
|
||||||
.writeln("$SC_TOOLBOX_ENABLED_LOCALIZATION_SCRIPT_START\"${assarState.value!.enabledLocalization}\";");
|
"$SC_TOOLBOX_ENABLED_LOCALIZATION_SCRIPT_START\"${assarState.value!.enabledLocalization}\";",
|
||||||
|
);
|
||||||
} else if (lineTrim.startsWith(SC_TOOLBOX_ENABLE_DOWNLOADER_BOOST_SCRIPT_START)) {
|
} else if (lineTrim.startsWith(SC_TOOLBOX_ENABLE_DOWNLOADER_BOOST_SCRIPT_START)) {
|
||||||
scriptBuffer
|
scriptBuffer.writeln(
|
||||||
.writeln("$SC_TOOLBOX_ENABLE_DOWNLOADER_BOOST_SCRIPT_START${assarState.value!.enableDownloaderBoost};");
|
"$SC_TOOLBOX_ENABLE_DOWNLOADER_BOOST_SCRIPT_START${assarState.value!.enableDownloaderBoost};",
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
scriptBuffer.writeln(line);
|
scriptBuffer.writeln(line);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,13 +72,14 @@ class ToolsUIModel extends _$ToolsUIModel {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
items = [
|
items = [
|
||||||
ToolsItemData(
|
if (Platform.isWindows)
|
||||||
"systemnfo",
|
ToolsItemData(
|
||||||
S.current.tools_action_view_system_info,
|
"systemnfo",
|
||||||
S.current.tools_action_info_view_critical_system_info,
|
S.current.tools_action_view_system_info,
|
||||||
const Icon(FluentIcons.system, size: 24),
|
S.current.tools_action_info_view_critical_system_info,
|
||||||
onTap: () => _showSystemInfo(context),
|
const Icon(FluentIcons.system, size: 24),
|
||||||
),
|
onTap: () => _showSystemInfo(context),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
// 年度报告入口 logic
|
// 年度报告入口 logic
|
||||||
@ -108,13 +109,14 @@ class ToolsUIModel extends _$ToolsUIModel {
|
|||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
items.add(await _addP4kCard(context));
|
items.add(await _addP4kCard(context));
|
||||||
items.addAll([
|
items.addAll([
|
||||||
ToolsItemData(
|
if (Platform.isWindows)
|
||||||
"hosts_booster",
|
ToolsItemData(
|
||||||
S.current.tools_action_hosts_acceleration_experimental,
|
"hosts_booster",
|
||||||
S.current.tools_action_info_hosts_acceleration_experimental_tip,
|
S.current.tools_action_hosts_acceleration_experimental,
|
||||||
const Icon(FluentIcons.virtual_network, size: 24),
|
S.current.tools_action_info_hosts_acceleration_experimental_tip,
|
||||||
onTap: () => _doHostsBooster(context),
|
const Icon(FluentIcons.virtual_network, size: 24),
|
||||||
),
|
onTap: () => _doHostsBooster(context),
|
||||||
|
),
|
||||||
ToolsItemData(
|
ToolsItemData(
|
||||||
"log_analyze",
|
"log_analyze",
|
||||||
S.current.log_analyzer_title,
|
S.current.log_analyzer_title,
|
||||||
@ -129,20 +131,22 @@ class ToolsUIModel extends _$ToolsUIModel {
|
|||||||
const Icon(FluentIcons.c_plus_plus, size: 24),
|
const Icon(FluentIcons.c_plus_plus, size: 24),
|
||||||
onTap: () => rsiEnhance(context),
|
onTap: () => rsiEnhance(context),
|
||||||
),
|
),
|
||||||
ToolsItemData(
|
if (Platform.isWindows)
|
||||||
"reinstall_eac",
|
ToolsItemData(
|
||||||
S.current.tools_action_reinstall_easyanticheat,
|
"reinstall_eac",
|
||||||
S.current.tools_action_info_reinstall_eac,
|
S.current.tools_action_reinstall_easyanticheat,
|
||||||
const Icon(FluentIcons.game, size: 24),
|
S.current.tools_action_info_reinstall_eac,
|
||||||
onTap: () => _reinstallEAC(context),
|
const Icon(FluentIcons.game, size: 24),
|
||||||
),
|
onTap: () => _reinstallEAC(context),
|
||||||
ToolsItemData(
|
),
|
||||||
"rsilauncher_admin_mode",
|
if (Platform.isWindows)
|
||||||
S.current.tools_action_rsi_launcher_admin_mode,
|
ToolsItemData(
|
||||||
S.current.tools_action_info_run_rsi_as_admin,
|
"rsilauncher_admin_mode",
|
||||||
const Icon(FluentIcons.admin, size: 24),
|
S.current.tools_action_rsi_launcher_admin_mode,
|
||||||
onTap: () => _adminRSILauncher(context),
|
S.current.tools_action_info_run_rsi_as_admin,
|
||||||
),
|
const Icon(FluentIcons.admin, size: 24),
|
||||||
|
onTap: () => _adminRSILauncher(context),
|
||||||
|
),
|
||||||
ToolsItemData(
|
ToolsItemData(
|
||||||
"unp4kc",
|
"unp4kc",
|
||||||
S.current.tools_action_unp4k,
|
S.current.tools_action_unp4k,
|
||||||
@ -169,8 +173,10 @@ class ToolsUIModel extends _$ToolsUIModel {
|
|||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
items.add(await _addPhotographyCard(context));
|
items.add(await _addPhotographyCard(context));
|
||||||
state = state.copyWith(items: items);
|
state = state.copyWith(items: items);
|
||||||
if (!context.mounted) return;
|
if (Platform.isWindows) {
|
||||||
items.addAll(await _addNvmePatchCard(context));
|
if (!context.mounted) return;
|
||||||
|
items.addAll(await _addNvmePatchCard(context));
|
||||||
|
}
|
||||||
state = state.copyWith(items: items, isItemLoading: false);
|
state = state.copyWith(items: items, isItemLoading: false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
@ -250,7 +256,10 @@ class ToolsUIModel extends _$ToolsUIModel {
|
|||||||
Future<ToolsItemData> _addShaderCard(BuildContext context) async {
|
Future<ToolsItemData> _addShaderCard(BuildContext context) async {
|
||||||
final gameShaderCachePath = await SCLoggerHelper.getShaderCachePath();
|
final gameShaderCachePath = await SCLoggerHelper.getShaderCachePath();
|
||||||
final shaderSize =
|
final shaderSize =
|
||||||
((await SystemHelper.getDirLen(gameShaderCachePath ?? "", skipPath: ["$gameShaderCachePath\\Crashes"])) /
|
((await SystemHelper.getDirLen(
|
||||||
|
gameShaderCachePath ?? "",
|
||||||
|
skipPath: ["$gameShaderCachePath\\Crashes".platformPath],
|
||||||
|
)) /
|
||||||
1024 /
|
1024 /
|
||||||
1024)
|
1024)
|
||||||
.toStringAsFixed(4);
|
.toStringAsFixed(4);
|
||||||
@ -300,7 +309,8 @@ class ToolsUIModel extends _$ToolsUIModel {
|
|||||||
|
|
||||||
// 使用最新版本
|
// 使用最新版本
|
||||||
final latestVersion = versions.first;
|
final latestVersion = versions.first;
|
||||||
final settingsPath = "$gameShaderCachePath\\starcitizen_$latestVersion\\GraphicsSettings\\GraphicsSettings.json";
|
final settingsPath =
|
||||||
|
"$gameShaderCachePath\\starcitizen_$latestVersion\\GraphicsSettings\\GraphicsSettings.json".platformPath;
|
||||||
|
|
||||||
final file = File(settingsPath);
|
final file = File(settingsPath);
|
||||||
if (!await file.exists()) return (-1, latestVersion);
|
if (!await file.exists()) return (-1, latestVersion);
|
||||||
@ -627,6 +637,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
|||||||
final result = await showDialog<String>(
|
final result = await showDialog<String>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (dialogContext) => ContentDialog(
|
builder: (dialogContext) => ContentDialog(
|
||||||
|
constraints: BoxConstraints(maxWidth: 380),
|
||||||
title: Text(S.current.tools_shader_clean_dialog_title),
|
title: Text(S.current.tools_shader_clean_dialog_title),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
|||||||
@ -4,10 +4,10 @@ project(runner LANGUAGES CXX)
|
|||||||
|
|
||||||
# The name of the executable created for the application. Change this to change
|
# The name of the executable created for the application. Change this to change
|
||||||
# the on-disk name of your application.
|
# the on-disk name of your application.
|
||||||
set(BINARY_NAME "app")
|
set(BINARY_NAME "starcitizen_doctor")
|
||||||
# The unique GTK application identifier for this application. See:
|
# The unique GTK application identifier for this application. See:
|
||||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||||
set(APPLICATION_ID "com.example.app")
|
set(APPLICATION_ID "com.starcitizen_doctor")
|
||||||
|
|
||||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||||
# versions of CMake.
|
# versions of CMake.
|
||||||
@ -53,6 +53,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR})
|
|||||||
# System-level dependencies.
|
# System-level dependencies.
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
|
pkg_check_modules(GDK_PIXBUF REQUIRED IMPORTED_TARGET gdk-pixbuf-2.0)
|
||||||
|
|
||||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ apply_standard_settings(${BINARY_NAME})
|
|||||||
# Add dependency libraries. Add any application-specific dependencies here.
|
# Add dependency libraries. Add any application-specific dependencies here.
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GDK_PIXBUF)
|
||||||
|
|
||||||
# Run the Flutter tool portions of the build. This must not be removed.
|
# Run the Flutter tool portions of the build. This must not be removed.
|
||||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||||
@ -143,3 +145,13 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
|||||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
COMPONENT Runtime)
|
COMPONENT Runtime)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Install application icons
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/icons/hicolor"
|
||||||
|
DESTINATION "share/icons"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
# Install desktop file
|
||||||
|
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/com.starcitizen_doctor.desktop"
|
||||||
|
DESTINATION "share/applications"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|||||||
9
linux/com.starcitizen_doctor.desktop
Normal file
9
linux/com.starcitizen_doctor.desktop
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=SC汉化盒子
|
||||||
|
Comment=Star Citizen Tool Box for Chinese players
|
||||||
|
Exec=starcitizen_doctor
|
||||||
|
Icon=starcitizen_doctor
|
||||||
|
Categories=Utility;Game;
|
||||||
|
Terminal=false
|
||||||
|
StartupNotify=true
|
||||||
BIN
linux/icons/hicolor/128x128/apps/starcitizen_doctor.png
Normal file
BIN
linux/icons/hicolor/128x128/apps/starcitizen_doctor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
BIN
linux/icons/hicolor/16x16/apps/starcitizen_doctor.png
Normal file
BIN
linux/icons/hicolor/16x16/apps/starcitizen_doctor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 879 B |
BIN
linux/icons/hicolor/256x256/apps/starcitizen_doctor.png
Normal file
BIN
linux/icons/hicolor/256x256/apps/starcitizen_doctor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
linux/icons/hicolor/32x32/apps/starcitizen_doctor.png
Normal file
BIN
linux/icons/hicolor/32x32/apps/starcitizen_doctor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
linux/icons/hicolor/48x48/apps/starcitizen_doctor.png
Normal file
BIN
linux/icons/hicolor/48x48/apps/starcitizen_doctor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
BIN
linux/icons/hicolor/64x64/apps/starcitizen_doctor.png
Normal file
BIN
linux/icons/hicolor/64x64/apps/starcitizen_doctor.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@ -4,6 +4,7 @@
|
|||||||
#ifdef GDK_WINDOWING_X11
|
#ifdef GDK_WINDOWING_X11
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
#include "flutter/generated_plugin_registrant.h"
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
|
||||||
@ -42,11 +43,11 @@ static void my_application_activate(GApplication* application) {
|
|||||||
if (use_header_bar) {
|
if (use_header_bar) {
|
||||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||||
gtk_header_bar_set_title(header_bar, "app");
|
gtk_header_bar_set_title(header_bar, "SC汉化盒子");
|
||||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||||
} else {
|
} else {
|
||||||
gtk_window_set_title(window, "app");
|
gtk_window_set_title(window, "SC汉化盒子");
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_window_set_default_size(window, 1280, 720);
|
gtk_window_set_default_size(window, 1280, 720);
|
||||||
|
|||||||
@ -71,8 +71,8 @@ pub async fn get_rsi_launcher_asar_data(asar_path: &str) -> anyhow::Result<RsiLa
|
|||||||
let mut main_js_content: Vec<u8> = Vec::new();
|
let mut main_js_content: Vec<u8> = Vec::new();
|
||||||
asar.files().iter().for_each(|v| {
|
asar.files().iter().for_each(|v| {
|
||||||
let (path, file) = v;
|
let (path, file) = v;
|
||||||
let path_string = path.clone().into_os_string().into_string().unwrap();
|
let path_string = path.clone().into_os_string().into_string().unwrap().replace("\\", "/");
|
||||||
if path_string.starts_with("app\\static\\js\\main.") && path_string.ends_with(".js") {
|
if path_string.starts_with("app/static/js/main.") && path_string.ends_with(".js") {
|
||||||
main_js_path = path_string;
|
main_js_path = path_string;
|
||||||
main_js_content = file.data().to_vec();
|
main_js_content = file.data().to_vec();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,12 +12,16 @@ use tao::dpi::{LogicalPosition, LogicalSize};
|
|||||||
use tao::event::{Event, WindowEvent};
|
use tao::event::{Event, WindowEvent};
|
||||||
use tao::event_loop::{ControlFlow, EventLoop, EventLoopBuilder};
|
use tao::event_loop::{ControlFlow, EventLoop, EventLoopBuilder};
|
||||||
use tao::platform::run_return::EventLoopExtRunReturn;
|
use tao::platform::run_return::EventLoopExtRunReturn;
|
||||||
|
|
||||||
use tao::window::{Icon, Window, WindowBuilder};
|
use tao::window::{Icon, Window, WindowBuilder};
|
||||||
use wry::{NewWindowResponse, PageLoadEvent, WebView, WebViewBuilder};
|
use wry::{NewWindowResponse, PageLoadEvent, WebView, WebViewBuilder};
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use tao::platform::windows::EventLoopBuilderExtWindows;
|
use tao::platform::windows::EventLoopBuilderExtWindows;
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use tao::platform::unix::EventLoopBuilderExtUnix;
|
||||||
|
|
||||||
use crate::api::webview_api::{
|
use crate::api::webview_api::{
|
||||||
WebViewCommand, WebViewConfiguration, WebViewEvent, WebViewNavigationState,
|
WebViewCommand, WebViewConfiguration, WebViewEvent, WebViewNavigationState,
|
||||||
};
|
};
|
||||||
@ -263,14 +267,10 @@ fn run_webview_loop(
|
|||||||
is_closed: Arc<AtomicBool>,
|
is_closed: Arc<AtomicBool>,
|
||||||
) {
|
) {
|
||||||
// Create event loop with any_thread support for non-main thread execution
|
// Create event loop with any_thread support for non-main thread execution
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
let mut event_loop: EventLoop<UserEvent> = EventLoopBuilder::with_user_event()
|
let mut event_loop: EventLoop<UserEvent> = EventLoopBuilder::with_user_event()
|
||||||
.with_any_thread(true)
|
.with_any_thread(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
let mut event_loop: EventLoop<UserEvent> = EventLoopBuilder::with_user_event().build();
|
|
||||||
|
|
||||||
let proxy = event_loop.create_proxy();
|
let proxy = event_loop.create_proxy();
|
||||||
|
|
||||||
// Load window icon from embedded ICO file
|
// Load window icon from embedded ICO file
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user