mirror of
https://mirror.ghproxy.com/https://github.com/StarCitizenToolBox/app.git
synced 2024-12-22 19:53:43 +08:00
feat: 多语言 初步引入
This commit is contained in:
parent
eae02be2af
commit
b2c13a8a6f
@ -3,6 +3,8 @@ import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:synchronized/synchronized.dart';
|
||||
|
||||
export 'package:starcitizen_doctor/generated/l10n.dart';
|
||||
|
||||
var _logLock = Lock();
|
||||
File? _logFile;
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:starcitizen_doctor/generated/l10n.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
import 'app.dart';
|
||||
|
||||
@ -38,10 +40,18 @@ class App extends HookConsumerWidget {
|
||||
title: "StarCitizenToolBox",
|
||||
restorationScopeId: "StarCitizenToolBox",
|
||||
themeMode: ThemeMode.dark,
|
||||
localizationsDelegates: const [
|
||||
S.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
FluentLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: S.delegate.supportedLocales,
|
||||
builder: (context, child) {
|
||||
return MediaQuery(
|
||||
data:
|
||||
MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
|
||||
MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
|
||||
child: child ?? const SizedBox(),
|
||||
);
|
||||
},
|
||||
@ -55,10 +65,10 @@ class App extends HookConsumerWidget {
|
||||
micaBackgroundColor: appState.themeConf.micaColor,
|
||||
buttonTheme: ButtonThemeData(
|
||||
defaultButtonStyle: ButtonStyle(
|
||||
shape: ButtonState.all(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
side: BorderSide(color: Colors.white.withOpacity(.01)))),
|
||||
))),
|
||||
shape: ButtonState.all(RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
side: BorderSide(color: Colors.white.withOpacity(.01)))),
|
||||
))),
|
||||
debugShowCheckedModeBanner: false,
|
||||
routeInformationParser: router.routeInformationParser,
|
||||
routerDelegate: router.routerDelegate,
|
||||
@ -98,10 +108,10 @@ Widget _defaultWebviewTitleBar(BuildContext context) {
|
||||
const SizedBox(width: 12),
|
||||
(state.isLoading)
|
||||
? const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: ProgressRing(),
|
||||
)
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: ProgressRing(),
|
||||
)
|
||||
: const SizedBox(width: 24),
|
||||
const SizedBox(width: 12),
|
||||
SelectableText(state.url ?? ""),
|
||||
|
@ -31,9 +31,9 @@ class AboutUI extends HookConsumerWidget {
|
||||
const SizedBox(height: 12),
|
||||
Button(
|
||||
onPressed: () => _onCheckUpdate(context, ref),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Text("检查更新"),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Text(S.current.about_check_update),
|
||||
)),
|
||||
const SizedBox(height: 32),
|
||||
Container(
|
||||
@ -103,7 +103,7 @@ class AboutUI extends HookConsumerWidget {
|
||||
const Icon(FontAwesomeIcons.link),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
"在线反馈",
|
||||
S.current.about_online_feedback,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: Colors.white.withOpacity(.6)),
|
||||
),
|
||||
@ -120,7 +120,7 @@ class AboutUI extends HookConsumerWidget {
|
||||
const Icon(FontAwesomeIcons.qq),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
"QQ群: 940696487",
|
||||
S.current.about_action_qq_group,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: Colors.white.withOpacity(.6)),
|
||||
),
|
||||
@ -138,7 +138,7 @@ class AboutUI extends HookConsumerWidget {
|
||||
const Icon(FontAwesomeIcons.envelope),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
"邮箱: scbox@xkeyc.com",
|
||||
S.current.about_action_email,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: Colors.white.withOpacity(.6)),
|
||||
),
|
||||
@ -155,7 +155,7 @@ class AboutUI extends HookConsumerWidget {
|
||||
const Icon(FontAwesomeIcons.github),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
"开源",
|
||||
S.current.about_action_open_source,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: Colors.white.withOpacity(.6)),
|
||||
),
|
||||
@ -209,13 +209,13 @@ class AboutUI extends HookConsumerWidget {
|
||||
{required BuildContext context,
|
||||
required String name,
|
||||
required int value}) {
|
||||
const names = {
|
||||
"launch": "启动",
|
||||
"gameLaunch": "启动游戏",
|
||||
"firstLaunch": "累计用户",
|
||||
"install_localization": "汉化安装",
|
||||
"performance_apply": "性能调优",
|
||||
"p4k_download": "P4K分流"
|
||||
final names = {
|
||||
"launch": S.current.about_analytics_launch,
|
||||
"gameLaunch": S.current.about_analytics_launch_game,
|
||||
"firstLaunch": S.current.about_analytics_total_users,
|
||||
"install_localization": S.current.about_analytics_install_translation,
|
||||
"performance_apply": S.current.about_analytics_performance_optimization,
|
||||
"p4k_download": S.current.about_analytics_p4k_redirection
|
||||
};
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
@ -256,8 +256,8 @@ class AboutUI extends HookConsumerWidget {
|
||||
await ref.read(appGlobalModelProvider.notifier).checkUpdate(context);
|
||||
if (!hasUpdate) {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "已经是最新版本!");
|
||||
showToast(context, S.current.about_info_latest_version);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ class HomeCountdownDialogUI extends HookConsumerWidget {
|
||||
Navigator.of(context).pop();
|
||||
}),
|
||||
const SizedBox(width: 12),
|
||||
const Text("节日倒计时"),
|
||||
Text(S.current.home_holiday_countdown),
|
||||
],
|
||||
),
|
||||
content: homeState.countdownFestivalListData == null
|
||||
@ -85,7 +85,7 @@ class HomeCountdownDialogUI extends HookConsumerWidget {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
"* 以上节日日期由人工收录、维护,可能存在错误,欢迎反馈!",
|
||||
S.current.home_holiday_countdown_disclaimer,
|
||||
style: TextStyle(
|
||||
fontSize: 13, color: Colors.white.withOpacity(.3)),
|
||||
)
|
||||
@ -95,4 +95,4 @@ class HomeCountdownDialogUI extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,12 +14,12 @@ class HomeGameLoginDialogUI extends HookConsumerWidget {
|
||||
useEffect(() {
|
||||
ref.read(homeGameLoginUIModelProvider.notifier).launchWebLogin(context);
|
||||
return null;
|
||||
}, const []);
|
||||
}, []);
|
||||
return ContentDialog(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * .56,
|
||||
),
|
||||
title: (loginState.loginStatus == 2) ? null : const Text("一键启动"),
|
||||
title: (loginState.loginStatus == 2) ? null : Text(S.current.home_action_one_click_launch),
|
||||
content: AnimatedSize(
|
||||
duration: const Duration(milliseconds: 230),
|
||||
child: Padding(
|
||||
@ -33,13 +33,13 @@ class HomeGameLoginDialogUI extends HookConsumerWidget {
|
||||
Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const Text("登录中..."),
|
||||
Text(S.current.home_title_logging_in),
|
||||
const SizedBox(height: 12),
|
||||
const ProgressRing(),
|
||||
if (loginState.isDeviceSupportWinHello ?? false)
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
"* 若开启了自动填充,请留意弹出的 Windows Hello 窗口",
|
||||
S.current.home_info_auto_fill_notice,
|
||||
style: TextStyle(
|
||||
fontSize: 13, color: Colors.white.withOpacity(.6)),
|
||||
)
|
||||
@ -52,9 +52,9 @@ class HomeGameLoginDialogUI extends HookConsumerWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
const Text(
|
||||
"欢迎回来!",
|
||||
style: TextStyle(fontSize: 20),
|
||||
Text(
|
||||
S.current.home_login_title_welcome_back,
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
if (loginState.avatarUrl != null)
|
||||
@ -74,7 +74,7 @@ class HomeGameLoginDialogUI extends HookConsumerWidget {
|
||||
fontSize: 24, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const Text("正在为您启动游戏..."),
|
||||
Text(S.current.home_login_title_launching_game),
|
||||
const SizedBox(height: 12),
|
||||
const ProgressRing(),
|
||||
],
|
||||
@ -87,4 +87,4 @@ class HomeGameLoginDialogUI extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ part 'home_game_login_dialog_ui_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class HomeGameLoginState with _$HomeGameLoginState {
|
||||
const factory HomeGameLoginState({
|
||||
factory HomeGameLoginState({
|
||||
required int loginStatus,
|
||||
String? nickname,
|
||||
String? avatarUrl,
|
||||
@ -41,7 +41,7 @@ class HomeGameLoginState with _$HomeGameLoginState {
|
||||
class HomeGameLoginUIModel extends _$HomeGameLoginUIModel {
|
||||
@override
|
||||
HomeGameLoginState build() {
|
||||
return const HomeGameLoginState(loginStatus: 0);
|
||||
return HomeGameLoginState(loginStatus: 0);
|
||||
}
|
||||
|
||||
final LocalAuthentication _localAuth = LocalAuthentication();
|
||||
@ -53,9 +53,9 @@ class HomeGameLoginUIModel extends _$HomeGameLoginUIModel {
|
||||
state = state.copyWith(isDeviceSupportWinHello: isDeviceSupportWinHello);
|
||||
|
||||
if (!context.mounted) return;
|
||||
goWebView(
|
||||
context, "登录 RSI 账户", "https://robertsspaceindustries.com/connect",
|
||||
loginMode: true, rsiLoginCallback: (message, ok) async {
|
||||
goWebView(context, S.current.home_action_login_rsi_account,
|
||||
"https://robertsspaceindustries.com/connect", loginMode: true,
|
||||
rsiLoginCallback: (message, ok) async {
|
||||
// dPrint(
|
||||
// "======rsiLoginCallback=== $ok ===== data==\n${json.encode(message)}");
|
||||
if (message == null || !ok) {
|
||||
@ -98,12 +98,13 @@ class HomeGameLoginUIModel extends _$HomeGameLoginUIModel {
|
||||
if (!context.mounted) return;
|
||||
final ok = await showConfirmDialogs(
|
||||
context,
|
||||
"是否开启自动密码填充?",
|
||||
S.current.home_action_q_auto_password_fill_prompt,
|
||||
const Text(
|
||||
"盒子将使用 PIN 与 Windows 凭据加密保存您的密码,密码只存储在您的设备中。\n\n当下次登录需要输入密码时,您只需授权PIN即可自动填充登录。"));
|
||||
if (ok == true) {
|
||||
if (await _localAuth.authenticate(
|
||||
localizedReason: "输入PIN以启用加密") ==
|
||||
localizedReason:
|
||||
S.current.home_login_info_enter_pin_to_encrypt) ==
|
||||
true) {
|
||||
await _savePwd(inputEmail, inputPassword);
|
||||
}
|
||||
@ -129,12 +130,12 @@ class HomeGameLoginUIModel extends _$HomeGameLoginUIModel {
|
||||
if (!context.mounted) return;
|
||||
final ok = await showConfirmDialogs(
|
||||
context,
|
||||
"游戏版本过期",
|
||||
S.current.home_login_info_game_version_outdated,
|
||||
Text(
|
||||
"RSI 服务器报告版本号:${releaseInfo?["versionLabel"]} \n\n本地版本号:${buildInfo["RequestedP4ChangeNum"]} \n\n建议使用 RSI Launcher 更新游戏!"),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * .4),
|
||||
cancel: "忽略");
|
||||
cancel: S.current.home_login_info_action_ignore);
|
||||
if (ok == true) {
|
||||
if (!context.mounted) return;
|
||||
Navigator.pop(context);
|
||||
@ -163,7 +164,7 @@ class HomeGameLoginUIModel extends _$HomeGameLoginUIModel {
|
||||
if (!context.mounted) return;
|
||||
final ok = await showConfirmDialogs(
|
||||
context,
|
||||
"盒子一键启动",
|
||||
S.current.home_login_action_title_box_one_click_launch,
|
||||
const Text(
|
||||
"本功能可以帮您更加便利的启动游戏。\n\n为确保账户安全 ,本功能使用汉化浏览器保留登录状态,且不会保存您的密码信息(除非你启用了自动填充功能)。"
|
||||
"\n\n使用此功能登录账号时请确保您的 SC汉化盒子 是从可信任的来源下载。",
|
||||
@ -182,7 +183,8 @@ class HomeGameLoginUIModel extends _$HomeGameLoginUIModel {
|
||||
}
|
||||
if (!await WebviewWindow.isWebviewAvailable()) {
|
||||
if (!context.mounted) return;
|
||||
await showToast(context, "需要安装 WebView2 Runtime");
|
||||
await showToast(context,
|
||||
S.current.home_login_action_title_need_webview2_runtime);
|
||||
if (!context.mounted) return;
|
||||
await launchUrlString(
|
||||
"https://developer.microsoft.com/en-us/microsoft-edge/webview2/");
|
||||
|
@ -185,7 +185,7 @@ class __$$LoginStatusImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
|
||||
class _$LoginStatusImpl implements _LoginStatus {
|
||||
const _$LoginStatusImpl(
|
||||
_$LoginStatusImpl(
|
||||
{required this.loginStatus,
|
||||
this.nickname,
|
||||
this.avatarUrl,
|
||||
@ -270,7 +270,7 @@ class _$LoginStatusImpl implements _LoginStatus {
|
||||
}
|
||||
|
||||
abstract class _LoginStatus implements HomeGameLoginState {
|
||||
const factory _LoginStatus(
|
||||
factory _LoginStatus(
|
||||
{required final int loginStatus,
|
||||
final String? nickname,
|
||||
final String? avatarUrl,
|
||||
|
@ -7,7 +7,7 @@ part of 'home_game_login_dialog_ui_model.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$homeGameLoginUIModelHash() =>
|
||||
r'c26dfd89985ff9246104135c288b673b7f15acf0';
|
||||
r'bcd5fc6d85345207797dd51253b2608035e1fc36';
|
||||
|
||||
/// See also [HomeGameLoginUIModel].
|
||||
@ProviderFor(HomeGameLoginUIModel)
|
||||
|
@ -36,9 +36,9 @@ class HomeMdContentDialogUI extends HookConsumerWidget {
|
||||
),
|
||||
actions: [
|
||||
FilledButton(
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(left: 8, right: 8, top: 2, bottom: 2),
|
||||
child: Text("关闭"),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 8, right: 8, top: 2, bottom: 2),
|
||||
child: Text(S.current.action_close),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
@ -52,4 +52,4 @@ class HomeMdContentDialogUI extends HookConsumerWidget {
|
||||
final r = await RSHttp.getText(url);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
@ -24,13 +24,13 @@ class HomeDownloaderUI extends HookConsumerWidget {
|
||||
const SizedBox(width: 24),
|
||||
const SizedBox(width: 12),
|
||||
for (final item in <MapEntry<String, IconData>, String>{
|
||||
const MapEntry("settings", FluentIcons.settings): "限速设置",
|
||||
const MapEntry("settings", FluentIcons.settings): S.current.downloader_speed_limit_settings,
|
||||
if (state.tasks.isNotEmpty)
|
||||
const MapEntry("pause_all", FluentIcons.pause): "全部暂停",
|
||||
const MapEntry("pause_all", FluentIcons.pause): S.current.downloader_action_pause_all,
|
||||
if (state.waitingTasks.isNotEmpty)
|
||||
const MapEntry("resume_all", FluentIcons.download): "恢复全部",
|
||||
const MapEntry("resume_all", FluentIcons.download): S.current.downloader_action_resume_all,
|
||||
if (state.tasks.isNotEmpty || state.waitingTasks.isNotEmpty)
|
||||
const MapEntry("cancel_all", FluentIcons.cancel): "全部取消",
|
||||
const MapEntry("cancel_all", FluentIcons.cancel): S.current.downloader_action_cancel_all,
|
||||
}.entries)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 6, right: 6),
|
||||
@ -52,9 +52,9 @@ class HomeDownloaderUI extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
if (model.getTasksLen() == 0)
|
||||
const Expanded(
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Text("无下载任务"),
|
||||
child: Text(S.current.downloader_info_no_download_tasks),
|
||||
))
|
||||
else
|
||||
Expanded(
|
||||
@ -171,22 +171,22 @@ class HomeDownloaderUI extends HookConsumerWidget {
|
||||
if (type != "stopped")
|
||||
DropDownButton(
|
||||
closeAfterClick: false,
|
||||
title: const Padding(
|
||||
padding: EdgeInsets.all(3),
|
||||
child: Text('选项'),
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.all(3),
|
||||
child: Text(S.current.downloader_action_options),
|
||||
),
|
||||
items: [
|
||||
if (task.status == "paused")
|
||||
MenuFlyoutItem(
|
||||
leading:
|
||||
const Icon(FluentIcons.download),
|
||||
text: const Text('继续下载'),
|
||||
text: Text(S.current.downloader_action_continue_download),
|
||||
onPressed: () =>
|
||||
model.resumeTask(task.gid))
|
||||
else if (task.status == "active")
|
||||
MenuFlyoutItem(
|
||||
leading: const Icon(FluentIcons.pause),
|
||||
text: const Text('暂停下载'),
|
||||
text: Text(S.current.downloader_action_pause_download),
|
||||
onPressed: () =>
|
||||
model.pauseTask(task.gid)),
|
||||
const MenuFlyoutSeparator(),
|
||||
@ -195,7 +195,7 @@ class HomeDownloaderUI extends HookConsumerWidget {
|
||||
FluentIcons.chrome_close,
|
||||
size: 14,
|
||||
),
|
||||
text: const Text('取消下载'),
|
||||
text: Text(S.current.downloader_action_cancel_download),
|
||||
onPressed: () =>
|
||||
model.cancelTask(context, task.gid)),
|
||||
MenuFlyoutItem(
|
||||
@ -203,7 +203,7 @@ class HomeDownloaderUI extends HookConsumerWidget {
|
||||
FluentIcons.folder_open,
|
||||
size: 14,
|
||||
),
|
||||
text: const Text('打开文件夹'),
|
||||
text: Text(S.current.action_open_folder),
|
||||
onPressed: () => model.openFolder(task)),
|
||||
],
|
||||
),
|
||||
@ -243,4 +243,4 @@ class HomeDownloaderUI extends HookConsumerWidget {
|
||||
),
|
||||
useBodyContainer: true);
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ part 'home_downloader_ui_model.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class HomeDownloaderUIState with _$HomeDownloaderUIState {
|
||||
const factory HomeDownloaderUIState({
|
||||
factory HomeDownloaderUIState({
|
||||
@Default([]) List<Aria2Task> tasks,
|
||||
@Default([]) List<Aria2Task> waitingTasks,
|
||||
@Default([]) List<Aria2Task> stoppedTasks,
|
||||
@ -40,23 +40,23 @@ class HomeDownloaderUIModel extends _$HomeDownloaderUIModel {
|
||||
bool _disposed = false;
|
||||
|
||||
final statusMap = {
|
||||
"active": "下载中...",
|
||||
"waiting": "等待中",
|
||||
"paused": "已暂停",
|
||||
"error": "下载失败",
|
||||
"complete": "下载完成",
|
||||
"removed": "已删除",
|
||||
"active": S.current.downloader_info_downloading_status,
|
||||
"waiting": S.current.downloader_info_waiting,
|
||||
"paused": S.current.downloader_info_paused,
|
||||
"error": S.current.downloader_info_download_failed,
|
||||
"complete": S.current.downloader_info_download_completed,
|
||||
"removed": S.current.downloader_info_deleted,
|
||||
};
|
||||
|
||||
final listHeaderStatusMap = {
|
||||
"active": "下载中",
|
||||
"waiting": "等待中",
|
||||
"stopped": "已结束",
|
||||
"active": S.current.downloader_title_downloading,
|
||||
"waiting": S.current.downloader_info_waiting,
|
||||
"stopped": S.current.downloader_title_ended,
|
||||
};
|
||||
|
||||
@override
|
||||
HomeDownloaderUIState build() {
|
||||
state = const HomeDownloaderUIState();
|
||||
state = HomeDownloaderUIState();
|
||||
_listenDownloader();
|
||||
ref.onDispose(() {
|
||||
_disposed = true;
|
||||
@ -79,7 +79,7 @@ class HomeDownloaderUIModel extends _$HomeDownloaderUIModel {
|
||||
return;
|
||||
case "cancel_all":
|
||||
final userOK = await showConfirmDialogs(
|
||||
context, "确认取消全部任务?", const Text("如果文件不再需要,你可能需要手动删除下载文件。"));
|
||||
context, "确认取消全部任务?", Text(S.current.downloader_info_manual_file_deletion_note));
|
||||
if (userOK == true) {
|
||||
if (!aria2cState.isRunning) return;
|
||||
try {
|
||||
@ -170,7 +170,7 @@ class HomeDownloaderUIModel extends _$HomeDownloaderUIModel {
|
||||
if (gid != null) {
|
||||
if (!context.mounted) return;
|
||||
final ok = await showConfirmDialogs(
|
||||
context, "确认取消下载?", const Text("如果文件不再需要,你可能需要手动删除下载文件。"));
|
||||
context, "确认取消下载?", Text(S.current.downloader_info_manual_file_deletion_note));
|
||||
if (ok == true) {
|
||||
final aria2c = ref.read(aria2cModelProvider).aria2c;
|
||||
await aria2c?.remove(gid);
|
||||
@ -242,22 +242,22 @@ class HomeDownloaderUIModel extends _$HomeDownloaderUIModel {
|
||||
if (!context.mounted) return;
|
||||
final ok = await showConfirmDialogs(
|
||||
context,
|
||||
"限速设置",
|
||||
S.current.downloader_speed_limit_settings,
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"SC 汉化盒子使用 p2p 网络来加速文件下载,如果您流量有限,可在此处将上传带宽设置为 1(byte)。",
|
||||
S.current.downloader_info_p2p_network_note,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.white.withOpacity(.6),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const Text("请输入下载单位,如:1、100k、10m, 0或留空为不限速。"),
|
||||
Text(S.current.downloader_info_download_unit_input_prompt),
|
||||
const SizedBox(height: 12),
|
||||
const Text("上传限速:"),
|
||||
Text(S.current.downloader_input_upload_speed_limit),
|
||||
const SizedBox(height: 6),
|
||||
TextFormBox(
|
||||
placeholder: "1、100k、10m、0",
|
||||
@ -266,7 +266,7 @@ class HomeDownloaderUIModel extends _$HomeDownloaderUIModel {
|
||||
inputFormatters: [ifr],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const Text("下载限速:"),
|
||||
Text(S.current.downloader_input_download_speed_limit),
|
||||
const SizedBox(height: 6),
|
||||
TextFormBox(
|
||||
placeholder: "1、100k、10m、0",
|
||||
@ -276,7 +276,7 @@ class HomeDownloaderUIModel extends _$HomeDownloaderUIModel {
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
"* P2P 上传仅在下载文件时进行,下载完成后会关闭 p2p 连接。如您想参与做种,请通过关于页面联系我们。",
|
||||
S.current.downloader_input_info_p2p_upload_note,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.white.withOpacity(.6),
|
||||
@ -303,4 +303,4 @@ class HomeDownloaderUIModel extends _$HomeDownloaderUIModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -136,7 +136,7 @@ class __$$HomeDownloaderUIStateImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
|
||||
class _$HomeDownloaderUIStateImpl implements _HomeDownloaderUIState {
|
||||
const _$HomeDownloaderUIStateImpl(
|
||||
_$HomeDownloaderUIStateImpl(
|
||||
{final List<Aria2Task> tasks = const [],
|
||||
final List<Aria2Task> waitingTasks = const [],
|
||||
final List<Aria2Task> stoppedTasks = const [],
|
||||
@ -211,7 +211,7 @@ class _$HomeDownloaderUIStateImpl implements _HomeDownloaderUIState {
|
||||
}
|
||||
|
||||
abstract class _HomeDownloaderUIState implements HomeDownloaderUIState {
|
||||
const factory _HomeDownloaderUIState(
|
||||
factory _HomeDownloaderUIState(
|
||||
{final List<Aria2Task> tasks,
|
||||
final List<Aria2Task> waitingTasks,
|
||||
final List<Aria2Task> stoppedTasks,
|
||||
|
@ -7,7 +7,7 @@ part of 'home_downloader_ui_model.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$homeDownloaderUIModelHash() =>
|
||||
r'947ebb9abb262aea6121c74481753da0eebb9a79';
|
||||
r'88e1c9a667672d303cb244305dc0aec89d77ffe5';
|
||||
|
||||
/// See also [HomeDownloaderUIModel].
|
||||
@ProviderFor(HomeDownloaderUIModel)
|
||||
|
@ -27,7 +27,7 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
model.doCheck(context);
|
||||
});
|
||||
return null;
|
||||
}, const []);
|
||||
}, []);
|
||||
|
||||
return makeDefaultPage(context,
|
||||
title: "一键诊断 -> ${homeState.scInstalledPath}",
|
||||
@ -40,9 +40,9 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
for (final item in const {
|
||||
"rsi_log": "RSI启动器log",
|
||||
"game_log": "游戏运行log",
|
||||
for (final item in {
|
||||
"rsi_log": S.current.doctor_action_rsi_launcher_log,
|
||||
"game_log": S.current.doctor_action_game_run_log,
|
||||
}.entries)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 6, right: 6),
|
||||
@ -76,14 +76,14 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
))
|
||||
else if (state.checkResult == null ||
|
||||
state.checkResult!.isEmpty) ...[
|
||||
const Expanded(
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 12),
|
||||
Text("扫描完毕,没有找到问题!", maxLines: 1),
|
||||
SizedBox(height: 64),
|
||||
const SizedBox(height: 12),
|
||||
Text(S.current.doctor_info_scan_complete_no_issues, maxLines: 1),
|
||||
const SizedBox(height: 64),
|
||||
],
|
||||
),
|
||||
))
|
||||
@ -104,7 +104,7 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
const SizedBox(height: 12),
|
||||
Text(state.isFixingString.isNotEmpty
|
||||
? state.isFixingString
|
||||
: "正在处理..."),
|
||||
: S.current.doctor_info_processing),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -122,7 +122,7 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
await showToast(context,
|
||||
"您即将前往由 深空治疗中心(QQ群号:536454632 ) 提供的游戏异常救援服务,主要解决游戏安装失败与频繁闪退,如游戏玩法问题,请勿加群。");
|
||||
S.current.doctor_info_game_rescue_service_note);
|
||||
launchUrlString(
|
||||
"https://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=-M4wEme_bCXbUGT4LFKLH0bAYTFt70Ad&authKey=vHVr0TNgRmKu%2BHwywoJV6EiLa7La2VX74Vkyixr05KA0H9TqB6qWlCdY%2B9jLQ4Ha&noverify=0&group_code=536454632");
|
||||
},
|
||||
@ -140,7 +140,7 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
children: [
|
||||
Image.asset("assets/rescue.png", width: 24, height: 24),
|
||||
const SizedBox(width: 12),
|
||||
const Text("需要帮助? 点击加群寻求免费人工支援!"),
|
||||
Text(S.current.doctor_info_need_help),
|
||||
],
|
||||
),
|
||||
)),
|
||||
@ -155,7 +155,7 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
Text(state.lastScreenInfo, maxLines: 1),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
"注意:本工具检测结果仅供参考,若您不理解以下操作,请提供截图给有经验的玩家!",
|
||||
S.current.doctor_info_tool_check_result_note,
|
||||
style: TextStyle(color: Colors.red, fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
@ -177,17 +177,17 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
final errorNames = {
|
||||
"unSupport_system":
|
||||
MapEntry("不支持的操作系统,游戏可能无法运行", "请升级您的系统 (${item.value})"),
|
||||
"no_live_path": MapEntry("安装目录缺少LIVE文件夹,可能导致安装失败",
|
||||
"no_live_path": MapEntry(S.current.doctor_info_result_missing_live_folder,
|
||||
"点击修复为您创建 LIVE 文件夹,完成后重试安装。(${item.value})"),
|
||||
"nvme_PhysicalBytes": MapEntry("新型 NVME 设备,与 RSI 启动器暂不兼容,可能导致安装失败",
|
||||
"nvme_PhysicalBytes": MapEntry(S.current.doctor_info_result_incompatible_nvme_device,
|
||||
"为注册表项添加 ForcedPhysicalSectorSizeInBytes 值 模拟旧设备。硬盘分区(${item.value})"),
|
||||
"eac_file_miss": const MapEntry("EasyAntiCheat 文件丢失",
|
||||
"未在 LIVE 文件夹找到 EasyAntiCheat 文件 或 文件不完整,请使用 RSI 启动器校验文件"),
|
||||
"eac_not_install": const MapEntry("EasyAntiCheat 未安装 或 未正常退出",
|
||||
"EasyAntiCheat 未安装,请点击修复为您一键安装。(在游戏正常启动并结束前,该问题会一直出现,若您因为其他原因游戏闪退,可忽略此条目)"),
|
||||
"eac_file_miss": MapEntry(S.current.doctor_info_result_missing_easyanticheat_files,
|
||||
S.current.doctor_info_result_verify_files_with_rsi_launcher),
|
||||
"eac_not_install": MapEntry(S.current.doctor_info_result_easyanticheat_not_installed,
|
||||
S.current.doctor_info_result_install_easyanticheat),
|
||||
"cn_user_name":
|
||||
const MapEntry("中文用户名!", "中文用户名可能会导致游戏启动/安装错误! 点击修复按钮查看修改教程!"),
|
||||
"cn_install_path": MapEntry("中文安装路径!",
|
||||
MapEntry("中文用户名!", S.current.doctor_info_result_chinese_username_error),
|
||||
"cn_install_path": MapEntry(S.current.doctor_info_result_chinese_install_path,
|
||||
"中文安装路径!这可能会导致游戏 启动/安装 错误!(${item.value}),请在RSI启动器更换安装路径。"),
|
||||
"low_ram": MapEntry(
|
||||
"物理内存过低", "您至少需要 16GB 的物理内存(Memory)才可运行此游戏。(当前大小:${item.value})"),
|
||||
@ -224,9 +224,9 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
: () async {
|
||||
await model.doFix(context, item);
|
||||
},
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(left: 8, right: 8, top: 4, bottom: 4),
|
||||
child: Text("修复"),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 8, right: 8, top: 4, bottom: 4),
|
||||
child: Text(S.current.doctor_info_action_fix),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -262,10 +262,10 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
onPressed: () {
|
||||
launchUrlString(item.value);
|
||||
},
|
||||
child: const Padding(
|
||||
child: Padding(
|
||||
padding:
|
||||
EdgeInsets.only(left: 8, right: 8, top: 4, bottom: 4),
|
||||
child: Text("查看解决方案"),
|
||||
const EdgeInsets.only(left: 8, right: 8, top: 4, bottom: 4),
|
||||
child: Text(S.current.doctor_action_view_solution),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
@ -284,11 +284,11 @@ class HomeGameDoctorUI extends HookConsumerWidget {
|
||||
case "game_log":
|
||||
if (homeState.scInstalledPath == "not_install" ||
|
||||
homeState.scInstalledPath == null) {
|
||||
showToast(context, "请在首页选择游戏安装目录。");
|
||||
showToast(context, S.current.doctor_tip_title_select_game_directory);
|
||||
return;
|
||||
}
|
||||
SystemHelper.openDir("${homeState.scInstalledPath}\\Game.log");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ part 'game_doctor_ui_model.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class HomeGameDoctorState with _$HomeGameDoctorState {
|
||||
const factory HomeGameDoctorState({
|
||||
factory HomeGameDoctorState({
|
||||
@Default(false) bool isChecking,
|
||||
@Default(false) bool isFixing,
|
||||
@Default("") String lastScreenInfo,
|
||||
@ -30,7 +30,7 @@ class HomeGameDoctorState with _$HomeGameDoctorState {
|
||||
class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
@override
|
||||
HomeGameDoctorState build() {
|
||||
state = const HomeGameDoctorState();
|
||||
state = HomeGameDoctorState();
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -43,13 +43,13 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
state = state.copyWith(isFixing: true, isFixingString: "");
|
||||
switch (item.key) {
|
||||
case "unSupport_system":
|
||||
showToast(context, "若您的硬件达标,请尝试安装最新的 Windows 系统。");
|
||||
showToast(context, S.current.doctor_action_result_try_latest_windows);
|
||||
break;
|
||||
case "no_live_path":
|
||||
try {
|
||||
await Directory(item.value).create(recursive: true);
|
||||
if (!context.mounted) break;
|
||||
showToast(context, "创建文件夹成功,请尝试继续下载游戏!");
|
||||
showToast(context, S.current.doctor_action_result_create_folder_success);
|
||||
checkResult.remove(item);
|
||||
state = state.copyWith(checkResult: checkResult);
|
||||
} catch (e) {
|
||||
@ -61,7 +61,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
if (r == "") {
|
||||
if (!context.mounted) break;
|
||||
showToast(context,
|
||||
"修复成功,请尝试重启后继续安装游戏! 若注册表修改操作导致其他软件出现兼容问题,请使用 工具 中的 NVME 注册表清理。");
|
||||
S.current.doctor_action_result_fix_success);
|
||||
checkResult.remove(item);
|
||||
state = state.copyWith(checkResult: checkResult);
|
||||
} else {
|
||||
@ -71,7 +71,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
break;
|
||||
case "eac_file_miss":
|
||||
showToast(
|
||||
context, "未在 LIVE 文件夹找到 EasyAntiCheat 文件 或 文件不完整,请使用 RSI 启动器校验文件");
|
||||
context, S.current.doctor_info_result_verify_files_with_rsi_launcher);
|
||||
break;
|
||||
case "eac_not_install":
|
||||
final eacJsonPath = "${item.value}\\Settings.json";
|
||||
@ -84,7 +84,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
dPrint("${item.value}\\EasyAntiCheat_EOS_Setup.exe install $eacID");
|
||||
if (result.stderr == "") {
|
||||
if (!context.mounted) break;
|
||||
showToast(context, "修复成功,请尝试启动游戏。(若问题无法解决,请使用工具箱的 《重装 EAC》)");
|
||||
showToast(context, S.current.doctor_action_result_game_start_success);
|
||||
checkResult.remove(item);
|
||||
state = state.copyWith(checkResult: checkResult);
|
||||
} else {
|
||||
@ -97,13 +97,13 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
}
|
||||
break;
|
||||
case "cn_user_name":
|
||||
showToast(context, "即将跳转,教程来自互联网,请谨慎操作...");
|
||||
showToast(context, S.current.doctor_action_result_redirect_warning);
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
launchUrlString(
|
||||
"https://btfy.eu.org/?q=5L+u5pS5d2luZG93c+eUqOaIt+WQjeS7juS4reaWh+WIsOiLseaWhw==");
|
||||
break;
|
||||
default:
|
||||
showToast(context, "该问题暂不支持自动处理,请提供截图寻求帮助");
|
||||
showToast(context, S.current.doctor_action_result_issue_not_supported);
|
||||
break;
|
||||
}
|
||||
state = state.copyWith(isFixing: false, isFixingString: "");
|
||||
@ -112,7 +112,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
// ignore: avoid_build_context_in_providers
|
||||
doCheck(BuildContext context) async {
|
||||
if (state.isChecking) return;
|
||||
state = state.copyWith(isChecking: true, lastScreenInfo: "正在分析...");
|
||||
state = state.copyWith(isChecking: true, lastScreenInfo: S.current.doctor_action_analyzing);
|
||||
dPrint("-------- start docker check -----");
|
||||
if (!context.mounted) return;
|
||||
await _statCheck(context);
|
||||
@ -126,9 +126,9 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
|
||||
final checkResult = <MapEntry<String, String>>[];
|
||||
// TODO for debug
|
||||
// checkResult?.add(const MapEntry("unSupport_system", "android"));
|
||||
// checkResult?.add(const MapEntry("nvme_PhysicalBytes", "C"));
|
||||
// checkResult?.add(const MapEntry("no_live_path", ""));
|
||||
// checkResult?.add(MapEntry("unSupport_system", "android"));
|
||||
// checkResult?.add(MapEntry("nvme_PhysicalBytes", "C"));
|
||||
// checkResult?.add(MapEntry("no_live_path", ""));
|
||||
|
||||
await _checkPreInstall(context, scInstalledPath, checkResult);
|
||||
if (!context.mounted) return;
|
||||
@ -137,7 +137,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
await _checkGameRunningLog(context, scInstalledPath, checkResult);
|
||||
|
||||
if (checkResult.isEmpty) {
|
||||
const lastScreenInfo = "分析完毕,没有发现问题";
|
||||
final lastScreenInfo = S.current.doctor_action_result_analysis_no_issue;
|
||||
state = state.copyWith(checkResult: null, lastScreenInfo: lastScreenInfo);
|
||||
} else {
|
||||
final lastScreenInfo = "分析完毕,发现 ${checkResult.length} 个问题";
|
||||
@ -147,7 +147,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
|
||||
if (scInstalledPath == "not_install" && (checkResult.isEmpty)) {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "扫描完毕,没有发现问题,若仍然安装失败,请尝试使用工具箱中的 RSI启动器管理员模式。");
|
||||
showToast(context, S.current.doctor_action_result_toast_scan_no_issue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
Future _checkGameRunningLog(BuildContext context, String scInstalledPath,
|
||||
List<MapEntry<String, String>> checkResult) async {
|
||||
if (scInstalledPath == "not_install") return;
|
||||
const lastScreenInfo = "正在检查:Game.log";
|
||||
final lastScreenInfo = S.current.doctor_action_tip_checking_game_log;
|
||||
state = state.copyWith(lastScreenInfo: lastScreenInfo);
|
||||
final logs = await SCLoggerHelper.getGameRunningLogs(scInstalledPath);
|
||||
if (logs == null) return;
|
||||
@ -174,7 +174,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
Future _checkEAC(BuildContext context, String scInstalledPath,
|
||||
List<MapEntry<String, String>> checkResult) async {
|
||||
if (scInstalledPath == "not_install") return;
|
||||
const lastScreenInfo = "正在检查:EAC";
|
||||
final lastScreenInfo = S.current.doctor_action_info_checking_eac;
|
||||
state = state.copyWith(lastScreenInfo: lastScreenInfo);
|
||||
|
||||
final eacPath = "$scInstalledPath\\EasyAntiCheat";
|
||||
@ -205,7 +205,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
// ignore: avoid_build_context_in_providers
|
||||
Future _checkPreInstall(BuildContext context, String scInstalledPath,
|
||||
List<MapEntry<String, String>> checkResult) async {
|
||||
const lastScreenInfo = "正在检查:运行环境";
|
||||
final lastScreenInfo = S.current.doctor_action_info_checking_runtime;
|
||||
state = state.copyWith(lastScreenInfo: lastScreenInfo);
|
||||
|
||||
if (!(Platform.operatingSystemVersion.contains("Windows 10") ||
|
||||
@ -226,7 +226,7 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
if (ramSize < 16) {
|
||||
checkResult.add(MapEntry("low_ram", "$ramSize"));
|
||||
}
|
||||
state = state.copyWith(lastScreenInfo: "正在检查:安装信息");
|
||||
state = state.copyWith(lastScreenInfo: S.current.doctor_action_info_checking_install_info);
|
||||
// 检查安装分区
|
||||
try {
|
||||
final listData = await SCLoggerHelper.getGameInstallPath(
|
||||
@ -270,4 +270,4 @@ class HomeGameDoctorUIModel extends _$HomeGameDoctorUIModel {
|
||||
dPrint(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -147,7 +147,7 @@ class __$$HomeGameDoctorStateImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
|
||||
class _$HomeGameDoctorStateImpl implements _HomeGameDoctorState {
|
||||
const _$HomeGameDoctorStateImpl(
|
||||
_$HomeGameDoctorStateImpl(
|
||||
{this.isChecking = false,
|
||||
this.isFixing = false,
|
||||
this.lastScreenInfo = "",
|
||||
@ -217,7 +217,7 @@ class _$HomeGameDoctorStateImpl implements _HomeGameDoctorState {
|
||||
}
|
||||
|
||||
abstract class _HomeGameDoctorState implements HomeGameDoctorState {
|
||||
const factory _HomeGameDoctorState(
|
||||
factory _HomeGameDoctorState(
|
||||
{final bool isChecking,
|
||||
final bool isFixing,
|
||||
final String lastScreenInfo,
|
||||
|
@ -7,7 +7,7 @@ part of 'game_doctor_ui_model.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$homeGameDoctorUIModelHash() =>
|
||||
r'1e32d75095de065cf2cdedf444f74ffc753ce66f';
|
||||
r'10e8103fca9565ee6363c093e1d0bf2bc9e68f41';
|
||||
|
||||
/// See also [HomeGameDoctorUIModel].
|
||||
@ProviderFor(HomeGameDoctorUIModel)
|
||||
|
@ -41,7 +41,7 @@ class HomeUI extends HookConsumerWidget {
|
||||
action: homeState.appPlacardData?.link == null
|
||||
? null
|
||||
: Button(
|
||||
child: const Text('查看详情'),
|
||||
child: Text(S.current.doctor_action_view_details),
|
||||
onPressed: () => _showPlacard(context, homeState),
|
||||
),
|
||||
onClose: homeState.appPlacardData?.alwaysShow == true
|
||||
@ -68,7 +68,7 @@ class HomeUI extends HookConsumerWidget {
|
||||
const SizedBox(height: 12),
|
||||
Text(homeState.isFixingString.isNotEmpty
|
||||
? homeState.isFixingString
|
||||
: "正在处理..."),
|
||||
: S.current.doctor_info_processing),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -79,7 +79,7 @@ class HomeUI extends HookConsumerWidget {
|
||||
|
||||
List<Widget> makeIndex(BuildContext context, HomeUIModel model,
|
||||
HomeUIModelState homeState, WidgetRef ref) {
|
||||
const double width = 280;
|
||||
double width = 280;
|
||||
return [
|
||||
Stack(
|
||||
children: [
|
||||
@ -122,16 +122,16 @@ class HomeUI extends HookConsumerWidget {
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text("安装位置:"),
|
||||
Text(S.current.home_install_location),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: ComboBox<String>(
|
||||
value: homeState.scInstalledPath,
|
||||
isExpanded: true,
|
||||
items: [
|
||||
const ComboBoxItem(
|
||||
ComboBoxItem(
|
||||
value: "not_install",
|
||||
child: Text("未安装 或 安装失败"),
|
||||
child: Text(S.current.home_not_installed_or_failed),
|
||||
),
|
||||
for (final path in homeState.scInstallPaths)
|
||||
ComboBoxItem(
|
||||
@ -207,10 +207,10 @@ class HomeUI extends HookConsumerWidget {
|
||||
colorFilter: makeSvgColor(Colors.white),
|
||||
height: 18,
|
||||
),
|
||||
name: "星际公民官网汉化",
|
||||
webTitle: "星际公民官网汉化",
|
||||
name: S.current.home_action_star_citizen_website_localization,
|
||||
webTitle: S.current.home_action_star_citizen_website_localization,
|
||||
webURL: "https://robertsspaceindustries.com",
|
||||
info: "罗伯茨航天工业公司,万物的起源",
|
||||
info: S.current.home_action_info_roberts_space_industries_origin,
|
||||
useLocalization: true,
|
||||
width: width,
|
||||
touchKey: "webLocalization_rsi"),
|
||||
@ -225,10 +225,10 @@ class HomeUI extends HookConsumerWidget {
|
||||
const SizedBox(width: 12),
|
||||
],
|
||||
),
|
||||
name: "UEX 汉化",
|
||||
webTitle: "UEX 汉化",
|
||||
name: S.current.home_action_uex_localization,
|
||||
webTitle: S.current.home_action_uex_localization,
|
||||
webURL: "https://uexcorp.space/",
|
||||
info: "采矿、精炼、贸易计算器、价格、船信息",
|
||||
info: S.current.home_action_info_mining_refining_trade_calculator,
|
||||
useLocalization: true,
|
||||
width: width,
|
||||
touchKey: "webLocalization_uex"),
|
||||
@ -243,15 +243,15 @@ class HomeUI extends HookConsumerWidget {
|
||||
const SizedBox(width: 12),
|
||||
],
|
||||
),
|
||||
name: "DPS计算器汉化",
|
||||
webTitle: "DPS计算器汉化",
|
||||
name: S.current.home_action_dps_calculator_localization,
|
||||
webTitle: S.current.home_action_dps_calculator_localization,
|
||||
webURL: "https://www.erkul.games/live/calculator",
|
||||
info: "在线改船,查询伤害数值和配件购买地点",
|
||||
info: S.current.home_action_info_ship_upgrade_damage_value_query,
|
||||
useLocalization: true,
|
||||
width: width,
|
||||
touchKey: "webLocalization_dps"),
|
||||
const SizedBox(height: 12),
|
||||
const Text("外部浏览器拓展:"),
|
||||
Text(S.current.home_action_external_browser_extension),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
@ -434,11 +434,11 @@ class HomeUI extends HookConsumerWidget {
|
||||
Widget makeIndexActionLists(BuildContext context, HomeUIModel model,
|
||||
HomeUIModelState homeState, WidgetRef ref) {
|
||||
final items = [
|
||||
_HomeItemData("game_doctor", "一键诊断", "一键诊断星际公民常见问题",
|
||||
_HomeItemData("game_doctor", "一键诊断", S.current.home_action_info_one_click_diagnosis_star_citizen,
|
||||
FluentIcons.auto_deploy_settings),
|
||||
_HomeItemData(
|
||||
"localization", "汉化管理", "快捷安装汉化资源", FluentIcons.locale_language),
|
||||
_HomeItemData("performance", "性能优化", "调整引擎配置文件,优化游戏性能",
|
||||
"localization", "汉化管理", S.current.home_action_info_quick_install_localization_resources, FluentIcons.locale_language),
|
||||
_HomeItemData("performance", "性能优化", S.current.home_action_info_engine_config_optimization,
|
||||
FluentIcons.process_meta_task),
|
||||
];
|
||||
return Padding(
|
||||
@ -589,11 +589,11 @@ class HomeUI extends HookConsumerWidget {
|
||||
|
||||
Widget makeGameStatusCard(BuildContext context, HomeUIModel model,
|
||||
double width, HomeUIModelState homeState) {
|
||||
const statusCnName = {
|
||||
"Platform": "平台",
|
||||
"Persistent Universe": "持续宇宙",
|
||||
"Electronic Access": "电子访问",
|
||||
"Arena Commander": "竞技场指挥官"
|
||||
final statusCnName = {
|
||||
"Platform": S.current.home_action_rsi_status_platform,
|
||||
"Persistent Universe": S.current.home_action_rsi_status_persistent_universe,
|
||||
"Electronic Access": S.current.home_action_rsi_status_electronic_access,
|
||||
"Arena Commander": S.current.home_action_rsi_status_arena_commander
|
||||
};
|
||||
|
||||
return Tilt(
|
||||
@ -601,7 +601,7 @@ class HomeUI extends HookConsumerWidget {
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
model.goWebView(context, "RSI 服务器状态",
|
||||
model.goWebView(context, S.current.home_action_rsi_status_rsi_server_status,
|
||||
"https://status.robertsspaceindustries.com/",
|
||||
useLocalization: true);
|
||||
},
|
||||
@ -619,7 +619,7 @@ class HomeUI extends HookConsumerWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text("状态:"),
|
||||
Text(S.current.home_action_rsi_status_status),
|
||||
for (final item in homeState.scServerStatus ?? [])
|
||||
Row(
|
||||
children: [
|
||||
@ -741,7 +741,7 @@ class HomeUI extends HookConsumerWidget {
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return HomeMdContentDialogUI(
|
||||
title: homeState.appPlacardData?.title ?? "公告详情",
|
||||
title: homeState.appPlacardData?.title ?? S.current.home_announcement_details,
|
||||
url: homeState.appPlacardData?.link,
|
||||
);
|
||||
});
|
||||
@ -756,7 +756,7 @@ class HomeUI extends HookConsumerWidget {
|
||||
|
||||
_onMenuTap(BuildContext context, String key, HomeUIModelState homeState,
|
||||
WidgetRef ref) async {
|
||||
const String gameInstallReqInfo =
|
||||
String gameInstallReqInfo =
|
||||
"该功能需要一个有效的安装位置\n\n如果您的游戏未下载完成,请等待下载完毕后使用此功能。\n\n如果您的游戏已下载完毕但未识别,请启动一次游戏后重新打开盒子 或 在设置选项中手动设置安装位置。";
|
||||
switch (key) {
|
||||
case "localization":
|
||||
@ -786,4 +786,4 @@ class _HomeItemData {
|
||||
String name;
|
||||
String infoString;
|
||||
IconData icon;
|
||||
}
|
||||
}
|
@ -77,7 +77,8 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
|
||||
Future<void> reScanPath() async {
|
||||
state = state.copyWith(
|
||||
scInstalledPath: "not_install", lastScreenInfo: "正在扫描 ...");
|
||||
scInstalledPath: "not_install",
|
||||
lastScreenInfo: S.current.home_action_info_scanning);
|
||||
try {
|
||||
final listData = await SCLoggerHelper.getLauncherLogList();
|
||||
if (listData == null) {
|
||||
@ -97,10 +98,11 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
lastScreenInfo: lastScreenInfo);
|
||||
} catch (e) {
|
||||
state = state.copyWith(
|
||||
scInstalledPath: "not_install", lastScreenInfo: "解析 log 文件失败!");
|
||||
scInstalledPath: "not_install",
|
||||
lastScreenInfo: S.current.home_action_info_log_file_parse_fail);
|
||||
AnalyticsApi.touch("error_launchLogs");
|
||||
// showToast(context!,
|
||||
// "解析 log 文件失败! \n请关闭游戏,退出RSI启动器后重试,若仍有问题,请使用工具箱中的 RSI Launcher log 修复。");
|
||||
// "${S.current.home_action_info_log_file_parse_fail} \n请关闭游戏,退出RSI启动器后重试,若仍有问题,请使用工具箱中的 RSI Launcher log 修复。");
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +140,7 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
if (!context.mounted) return;
|
||||
final ok = await showConfirmDialogs(
|
||||
context,
|
||||
"星际公民网站汉化",
|
||||
S.current.home_action_title_star_citizen_website_localization,
|
||||
const Text(
|
||||
"本插功能件仅供大致浏览使用,不对任何有关本功能产生的问题负责!在涉及账号操作前请注意确认网站的原本内容!"
|
||||
"\n\n\n使用此功能登录账号时请确保您的 SC汉化盒子 是从可信任的来源下载。",
|
||||
@ -157,7 +159,8 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
}
|
||||
if (!await WebviewWindow.isWebviewAvailable()) {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "需要安装 WebView2 Runtime");
|
||||
showToast(context,
|
||||
S.current.home_login_action_title_need_webview2_runtime);
|
||||
launchUrlString(
|
||||
"https://developer.microsoft.com/en-us/microsoft-edge/webview2/");
|
||||
return;
|
||||
@ -166,7 +169,10 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
final webViewModel = WebViewModel(context,
|
||||
loginMode: loginMode, loginCallback: rsiLoginCallback);
|
||||
if (useLocalization) {
|
||||
state = state.copyWith(isFixing: true, isFixingString: "正在初始化汉化资源...");
|
||||
state = state.copyWith(
|
||||
isFixing: true,
|
||||
isFixingString:
|
||||
S.current.home_action_info_initializing_resources);
|
||||
try {
|
||||
await webViewModel.initLocalization(state.webLocalizationVersionsData!);
|
||||
} catch (e) {
|
||||
@ -280,14 +286,14 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
_appUpdateTimer?.cancel();
|
||||
_appUpdateTimer = null;
|
||||
// 发送通知
|
||||
final toastNotifier =
|
||||
ToastNotificationManager.createToastNotifierWithId("SC汉化盒子");
|
||||
final toastNotifier = ToastNotificationManager.createToastNotifierWithId(
|
||||
S.current.home_title_app_name);
|
||||
if (toastNotifier != null) {
|
||||
final toastContent = ToastNotificationManager.getTemplateContent(
|
||||
ToastTemplateType.toastText02);
|
||||
if (toastContent != null) {
|
||||
final xmlNodeList = toastContent.getElementsByTagName('text');
|
||||
const title = '汉化有新版本!';
|
||||
final title = S.current.home_localization_new_version_available;
|
||||
final content = '您在 ${updates.first} 安装的汉化有新版本啦!';
|
||||
xmlNodeList.item(0)?.appendChild(toastContent.createTextNode(title));
|
||||
xmlNodeList
|
||||
@ -304,7 +310,7 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
// ignore: avoid_build_context_in_providers
|
||||
launchRSI(BuildContext context) async {
|
||||
if (state.scInstalledPath == "not_install") {
|
||||
showToast(context, "该功能需要一个有效的安装位置");
|
||||
showToast(context, S.current.home_info_valid_installation_required);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -322,11 +328,11 @@ class HomeUIModel extends _$HomeUIModel {
|
||||
} else {
|
||||
final ok = await showConfirmDialogs(
|
||||
context,
|
||||
"一键启动功能提示",
|
||||
S.current.home_info_one_click_launch_warning,
|
||||
const Text("为确保账户安全,一键启动功能已在开发版中禁用,我们将在微软商店版本中提供此功能。"
|
||||
"\n\n微软商店版由微软提供可靠的分发下载与数字签名,可有效防止软件被恶意篡改。\n\n提示:您无需使用盒子启动游戏也可使用汉化。"),
|
||||
confirm: "安装微软商店版本",
|
||||
cancel: "取消");
|
||||
confirm: S.current.home_action_install_microsoft_store_version,
|
||||
cancel: S.current.home_action_cancel);
|
||||
if (ok == true) {
|
||||
await launchUrlString(
|
||||
"https://apps.microsoft.com/detail/9NF3SWFWNKL1?launch=true");
|
||||
|
@ -6,7 +6,7 @@ part of 'home_ui_model.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$homeUIModelHash() => r'a911826a7b852408123bf4b8999ac80c3c582fd4';
|
||||
String _$homeUIModelHash() => r'8268fab911b162f2f3f8a5a86449ea15a759569b';
|
||||
|
||||
/// See also [HomeUIModel].
|
||||
@ProviderFor(HomeUIModel)
|
||||
|
@ -35,13 +35,14 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
AnimatedSize(
|
||||
duration: const Duration(milliseconds: 130),
|
||||
child: state.patchStatus?.key == true &&
|
||||
state.patchStatus?.value == "游戏内置"
|
||||
state.patchStatus?.value ==
|
||||
S.current.home_action_info_game_built_in
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: InfoBar(
|
||||
title: const Text("警告"),
|
||||
content: const Text(
|
||||
"您正在使用游戏内置文本,官方文本目前为机器翻译(截至3.21.0),建议您在下方安装社区汉化。"),
|
||||
title: Text(S.current.home_action_info_warning),
|
||||
content: Text(
|
||||
S.current.localization_info_machine_translation_warning),
|
||||
severity: InfoBarSeverity.info,
|
||||
style: InfoBarThemeData(decoration: (severity) {
|
||||
return const BoxDecoration(
|
||||
@ -56,7 +57,7 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
makeListContainer(
|
||||
"汉化状态",
|
||||
S.current.localization_info_translation_status,
|
||||
[
|
||||
if (state.patchStatus == null)
|
||||
makeLoading(context)
|
||||
@ -80,31 +81,34 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
children: [
|
||||
Text("已安装版本:${state.patchStatus?.value}"),
|
||||
const Spacer(),
|
||||
if (state.patchStatus?.value != "游戏内置")
|
||||
if (state.patchStatus?.value !=
|
||||
S.current.home_action_info_game_built_in)
|
||||
Row(
|
||||
children: [
|
||||
Button(
|
||||
onPressed: model.goFeedback,
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(FluentIcons.feedback),
|
||||
SizedBox(width: 6),
|
||||
Text("汉化反馈"),
|
||||
const Icon(FluentIcons.feedback),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
S.current.localization_action_translation_feedback),
|
||||
],
|
||||
),
|
||||
)),
|
||||
const SizedBox(width: 16),
|
||||
Button(
|
||||
onPressed: model.doDelIniFile(),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(FluentIcons.delete),
|
||||
SizedBox(width: 6),
|
||||
Text("卸载汉化"),
|
||||
const Icon(FluentIcons.delete),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
S.current.localization_action_uninstall_translation),
|
||||
],
|
||||
),
|
||||
)),
|
||||
@ -130,9 +134,9 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
"备注:",
|
||||
style: TextStyle(fontSize: 18),
|
||||
Text(
|
||||
S.current.localization_info_note,
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
@ -154,14 +158,14 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
],
|
||||
context),
|
||||
makeListContainer(
|
||||
"社区汉化",
|
||||
S.current.localization_info_community_translation,
|
||||
[
|
||||
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.withOpacity(.8)),
|
||||
@ -181,7 +185,8 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
? FluentIcons.chevron_up
|
||||
: FluentIcons.chevron_down),
|
||||
const SizedBox(width: 12),
|
||||
const Text("高级功能"),
|
||||
Text(
|
||||
S.current.localization_action_advanced_features),
|
||||
],
|
||||
),
|
||||
onPressed: model.toggleCustomize),
|
||||
@ -192,14 +197,14 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
const SizedBox(height: 12),
|
||||
state.enableCustomize
|
||||
? makeListContainer(
|
||||
"自定义文本",
|
||||
S.current.localization_info_custom_text,
|
||||
[
|
||||
if (state.customizeList == null)
|
||||
makeLoading(context)
|
||||
else if (state.customizeList!.isEmpty)
|
||||
Center(
|
||||
child: Text(
|
||||
"暂无自定义文本",
|
||||
S.current.localization_info_no_custom_text,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.white.withOpacity(.8)),
|
||||
@ -222,13 +227,14 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
Button(
|
||||
onPressed:
|
||||
model.doLocalInstall(file),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 8,
|
||||
right: 8,
|
||||
top: 4,
|
||||
bottom: 4),
|
||||
child: Text("安装"),
|
||||
child: Text(
|
||||
S.current.localization_action_install),
|
||||
))
|
||||
],
|
||||
)
|
||||
@ -238,13 +244,13 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
actions: [
|
||||
Button(
|
||||
onPressed: () => model.openDir(context),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(4),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(FluentIcons.folder_open),
|
||||
SizedBox(width: 6),
|
||||
Text("打开文件夹"),
|
||||
const Icon(FluentIcons.folder_open),
|
||||
const SizedBox(width: 6),
|
||||
Text(S.current.action_open_folder),
|
||||
],
|
||||
),
|
||||
)),
|
||||
@ -324,8 +330,10 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
: FluentIcons.disable_updates),
|
||||
),
|
||||
Text(isInstalled
|
||||
? "已安装"
|
||||
: ((item.value.enable ?? false) ? "安装" : "不可用")),
|
||||
? S.current.localization_info_installed
|
||||
: ((item.value.enable ?? false)
|
||||
? "安装"
|
||||
: S.current.localization_info_unavailable)),
|
||||
],
|
||||
),
|
||||
)),
|
||||
@ -396,7 +404,7 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
),
|
||||
onPressed: model.onBack(context)),
|
||||
const SizedBox(width: 12),
|
||||
const Text("汉化管理"),
|
||||
Text(S.current.home_action_localization_management),
|
||||
const SizedBox(width: 24),
|
||||
Text(
|
||||
"${model.getScInstallPath()}",
|
||||
@ -407,9 +415,9 @@ class LocalizationDialogUI extends HookConsumerWidget {
|
||||
height: 36,
|
||||
child: Row(
|
||||
children: [
|
||||
const Text(
|
||||
"语言: ",
|
||||
style: TextStyle(fontSize: 16),
|
||||
Text(
|
||||
S.current.localization_info_language,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
ComboBox<String>(
|
||||
value: state.selectedLanguage,
|
||||
|
@ -26,7 +26,7 @@ part 'localization_ui_model.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class LocalizationUIState with _$LocalizationUIState {
|
||||
const factory LocalizationUIState({
|
||||
factory LocalizationUIState({
|
||||
String? selectedLanguage,
|
||||
Map<String, ScLocalizationData>? apiLocalizationData,
|
||||
@Default("") String workingVersion,
|
||||
@ -38,7 +38,7 @@ class LocalizationUIState with _$LocalizationUIState {
|
||||
|
||||
@riverpod
|
||||
class LocalizationUIModel extends _$LocalizationUIModel {
|
||||
static const languageSupport = {
|
||||
static const languageSupport = {
|
||||
"chinese_(simplified)": "简体中文",
|
||||
"chinese_(traditional)": "繁體中文",
|
||||
};
|
||||
@ -122,7 +122,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
||||
if (!context.mounted) return;
|
||||
final ok = await showConfirmDialogs(
|
||||
context,
|
||||
"是否移除不兼容的汉化参数",
|
||||
S.current.localization_info_remove_incompatible_translation_params,
|
||||
const Text(
|
||||
"USER.cfg 包含不兼容的汉化参数,这可能是以前的汉化文件的残留信息。\n\n这将可能导致汉化无效或乱码,点击确认为您一键移除(不会影响其他配置)。"),
|
||||
constraints: BoxConstraints(
|
||||
@ -288,7 +288,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
||||
// check file
|
||||
final globalIni = await compute(_readArchive, savePath.absolute.path);
|
||||
if (globalIni.isEmpty) {
|
||||
throw "文件受损,请重新下载";
|
||||
throw S.current.localization_info_corrupted_file;
|
||||
}
|
||||
await _installFormString(globalIni, value.versionName ?? "");
|
||||
} catch (e) {
|
||||
@ -371,7 +371,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
||||
|
||||
static Future<String> _getInstalledIniVersion(String iniPath) async {
|
||||
final iniFile = File(iniPath);
|
||||
if (!await iniFile.exists()) return "游戏内置";
|
||||
if (!await iniFile.exists()) return S.current.home_action_info_game_built_in;
|
||||
final iniStringSplit = (await iniFile.readAsString()).split("\n");
|
||||
for (var i = iniStringSplit.length - 1; i > 0; i--) {
|
||||
if (iniStringSplit[i]
|
||||
@ -382,7 +382,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return "自定义文件";
|
||||
return S.current.localization_info_custom_files;
|
||||
}
|
||||
|
||||
Future<List<String>> checkLangUpdate({bool skipReload = false}) async {
|
||||
@ -408,7 +408,7 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
||||
if (element.path.contains(lang)) {
|
||||
final installedVersion =
|
||||
await _getInstalledIniVersion("${element.path}\\global.ini");
|
||||
if (installedVersion == "游戏内置") continue;
|
||||
if (installedVersion == S.current.home_action_info_game_built_in) continue;
|
||||
final curData = _allVersionLocalizationData[lang];
|
||||
dPrint("check Localization update $scInstallPath");
|
||||
if (!(curData?.keys.contains(installedVersion) ?? false)) {
|
||||
@ -428,4 +428,4 @@ class LocalizationUIModel extends _$LocalizationUIModel {
|
||||
}
|
||||
return updates;
|
||||
}
|
||||
}
|
||||
}
|
@ -160,7 +160,7 @@ class __$$LocalizationUIStateImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
|
||||
class _$LocalizationUIStateImpl implements _LocalizationUIState {
|
||||
const _$LocalizationUIStateImpl(
|
||||
_$LocalizationUIStateImpl(
|
||||
{this.selectedLanguage,
|
||||
final Map<String, ScLocalizationData>? apiLocalizationData,
|
||||
this.workingVersion = "",
|
||||
@ -245,7 +245,7 @@ class _$LocalizationUIStateImpl implements _LocalizationUIState {
|
||||
}
|
||||
|
||||
abstract class _LocalizationUIState implements LocalizationUIState {
|
||||
const factory _LocalizationUIState(
|
||||
factory _LocalizationUIState(
|
||||
{final String? selectedLanguage,
|
||||
final Map<String, ScLocalizationData>? apiLocalizationData,
|
||||
final String workingVersion,
|
||||
|
@ -7,7 +7,7 @@ part of 'localization_ui_model.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$localizationUIModelHash() =>
|
||||
r'654fd38b5f38bee5fd2cab69ab003846a311a4ff';
|
||||
r'33c538abcdbfd667e844d0dcb5b8b7d6264794ab';
|
||||
|
||||
/// See also [LocalizationUIModel].
|
||||
@ProviderFor(LocalizationUIModel)
|
||||
|
@ -30,9 +30,10 @@ class HomePerformanceUI extends HookConsumerWidget {
|
||||
children: [
|
||||
if (state.showGraphicsPerformanceTip)
|
||||
InfoBar(
|
||||
title: const Text("图形优化提示"),
|
||||
content: const Text(
|
||||
"该功能对优化显卡瓶颈有很大帮助,但对 CPU 瓶颈可能起反效果,如果您显卡性能强劲,可以尝试使用更好的画质来获得更高的显卡利用率。",
|
||||
title: Text(
|
||||
S.current.performance_info_graphic_optimization_hint),
|
||||
content: Text(
|
||||
S.current.performance_info_graphic_optimization_warning,
|
||||
),
|
||||
onClose: () => model.closeTip(),
|
||||
),
|
||||
@ -44,15 +45,15 @@ class HomePerformanceUI extends HookConsumerWidget {
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(width: 32),
|
||||
const Text(
|
||||
"预设:",
|
||||
style: TextStyle(fontSize: 18),
|
||||
Text(
|
||||
S.current.performance_action_preset,
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
for (final item in const {
|
||||
"low": "低",
|
||||
"medium": "中",
|
||||
"high": "高",
|
||||
"ultra": "超级"
|
||||
for (final item in {
|
||||
"low": S.current.performance_action_low,
|
||||
"medium": S.current.performance_action_medium,
|
||||
"high": S.current.performance_action_high,
|
||||
"ultra": S.current.performance_action_super
|
||||
}.entries)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 6, right: 6),
|
||||
@ -65,7 +66,8 @@ class HomePerformanceUI extends HookConsumerWidget {
|
||||
onPressed: () =>
|
||||
model.onChangePreProfile(item.key)),
|
||||
),
|
||||
const Text("(预设只修改图形设置)"),
|
||||
Text(
|
||||
S.current.performance_action_info_preset_only_changes_graphics),
|
||||
const Spacer(),
|
||||
Button(
|
||||
onPressed: () => model.refresh(),
|
||||
@ -76,23 +78,23 @@ class HomePerformanceUI extends HookConsumerWidget {
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Button(
|
||||
child: const Text(
|
||||
" 恢复默认 ",
|
||||
style: TextStyle(fontSize: 16),
|
||||
child: Text(
|
||||
S.current.performance_action_reset_to_default,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
onPressed: () => model.clean(context)),
|
||||
const SizedBox(width: 24),
|
||||
Button(
|
||||
child: const Text(
|
||||
"应用",
|
||||
style: TextStyle(fontSize: 16),
|
||||
child: Text(
|
||||
S.current.performance_action_apply,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
onPressed: () => model.applyProfile(false)),
|
||||
const SizedBox(width: 6),
|
||||
Button(
|
||||
child: const Text(
|
||||
"应用并清理着色器(推荐)",
|
||||
style: TextStyle(fontSize: 16),
|
||||
child: Text(
|
||||
S.current.performance_action_apply_and_clear_shaders,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
onPressed: () => model.applyProfile(true)),
|
||||
],
|
||||
|
@ -11,6 +11,7 @@ import 'package:starcitizen_doctor/api/analytics.dart';
|
||||
import 'package:starcitizen_doctor/common/helper/log_helper.dart';
|
||||
import 'package:starcitizen_doctor/common/utils/base_utils.dart';
|
||||
import 'package:starcitizen_doctor/data/game_performance_data.dart';
|
||||
import 'package:starcitizen_doctor/generated/l10n.dart';
|
||||
import 'package:starcitizen_doctor/ui/home/home_ui_model.dart';
|
||||
|
||||
part 'performance_ui_model.freezed.dart';
|
||||
@ -19,7 +20,7 @@ part 'performance_ui_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class HomePerformanceUIState with _$HomePerformanceUIState {
|
||||
const factory HomePerformanceUIState({
|
||||
factory HomePerformanceUIState({
|
||||
@Default(true) bool showGraphicsPerformanceTip,
|
||||
@Default(false) bool enabled,
|
||||
Map<String, List<GamePerformanceData>>? performanceMap,
|
||||
@ -41,7 +42,7 @@ class HomePerformanceUIModel extends _$HomePerformanceUIModel {
|
||||
|
||||
@override
|
||||
HomePerformanceUIState build() {
|
||||
state = const HomePerformanceUIState();
|
||||
state = HomePerformanceUIState();
|
||||
_init();
|
||||
return state;
|
||||
}
|
||||
@ -111,7 +112,7 @@ class HomePerformanceUIModel extends _$HomePerformanceUIModel {
|
||||
switch (key) {
|
||||
case "low":
|
||||
state.performanceMap?.forEach((key, v) {
|
||||
if (key.contains("图形")) {
|
||||
if (key.contains(S.current.performance_info_graphics)) {
|
||||
for (var element in v) {
|
||||
element.value = element.min;
|
||||
}
|
||||
@ -120,7 +121,7 @@ class HomePerformanceUIModel extends _$HomePerformanceUIModel {
|
||||
break;
|
||||
case "medium":
|
||||
state.performanceMap?.forEach((key, v) {
|
||||
if (key.contains("图形")) {
|
||||
if (key.contains(S.current.performance_info_graphics)) {
|
||||
for (var element in v) {
|
||||
element.value = ((element.max ?? 0) ~/ 2);
|
||||
}
|
||||
@ -129,7 +130,7 @@ class HomePerformanceUIModel extends _$HomePerformanceUIModel {
|
||||
break;
|
||||
case "high":
|
||||
state.performanceMap?.forEach((key, v) {
|
||||
if (key.contains("图形")) {
|
||||
if (key.contains(S.current.performance_info_graphics)) {
|
||||
for (var element in v) {
|
||||
element.value = ((element.max ?? 0) / 1.5).ceil();
|
||||
}
|
||||
@ -138,7 +139,7 @@ class HomePerformanceUIModel extends _$HomePerformanceUIModel {
|
||||
break;
|
||||
case "ultra":
|
||||
state.performanceMap?.forEach((key, v) {
|
||||
if (key.contains("图形")) {
|
||||
if (key.contains(S.current.performance_info_graphics)) {
|
||||
for (var element in v) {
|
||||
element.value = element.max;
|
||||
}
|
||||
@ -154,14 +155,14 @@ class HomePerformanceUIModel extends _$HomePerformanceUIModel {
|
||||
}
|
||||
|
||||
clean(BuildContext context) async {
|
||||
state = state.copyWith(workingString: "删除配置文件...");
|
||||
state = state.copyWith(workingString: S.current.performance_info_delete_config_file);
|
||||
if (await confFile.exists()) {
|
||||
await confFile.delete(recursive: true);
|
||||
}
|
||||
state = state.copyWith(workingString: "清理着色器");
|
||||
state = state.copyWith(workingString: S.current.performance_action_clear_shaders);
|
||||
if (!context.mounted) return;
|
||||
await cleanShaderCache(context);
|
||||
state = state.copyWith(workingString: "完成...");
|
||||
state = state.copyWith(workingString: S.current.performance_info_done);
|
||||
await await Future.delayed(const Duration(milliseconds: 300));
|
||||
await _init();
|
||||
state = state.copyWith(workingString: "");
|
||||
@ -180,14 +181,14 @@ class HomePerformanceUIModel extends _$HomePerformanceUIModel {
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
if (context != null && context.mounted) {
|
||||
showToast(context, "清理着色器后首次进入游戏可能会出现卡顿,请耐心等待游戏初始化完毕。");
|
||||
showToast(context, S.current.performance_info_shader_clearing_warning);
|
||||
}
|
||||
}
|
||||
|
||||
applyProfile(bool cleanShader) async {
|
||||
if (state.performanceMap == null) return;
|
||||
AnalyticsApi.touch("performance_apply");
|
||||
state = state.copyWith(workingString: "生成配置文件");
|
||||
state = state.copyWith(workingString: S.current.performance_info_generate_config_file);
|
||||
String conf = "";
|
||||
for (var v in state.performanceMap!.entries) {
|
||||
for (var c in v.value) {
|
||||
@ -206,23 +207,23 @@ class HomePerformanceUIModel extends _$HomePerformanceUIModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
state = state.copyWith(workingString: "写出配置文件");
|
||||
state = state.copyWith(workingString: S.current.performance_info_write_out_config_file);
|
||||
if (await confFile.exists()) {
|
||||
await confFile.delete();
|
||||
}
|
||||
await confFile.create();
|
||||
await confFile.writeAsString(conf);
|
||||
if (cleanShader) {
|
||||
state = state.copyWith(workingString: "清理着色器");
|
||||
state = state.copyWith(workingString: S.current.performance_action_clear_shaders);
|
||||
await cleanShaderCache(null);
|
||||
}
|
||||
state = state.copyWith(workingString: "完成...");
|
||||
state = state.copyWith(workingString: S.current.performance_info_done);
|
||||
await await Future.delayed(const Duration(milliseconds: 300));
|
||||
await _init();
|
||||
state = state.copyWith(workingString: "清理着色器");
|
||||
state = state.copyWith(workingString: S.current.performance_action_clear_shaders);
|
||||
}
|
||||
|
||||
updateState() {
|
||||
state = state.copyWith();
|
||||
}
|
||||
}
|
||||
}
|
@ -138,7 +138,7 @@ class __$$HomePerformanceUIStateImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
|
||||
class _$HomePerformanceUIStateImpl implements _HomePerformanceUIState {
|
||||
const _$HomePerformanceUIStateImpl(
|
||||
_$HomePerformanceUIStateImpl(
|
||||
{this.showGraphicsPerformanceTip = true,
|
||||
this.enabled = false,
|
||||
final Map<String, List<GamePerformanceData>>? performanceMap,
|
||||
@ -203,7 +203,7 @@ class _$HomePerformanceUIStateImpl implements _HomePerformanceUIState {
|
||||
}
|
||||
|
||||
abstract class _HomePerformanceUIState implements HomePerformanceUIState {
|
||||
const factory _HomePerformanceUIState(
|
||||
factory _HomePerformanceUIState(
|
||||
{final bool showGraphicsPerformanceTip,
|
||||
final bool enabled,
|
||||
final Map<String, List<GamePerformanceData>>? performanceMap,
|
||||
|
@ -7,7 +7,7 @@ part of 'performance_ui_model.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$homePerformanceUIModelHash() =>
|
||||
r'85e3390e954b35ffeb7cbacf85619b5a61f866bb';
|
||||
r'0519b95b68b4bffcd940513fa800654c81da2502';
|
||||
|
||||
/// See also [HomePerformanceUIModel].
|
||||
@ProviderFor(HomePerformanceUIModel)
|
||||
|
@ -87,11 +87,11 @@ class IndexUI extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
Map<IconData, String> get pageMenus => {
|
||||
FluentIcons.home: "首页",
|
||||
FluentIcons.game: "大厅",
|
||||
FluentIcons.toolbox: "工具",
|
||||
FluentIcons.settings: "设置",
|
||||
FluentIcons.info: "关于",
|
||||
FluentIcons.home: S.current.app_index_menu_home,
|
||||
FluentIcons.game: S.current.app_index_menu_lobby,
|
||||
FluentIcons.toolbox: S.current.app_index_menu_tools,
|
||||
FluentIcons.settings: S.current.app_index_menu_settings,
|
||||
FluentIcons.info: S.current.app_index_menu_about,
|
||||
};
|
||||
|
||||
List<NavigationPaneItem> getNavigationPaneItems(
|
||||
@ -181,4 +181,4 @@ class IndexUI extends HookConsumerWidget {
|
||||
_goDownloader(BuildContext context) {
|
||||
context.push('/index/downloader');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:starcitizen_doctor/generated/l10n.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
class PartyRoomUI extends HookConsumerWidget {
|
||||
@ -11,22 +12,22 @@ class PartyRoomUI extends HookConsumerWidget {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
"联机大厅,敬请期待 !",
|
||||
style: TextStyle(fontSize: 20),
|
||||
Text(
|
||||
S.current.lobby_online_lobby_coming_soon,
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
launchUrlString("https://wj.qq.com/s2/14112124/f4c8/");
|
||||
},
|
||||
child: const Row(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text("诚邀您参与 "),
|
||||
Text(S.current.lobby_invitation_to_participate),
|
||||
Text(
|
||||
"问卷调查。",
|
||||
style: TextStyle(
|
||||
S.current.lobby_survey,
|
||||
style: const TextStyle(
|
||||
color: Colors.blue,
|
||||
),
|
||||
)
|
||||
@ -37,4 +38,4 @@ class PartyRoomUI extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:starcitizen_doctor/common/conf/const_conf.dart';
|
||||
import 'package:starcitizen_doctor/generated/l10n.dart';
|
||||
import 'package:starcitizen_doctor/ui/settings/settings_ui_model.dart';
|
||||
|
||||
class SettingsUI extends HookConsumerWidget {
|
||||
@ -17,59 +18,59 @@ class SettingsUI extends HookConsumerWidget {
|
||||
margin: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
makeSettingsItem(const Icon(FluentIcons.link, size: 20), "创建设置快捷方式",
|
||||
subTitle: "在桌面创建《SC汉化盒子》快捷方式", onTap: ()=> model.addShortCut(context)),
|
||||
makeSettingsItem(const Icon(FluentIcons.link, size: 20), S.current.setting_action_create_settings_shortcut,
|
||||
subTitle: S.current.setting_action_create_desktop_shortcut, onTap: ()=> model.addShortCut(context)),
|
||||
if (ConstConf.isMSE) ...[
|
||||
const SizedBox(height: 12),
|
||||
makeSettingsItem(
|
||||
const Icon(FluentIcons.reset_device, size: 20), "重置自动密码填充",
|
||||
const Icon(FluentIcons.reset_device, size: 20), S.current.setting_action_reset_auto_password_fill,
|
||||
subTitle:
|
||||
"启用:${sate.isEnableAutoLogin ? "已启用" : "已禁用"} 设备支持:${sate.isDeviceSupportWinHello ? "支持" : "不支持"} 邮箱:${sate.autoLoginEmail} 密码:${sate.isEnableAutoLoginPwd ? "已加密保存" : "未保存"}",
|
||||
onTap: ()=> model.onResetAutoLogin(context)),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
makeSettingsItem(const Icon(FontAwesomeIcons.microchip, size: 20),
|
||||
"启动游戏时忽略能效核心( 适用于Intel 12th+ 处理器 )",
|
||||
S.current.setting_action_ignore_efficiency_cores_on_launch,
|
||||
subTitle:
|
||||
"已设置的核心数量:${sate.inputGameLaunchECore} (此功能适用于首页的盒子一键启动 或 工具中的RSI启动器管理员模式,当为 0 时不启用此功能 )",
|
||||
onTap:()=> model.setGameLaunchECore(context)),
|
||||
const SizedBox(height: 12),
|
||||
makeSettingsItem(const Icon(FluentIcons.folder_open, size: 20),
|
||||
"设置启动器文件(RSI Launcher.exe)",
|
||||
S.current.setting_action_set_launcher_file,
|
||||
subTitle: sate.customLauncherPath != null
|
||||
? "${sate.customLauncherPath}"
|
||||
: "手动设置启动器位置,建议仅在无法自动扫描安装位置时使用",
|
||||
: S.current.setting_action_info_manual_launcher_location_setting,
|
||||
onTap: ()=> model.setLauncherPath(context), onDel: () {
|
||||
model.delName("custom_launcher_path");
|
||||
}),
|
||||
const SizedBox(height: 12),
|
||||
makeSettingsItem(const Icon(FluentIcons.game, size: 20),
|
||||
"设置游戏文件 (StarCitizen.exe)",
|
||||
S.current.setting_action_set_game_file,
|
||||
subTitle: sate.customGamePath != null
|
||||
? "${sate.customGamePath}"
|
||||
: "手动设置游戏安装位置,建议仅在无法自动扫描安装位置时使用",
|
||||
: S.current.setting_action_info_manual_game_location_setting,
|
||||
onTap: ()=> model.setGamePath(context), onDel: () {
|
||||
model.delName("custom_game_path");
|
||||
}),
|
||||
const SizedBox(height: 12),
|
||||
makeSettingsItem(const Icon(FluentIcons.delete, size: 20), "清理汉化文件缓存",
|
||||
makeSettingsItem(const Icon(FluentIcons.delete, size: 20), S.current.setting_action_clear_translation_file_cache,
|
||||
subTitle:
|
||||
"缓存大小 ${(sate.locationCacheSize / 1024 / 1024).toStringAsFixed(2)}MB,清理盒子下载的汉化文件缓存,不会影响已安装的汉化",
|
||||
onTap: ()=> model.cleanLocationCache(context)),
|
||||
const SizedBox(height: 12),
|
||||
makeSettingsItem(
|
||||
const Icon(FluentIcons.speed_high, size: 20), "工具站访问加速",
|
||||
const Icon(FluentIcons.speed_high, size: 20), S.current.setting_action_tool_site_access_acceleration,
|
||||
onTap: () =>
|
||||
model.onChangeToolSiteMirror(!sate.isEnableToolSiteMirrors),
|
||||
subTitle:
|
||||
"使用镜像服务器加速访问 Dps Uex 等工具网站,若访问异常请关闭该功能。 为保护账户安全,任何情况下都不会加速RSI官网。",
|
||||
S.current.setting_action_info_mirror_server_info,
|
||||
onSwitch: model.onChangeToolSiteMirror,
|
||||
switchStatus: sate.isEnableToolSiteMirrors),
|
||||
const SizedBox(height: 12),
|
||||
makeSettingsItem(
|
||||
const Icon(FluentIcons.document_set, size: 20), "查看log",
|
||||
const Icon(FluentIcons.document_set, size: 20), S.current.setting_action_view_log,
|
||||
onTap: () => model.showLogs(),
|
||||
subTitle: "查看汉化盒子的 log 文件,以定位盒子的 bug"),
|
||||
subTitle: S.current.setting_action_info_view_log_file),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -128,4 +129,4 @@ class SettingsUI extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ part 'settings_ui_model.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class SettingsUIState with _$SettingsUIState {
|
||||
const factory SettingsUIState({
|
||||
factory SettingsUIState({
|
||||
@Default(false) isDeviceSupportWinHello,
|
||||
@Default("-") String autoLoginEmail,
|
||||
@Default(false) bool isEnableAutoLogin,
|
||||
@ -38,7 +38,7 @@ class SettingsUIState with _$SettingsUIState {
|
||||
class SettingsUIModel extends _$SettingsUIModel {
|
||||
@override
|
||||
SettingsUIState build() {
|
||||
state = const SettingsUIState();
|
||||
state = SettingsUIState();
|
||||
_initState();
|
||||
return state;
|
||||
}
|
||||
@ -57,15 +57,15 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
}
|
||||
|
||||
Future<void> onResetAutoLogin(BuildContext context) async {
|
||||
final ok = await showConfirmDialogs(context, "确认重置自动填充?",
|
||||
const Text("这将会删除本地的账号记录,或在下次启动游戏时将自动填充选择 ‘否’ 以禁用自动填充。"));
|
||||
final ok = await showConfirmDialogs(context, S.current.setting_action_info_confirm_reset_autofill,
|
||||
Text(S.current.setting_action_info_delete_local_account_warning));
|
||||
if (ok) {
|
||||
final userBox = await Hive.openBox("rsi_account_data");
|
||||
await userBox.deleteFromDisk();
|
||||
Win32Credentials.delete("SCToolbox_RSI_Account_secret");
|
||||
if (!context.mounted) return;
|
||||
|
||||
showToast(context, "已清理自动填充数据");
|
||||
showToast(context, S.current.setting_action_info_autofill_data_cleared);
|
||||
_initState();
|
||||
}
|
||||
}
|
||||
@ -89,7 +89,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
userBox.get("gameLaunch_eCore_count", defaultValue: "0");
|
||||
if (!context.mounted) return;
|
||||
final input = await showInputDialogs(context,
|
||||
title: "请输入要忽略的 CPU 核心数",
|
||||
title: S.current.setting_action_info_enter_cpu_core_to_ignore,
|
||||
content:
|
||||
"Tip:您的设备拥有几个能效核心就输入几,非大小核设备请保持 0\n\n此功能适用于首页的盒子一键启动 或 工具中的 RSI启动器管理员模式,当为 0 时不启用此功能。",
|
||||
initialValue: defaultInput,
|
||||
@ -108,7 +108,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
|
||||
Future<void> setLauncherPath(BuildContext context) async {
|
||||
final r = await FilePicker.platform.pickFiles(
|
||||
dialogTitle: "请选择RSI启动器位置(RSI Launcher.exe)",
|
||||
dialogTitle: S.current.setting_action_info_select_rsi_launcher_location,
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ["exe"]);
|
||||
if (r == null || r.files.firstOrNull?.path == null) return;
|
||||
@ -116,17 +116,17 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
if (fileName.endsWith("\\RSI Launcher.exe")) {
|
||||
await _saveCustomPath("custom_launcher_path", fileName);
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "设置成功,在对应页面点击刷新即可扫描出新路径");
|
||||
showToast(context, S.current.setting_action_info_setting_success);
|
||||
_initState();
|
||||
} else {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "文件有误!");
|
||||
showToast(context, S.current.setting_action_info_file_error);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setGamePath(BuildContext context) async {
|
||||
final r = await FilePicker.platform.pickFiles(
|
||||
dialogTitle: "请选择游戏安装位置(StarCitizen.exe)",
|
||||
dialogTitle: S.current.setting_action_info_select_game_install_location,
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ["exe"]);
|
||||
if (r == null || r.files.firstOrNull?.path == null) return;
|
||||
@ -139,11 +139,11 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
String extractedPath = fileName.replaceFirst(pathRegex, '');
|
||||
await _saveCustomPath("custom_game_path", extractedPath);
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "设置成功,在对应页面点击刷新即可扫描出新路径");
|
||||
showToast(context, S.current.setting_action_info_setting_success);
|
||||
_initState();
|
||||
} else {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "文件有误!");
|
||||
showToast(context, S.current.setting_action_info_file_error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
|
||||
Future<void> cleanLocationCache(BuildContext context) async {
|
||||
final ok = await showConfirmDialogs(
|
||||
context, "确认清理汉化缓存?", const Text("这不会影响已安装的汉化。"));
|
||||
context, "确认清理汉化缓存?", Text(S.current.setting_action_info_clear_cache_warning));
|
||||
if (ok == true) {
|
||||
final dir =
|
||||
Directory("${appGlobalState.applicationSupportDir}/Localizations");
|
||||
@ -187,7 +187,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
|
||||
Future<void> addShortCut(BuildContext context) async {
|
||||
if (ConstConf.isMSE) {
|
||||
showToast(context, "因微软版功能限制,请在接下来打开的窗口中 手动将《SC汉化盒子》拖动到桌面,即可创建快捷方式。");
|
||||
showToast(context, S.current.setting_action_info_microsoft_version_limitation);
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
Process.run("explorer.exe", ["shell:AppsFolder"]);
|
||||
return;
|
||||
@ -208,7 +208,7 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
""";
|
||||
await Process.run(SystemHelper.powershellPath, [script]);
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "创建完毕,请返回桌面查看");
|
||||
showToast(context, S.current.setting_action_info_shortcut_created);
|
||||
}
|
||||
|
||||
_loadToolSiteMirrorState() async {
|
||||
@ -228,4 +228,4 @@ class SettingsUIModel extends _$SettingsUIModel {
|
||||
showLogs() async {
|
||||
SystemHelper.openDir(getDPrintFile()?.absolute.path.replaceAll("/", "\\"));
|
||||
}
|
||||
}
|
||||
}
|
@ -197,7 +197,7 @@ class __$$SettingsUIStateImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
|
||||
class _$SettingsUIStateImpl implements _SettingsUIState {
|
||||
const _$SettingsUIStateImpl(
|
||||
_$SettingsUIStateImpl(
|
||||
{this.isDeviceSupportWinHello = false,
|
||||
this.autoLoginEmail = "-",
|
||||
this.isEnableAutoLogin = false,
|
||||
@ -287,7 +287,7 @@ class _$SettingsUIStateImpl implements _SettingsUIState {
|
||||
}
|
||||
|
||||
abstract class _SettingsUIState implements SettingsUIState {
|
||||
const factory _SettingsUIState(
|
||||
factory _SettingsUIState(
|
||||
{final dynamic isDeviceSupportWinHello,
|
||||
final String autoLoginEmail,
|
||||
final bool isEnableAutoLogin,
|
||||
|
@ -6,7 +6,7 @@ part of 'settings_ui_model.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$settingsUIModelHash() => r'34ac24f658a081350be7d2b3bda810d101b888a1';
|
||||
String _$settingsUIModelHash() => r'de69e289c526d61a6287a9ca7bae848a4d594c20';
|
||||
|
||||
/// See also [SettingsUIModel].
|
||||
@ProviderFor(SettingsUIModel)
|
||||
|
@ -59,12 +59,12 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (description.value == null) ...[
|
||||
const Center(
|
||||
Center(
|
||||
child: Column(
|
||||
children: [
|
||||
ProgressRing(),
|
||||
SizedBox(height: 16),
|
||||
Text("正在获取新版本详情...")
|
||||
const ProgressRing(),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.current.app_upgrade_info_getting_new_version_details)
|
||||
],
|
||||
),
|
||||
)
|
||||
@ -85,7 +85,7 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
color: Colors.white.withOpacity(.1),
|
||||
borderRadius: BorderRadius.circular(7)),
|
||||
child: Text(
|
||||
"提示:当前正在使用分流服务器进行更新,可能会出现下载速度下降,但有助于我们进行成本控制,若下载异常请点击这里跳转手动安装。",
|
||||
S.current.app_upgrade_info_update_server_tip,
|
||||
style: TextStyle(
|
||||
fontSize: 14, color: Colors.white.withOpacity(.7)),
|
||||
),
|
||||
@ -97,7 +97,7 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
Row(
|
||||
children: [
|
||||
Text(progress.value == 100
|
||||
? "正在安装: "
|
||||
? S.current.app_upgrade_info_installing
|
||||
: "正在下载: ${progress.value.toStringAsFixed(2)}% "),
|
||||
Expanded(
|
||||
child: ProgressBar(
|
||||
@ -122,18 +122,18 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
description,
|
||||
isUsingDiversion,
|
||||
progress),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 4, bottom: 4, left: 8, right: 8),
|
||||
child: Text("立即更新"),
|
||||
child: Text(S.current.app_upgrade_action_update_now),
|
||||
)),
|
||||
if (ConstConf.appVersionCode >= (minVersionCode ?? 0))
|
||||
Button(
|
||||
onPressed: () => _doCancel(context),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 4, bottom: 4, left: 8, right: 8),
|
||||
child: Text("下次吧"),
|
||||
child: Text(S.current.app_upgrade_action_next_time),
|
||||
)),
|
||||
],
|
||||
),
|
||||
@ -240,7 +240,7 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
isUpgrading.value = false;
|
||||
progress.value = 0;
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "下载失败,请尝试手动安装!");
|
||||
showToast(context, S.current.app_upgrade_info_download_failed);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -255,9 +255,9 @@ class UpgradeDialogUI extends HookConsumerWidget {
|
||||
isUpgrading.value = false;
|
||||
progress.value = 0;
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "运行失败,请尝试手动安装!");
|
||||
showToast(context, S.current.app_upgrade_info_run_failed);
|
||||
Process.run(SystemHelper.powershellPath,
|
||||
["explorer.exe", "/select,\"$fileName\""]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ class SplashUI extends HookConsumerWidget {
|
||||
final appModel = ref.read(appGlobalModelProvider.notifier);
|
||||
_initApp(context, appModel, stepState, ref);
|
||||
return null;
|
||||
}, const []);
|
||||
}, []);
|
||||
|
||||
return makeDefaultPage(context,
|
||||
content: Center(
|
||||
@ -33,9 +33,9 @@ class SplashUI extends HookConsumerWidget {
|
||||
const SizedBox(height: 32),
|
||||
const ProgressRing(),
|
||||
const SizedBox(height: 32),
|
||||
if (step == 0) const Text("正在检测可用性,这可能需要一点时间..."),
|
||||
if (step == 1) const Text("正在检查更新..."),
|
||||
if (step == 2) const Text("即将完成..."),
|
||||
if (step == 0) Text(S.current.app_splash_checking_availability),
|
||||
if (step == 1) Text(S.current.app_splash_checking_for_updates),
|
||||
if (step == 2) Text(S.current.app_splash_almost_done),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -75,4 +75,4 @@ class SplashUI extends HookConsumerWidget {
|
||||
if (!context.mounted) return;
|
||||
context.go("/index");
|
||||
}
|
||||
}
|
||||
}
|
@ -12,11 +12,11 @@ import 'package:starcitizen_doctor/common/utils/log.dart';
|
||||
class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
const HostsBoosterDialogUI({super.key});
|
||||
|
||||
static const _hostsMap = {
|
||||
static final _hostsMap = {
|
||||
"Recaptcha": ["www.recaptcha.net", "recaptcha.net"],
|
||||
"RSI 官网": ["robertsspaceindustries.com"],
|
||||
"RSI Zendesk 客服站": ["cloudimperiumservicesllc.zendesk.com"],
|
||||
"RSI 客服站": ["support.robertsspaceindustries.com"],
|
||||
S.current.tools_hosts_info_rsi_official_website: ["robertsspaceindustries.com"],
|
||||
S.current.tools_hosts_info_rsi_zendesk: ["cloudimperiumservicesllc.zendesk.com"],
|
||||
S.current.tools_hosts_info_rsi_customer_service: ["support.robertsspaceindustries.com"],
|
||||
};
|
||||
|
||||
@override
|
||||
@ -37,12 +37,12 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
checkedMap.value = Map.from(checkedMap.value);
|
||||
}
|
||||
}
|
||||
workingText.value = "正在查询 DNS 并测试可访问性 请耐心等待...";
|
||||
workingText.value = S.current.tools_hosts_info_dns_query_and_test;
|
||||
final ipsMap = await _doCheckDns(workingMap, checkedMap);
|
||||
workingText.value = "正在写入 Hosts ...";
|
||||
workingText.value = S.current.tools_hosts_info_writing_hosts;
|
||||
if (!context.mounted) return;
|
||||
await _doWriteHosts(ipsMap).unwrap(context: context);
|
||||
workingText.value = "读取配置 ...";
|
||||
workingText.value = S.current.tools_hosts_info_reading_config;
|
||||
await _readHostsState(workingMap, checkedMap);
|
||||
workingText.value = "";
|
||||
}
|
||||
@ -51,7 +51,7 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
// 监听 Hosts 文件变更
|
||||
_readHostsState(workingMap, checkedMap);
|
||||
return null;
|
||||
}, const []);
|
||||
}, []);
|
||||
|
||||
return ContentDialog(
|
||||
constraints:
|
||||
@ -66,17 +66,17 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
onPressed:
|
||||
workingText.value.isEmpty ? Navigator.of(context).pop : null),
|
||||
const SizedBox(width: 12),
|
||||
const Text("Hosts 加速"),
|
||||
Text(S.current.tools_hosts_info_hosts_acceleration),
|
||||
const Spacer(),
|
||||
Button(
|
||||
onPressed: () => _openHostsFile(context),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(3),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(3),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(FluentIcons.open_file),
|
||||
SizedBox(width: 6),
|
||||
Text("打开 Hosts 文件"),
|
||||
const Icon(FluentIcons.open_file),
|
||||
const SizedBox(width: 6),
|
||||
Text(S.current.tools_hosts_info_open_hosts_file),
|
||||
],
|
||||
),
|
||||
))
|
||||
@ -88,15 +88,15 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
const Row(
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(width: 12),
|
||||
Text("状态"),
|
||||
SizedBox(width: 38),
|
||||
Text("站点"),
|
||||
Spacer(),
|
||||
Text("是否启用"),
|
||||
SizedBox(width: 12),
|
||||
const SizedBox(width: 12),
|
||||
Text(S.current.tools_hosts_info_status),
|
||||
const SizedBox(width: 38),
|
||||
Text(S.current.tools_hosts_info_site),
|
||||
const Spacer(),
|
||||
Text(S.current.tools_hosts_info_enable),
|
||||
const SizedBox(width: 12),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
@ -163,10 +163,10 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: FilledButton(
|
||||
onPressed: () => doHost(context),
|
||||
child: const Padding(
|
||||
child: Padding(
|
||||
padding:
|
||||
EdgeInsets.only(top: 3, bottom: 3, left: 12, right: 12),
|
||||
child: Text("一键加速"),
|
||||
const EdgeInsets.only(top: 3, bottom: 3, left: 12, right: 12),
|
||||
child: Text(S.current.tools_hosts_action_one_click_acceleration),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -177,7 +177,7 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
Future<void> _openHostsFile(BuildContext context) async {
|
||||
// 使用管理员权限调用记事本打开 Hosts 文件
|
||||
// 使用管理员权限调用记事本${S.current.tools_hosts_info_open_hosts_file}
|
||||
Process.run(SystemHelper.powershellPath, [
|
||||
"-Command",
|
||||
"Start-Process notepad.exe -Verb runAs -ArgumentList ${SystemHelper.getHostsFilePath()}"
|
||||
@ -287,4 +287,4 @@ class HostsBoosterDialogUI extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -55,14 +55,14 @@ class ToolsUI extends HookConsumerWidget {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
if (state.items.isEmpty)
|
||||
const Expanded(
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ProgressRing(),
|
||||
SizedBox(height: 12),
|
||||
Text("正在扫描..."),
|
||||
const ProgressRing(),
|
||||
const SizedBox(height: 12),
|
||||
Text(S.current.tools_info_scanning),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -170,13 +170,13 @@ class ToolsUI extends HookConsumerWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withAlpha(150),
|
||||
),
|
||||
child: const Center(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ProgressRing(),
|
||||
SizedBox(height: 12),
|
||||
Text("正在处理..."),
|
||||
const ProgressRing(),
|
||||
const SizedBox(height: 12),
|
||||
Text(S.current.doctor_info_processing),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -190,7 +190,7 @@ class ToolsUI extends HookConsumerWidget {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text("游戏安装位置: "),
|
||||
Text(S.current.tools_info_game_install_location),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
@ -228,7 +228,7 @@ class ToolsUI extends HookConsumerWidget {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text("RSI启动器位置:"),
|
||||
Text(S.current.tools_info_rsi_launcher_location),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
@ -260,4 +260,4 @@ class ToolsUI extends HookConsumerWidget {
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@ class ToolsItemData {
|
||||
|
||||
@freezed
|
||||
class ToolsUIState with _$ToolsUIState {
|
||||
const factory ToolsUIState({
|
||||
factory ToolsUIState({
|
||||
@Default(false) bool working,
|
||||
@Default("") String scInstalledPath,
|
||||
@Default("") String rsiLauncherInstalledPath,
|
||||
@ -56,7 +56,7 @@ class ToolsUIState with _$ToolsUIState {
|
||||
class ToolsUIModel extends _$ToolsUIModel {
|
||||
@override
|
||||
ToolsUIState build() {
|
||||
state = const ToolsUIState();
|
||||
state = ToolsUIState();
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -71,35 +71,35 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
items = [
|
||||
ToolsItemData(
|
||||
"systemnfo",
|
||||
"查看系统信息",
|
||||
S.current.tools_action_view_system_info,
|
||||
"查看系统关键信息,用于快速问诊 \n\n耗时操作,请耐心等待。",
|
||||
const Icon(FluentIcons.system, size: 24),
|
||||
onTap: () => _showSystemInfo(context),
|
||||
),
|
||||
ToolsItemData(
|
||||
"p4k_downloader",
|
||||
"P4K 分流下载 / 修复",
|
||||
S.current.tools_action_p4k_download_repair,
|
||||
"使用星际公民中文百科提供的分流下载服务,可用于下载或修复 p4k。 \n资源有限,请勿滥用。",
|
||||
const Icon(FontAwesomeIcons.download, size: 24),
|
||||
onTap: () => _downloadP4k(context),
|
||||
),
|
||||
ToolsItemData(
|
||||
"hosts_booster",
|
||||
"Hosts 加速(实验性)",
|
||||
S.current.tools_action_hosts_acceleration_experimental,
|
||||
"将 IP 信息写入 Hosts 文件,解决部分地区的 DNS 污染导致无法登录官网等问题。\n该功能正在进行第一阶段测试,遇到问题请及时反馈。",
|
||||
const Icon(FluentIcons.virtual_network, size: 24),
|
||||
onTap: () => _doHostsBooster(context),
|
||||
),
|
||||
ToolsItemData(
|
||||
"reinstall_eac",
|
||||
"重装 EasyAntiCheat 反作弊",
|
||||
"若您遇到 EAC 错误,且自动修复无效,请尝试使用此功能重装 EAC。",
|
||||
S.current.tools_action_reinstall_easyanticheat,
|
||||
S.current.tools_action_info_reinstall_eac,
|
||||
const Icon(FluentIcons.game, size: 24),
|
||||
onTap: () => _reinstallEAC(context),
|
||||
),
|
||||
ToolsItemData(
|
||||
"rsilauncher_admin_mode",
|
||||
"RSI Launcher 管理员模式",
|
||||
S.current.tools_action_rsi_launcher_admin_mode,
|
||||
"以管理员身份运行RSI启动器,可能会解决一些问题。\n\n若设置了能效核心屏蔽参数,也会在此应用。",
|
||||
const Icon(FluentIcons.admin, size: 24),
|
||||
onTap: () => _adminRSILauncher(context),
|
||||
@ -136,7 +136,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
return [
|
||||
ToolsItemData(
|
||||
"rsilauncher_log_fix",
|
||||
"RSI Launcher Log 修复",
|
||||
S.current.tools_action_rsi_launcher_log_fix,
|
||||
"在某些情况下 RSI启动器 的 log 文件会损坏,导致无法完成问题扫描,使用此工具清理损坏的 log 文件。\n\n当前日志文件大小:${(logPathLen.toStringAsFixed(4))} MB",
|
||||
const Icon(FontAwesomeIcons.bookBible, size: 24),
|
||||
onTap: () => _rsiLogFix(context),
|
||||
@ -150,7 +150,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
if (nvmePatchStatus)
|
||||
ToolsItemData(
|
||||
"remove_nvme_settings",
|
||||
"移除 nvme 注册表补丁",
|
||||
S.current.tools_action_remove_nvme_registry_patch,
|
||||
"若您使用 nvme 补丁出现问题,请运行此工具。(可能导致游戏 安装/更新 不可用。)\n\n当前补丁状态:${(nvmePatchStatus) ? "已安装" : "未安装"}",
|
||||
const Icon(FluentIcons.hard_drive, size: 24),
|
||||
onTap: nvmePatchStatus
|
||||
@ -159,7 +159,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
await SystemHelper.doRemoveNvmePath();
|
||||
state = state.copyWith(working: false);
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "已移除,重启电脑生效!");
|
||||
showToast(context, S.current.tools_action_info_removed_restart_effective);
|
||||
loadToolsCard(context, skipPathScan: true);
|
||||
}
|
||||
: null,
|
||||
@ -167,8 +167,8 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
if (!nvmePatchStatus)
|
||||
ToolsItemData(
|
||||
"add_nvme_settings",
|
||||
"写入 nvme 注册表补丁",
|
||||
"手动写入NVM补丁,该功能仅在您知道自己在作什么的情况下使用",
|
||||
S.current.tools_action_write_nvme_registry_patch,
|
||||
S.current.tools_action_info_manual_nvme_patch,
|
||||
const Icon(FontAwesomeIcons.cashRegister, size: 24),
|
||||
onTap: () async {
|
||||
state = state.copyWith(working: true);
|
||||
@ -176,7 +176,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
if (r == "") {
|
||||
if (!context.mounted) return;
|
||||
showToast(context,
|
||||
"修复成功,请尝试重启电脑后继续安装游戏! 若注册表修改操作导致其他软件出现兼容问题,请使用 工具 中的 NVME 注册表清理。");
|
||||
S.current.tools_action_info_fix_success_restart);
|
||||
} else {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "修复失败,$r");
|
||||
@ -192,7 +192,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
final gameShaderCachePath = await SCLoggerHelper.getShaderCachePath();
|
||||
return ToolsItemData(
|
||||
"clean_shaders",
|
||||
"清理着色器缓存",
|
||||
S.current.tools_action_clear_shader_cache,
|
||||
"若游戏画面出现异常或版本更新后可使用本工具清理过期的着色器(当大于500M时,建议清理) \n\n缓存大小:${((await SystemHelper.getDirLen(gameShaderCachePath ?? "", skipPath: [
|
||||
"$gameShaderCachePath\\Crashes"
|
||||
])) / 1024 / 1024).toStringAsFixed(4)} MB",
|
||||
@ -207,10 +207,10 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
|
||||
return ToolsItemData(
|
||||
"photography_mode",
|
||||
isEnable ? "关闭摄影模式" : "开启摄影模式",
|
||||
isEnable ? "关闭摄影模式" : S.current.tools_action_open_photography_mode,
|
||||
isEnable
|
||||
? "还原镜头摇晃效果。\n\n@拉邦那 Lapernum 提供参数信息。"
|
||||
: "一键关闭游戏内镜头晃动以便于摄影操作。\n\n @拉邦那 Lapernum 提供参数信息。",
|
||||
: "一键${S.current.action_close}游戏内镜头晃动以便于摄影操作。\n\n @拉邦那 Lapernum 提供参数信息。",
|
||||
const Icon(FontAwesomeIcons.camera, size: 24),
|
||||
onTap: () => _onChangePhotographyMode(context, isEnable),
|
||||
);
|
||||
@ -260,18 +260,18 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
|
||||
if (rsiLauncherInstalledPath == "") {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "未找到 RSI 启动器,请尝试重新安装,或在设置中手动添加。");
|
||||
showToast(context, S.current.tools_action_info_rsi_launcher_not_found);
|
||||
}
|
||||
if (scInstalledPath == "") {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "未找到星际公民游戏安装位置,请至少完成一次游戏启动操作 或在设置中手动添加。");
|
||||
showToast(context, S.current.tools_action_info_star_citizen_not_found);
|
||||
}
|
||||
}
|
||||
|
||||
/// 重装EAC
|
||||
Future<void> _reinstallEAC(BuildContext context) async {
|
||||
if (state.scInstalledPath.isEmpty) {
|
||||
showToast(context, "该功能需要一个有效的游戏安装目录");
|
||||
showToast(context, S.current.tools_action_info_valid_game_directory_needed);
|
||||
return;
|
||||
}
|
||||
state = state.copyWith(working: true);
|
||||
@ -302,7 +302,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
showToast(context,
|
||||
"已为您移除 EAC 文件,接下来将为您打开 RSI 启动器,请您前往 SETTINGS -> VERIFY 重装 EAC。");
|
||||
S.current.tools_action_info_eac_file_removed);
|
||||
_adminRSILauncher(context);
|
||||
} catch (e) {
|
||||
showToast(context, "出现错误:$e");
|
||||
@ -322,7 +322,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
/// 管理员模式运行 RSI 启动器
|
||||
Future _adminRSILauncher(BuildContext context) async {
|
||||
if (state.rsiLauncherInstalledPath == "") {
|
||||
showToast(context, "未找到 RSI 启动器目录,请您尝试手动操作。");
|
||||
showToast(context, S.current.tools_action_info_rsi_launcher_directory_not_found);
|
||||
}
|
||||
SystemHelper.checkAndLaunchRSILauncher(state.rsiLauncherInstalledPath);
|
||||
}
|
||||
@ -333,14 +333,14 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
if (!await File(path!).exists()) {
|
||||
if (!context.mounted) return;
|
||||
showToast(
|
||||
context, "日志文件不存在,请尝试进行一次游戏启动或游戏安装,并退出启动器,若无法解决问题,请尝试将启动器更新至最新版本!");
|
||||
context, S.current.tools_action_info_log_file_not_exist);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
SystemHelper.killRSILauncher();
|
||||
await File(path).delete(recursive: true);
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "清理完毕,请完成一次安装 / 游戏启动 操作。");
|
||||
showToast(context, S.current.tools_action_info_cleanup_complete);
|
||||
SystemHelper.checkAndLaunchRSILauncher(state.rsiLauncherInstalledPath);
|
||||
} catch (_) {
|
||||
if (!context.mounted) return;
|
||||
@ -362,16 +362,16 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => ContentDialog(
|
||||
title: const Text('系统信息'),
|
||||
title: Text(S.current.tools_action_info_system_info_title),
|
||||
content: Text(systemInfo),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * .65,
|
||||
),
|
||||
actions: [
|
||||
FilledButton(
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(top: 2, bottom: 2, left: 8, right: 8),
|
||||
child: Text('关闭'),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 2, bottom: 2, left: 8, right: 8),
|
||||
child: Text(S.current.action_close),
|
||||
),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
@ -404,7 +404,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
|
||||
if ((await SystemHelper.getPID("\"RSI Launcher\"")).isNotEmpty) {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "RSI启动器正在运行!请先关闭启动器再使用此功能!",
|
||||
showToast(context, S.current.tools_action_info_rsi_launcher_running_warning,
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * .35));
|
||||
return;
|
||||
@ -413,7 +413,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
if (!context.mounted) return;
|
||||
await showToast(
|
||||
context,
|
||||
"P4k 是星际公民的核心游戏文件,高达 100GB+,盒子提供的离线下载是为了帮助一些p4k文件下载超级慢的用户 或用于修复官方启动器无法修复的 p4k 文件。"
|
||||
"${S.current.tools_action_info_p4k_file_description_part1}"
|
||||
"\n\n接下来会弹窗询问您保存位置(可以选择星际公民文件夹也可以选择别处),下载完成后请确保 P4K 文件夹位于 LIVE 文件夹内,之后使用星际公民启动器校验更新即可。");
|
||||
|
||||
try {
|
||||
@ -431,7 +431,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
final t = HomeDownloaderUIModel.getTaskTypeAndName(value);
|
||||
if (t.key == "torrent" && t.value.contains("Data.p4k")) {
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "已经有一个p4k下载任务正在进行中,请前往下载管理器查看!");
|
||||
showToast(context, S.current.tools_action_info_p4k_download_in_progress);
|
||||
state = state.copyWith(working: false);
|
||||
return;
|
||||
}
|
||||
@ -447,7 +447,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
if (torrentUrl == "") {
|
||||
state = state.copyWith(working: false);
|
||||
if (!context.mounted) return;
|
||||
showToast(context, "功能维护中,请稍后重试!");
|
||||
showToast(context, S.current.tools_action_info_function_under_maintenance);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -496,7 +496,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
Future<bool> _checkPhotographyStatus(BuildContext context,
|
||||
{bool? setMode}) async {
|
||||
final scInstalledPath = state.scInstalledPath;
|
||||
const keys = ["AudioShakeStrength", "CameraSpringMovement", "ShakeScale"];
|
||||
final keys = ["AudioShakeStrength", "CameraSpringMovement", "ShakeScale"];
|
||||
final attributesFile = File(
|
||||
"$scInstalledPath\\USER\\Client\\0\\Profiles\\default\\attributes.xml");
|
||||
if (setMode == null) {
|
||||
@ -522,7 +522,7 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
} else {
|
||||
if (!await attributesFile.exists()) {
|
||||
if (!context.mounted) return false;
|
||||
showToast(context, "配置文件不存在,请尝试运行一次游戏");
|
||||
showToast(context, S.current.tools_action_info_config_file_not_exist);
|
||||
return false;
|
||||
}
|
||||
final xmlFile = XmlDocument.parse(await attributesFile.readAsString());
|
||||
@ -564,4 +564,4 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
context: context,
|
||||
builder: (BuildContext context) => const HostsBoosterDialogUI());
|
||||
}
|
||||
}
|
||||
}
|
@ -173,7 +173,7 @@ class __$$ToolsUIStateImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
|
||||
class _$ToolsUIStateImpl implements _ToolsUIState {
|
||||
const _$ToolsUIStateImpl(
|
||||
_$ToolsUIStateImpl(
|
||||
{this.working = false,
|
||||
this.scInstalledPath = "",
|
||||
this.rsiLauncherInstalledPath = "",
|
||||
@ -270,7 +270,7 @@ class _$ToolsUIStateImpl implements _ToolsUIState {
|
||||
}
|
||||
|
||||
abstract class _ToolsUIState implements ToolsUIState {
|
||||
const factory _ToolsUIState(
|
||||
factory _ToolsUIState(
|
||||
{final bool working,
|
||||
final String scInstalledPath,
|
||||
final String rsiLauncherInstalledPath,
|
||||
|
@ -6,7 +6,7 @@ part of 'tools_ui_model.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$toolsUIModelHash() => r'4fb78bfe350d792cfdadd3314f4763097ea1b279';
|
||||
String _$toolsUIModelHash() => r'5568cfd422f98a1aff9b8cb9d522c84565fcc289';
|
||||
|
||||
/// See also [ToolsUIModel].
|
||||
@ProviderFor(ToolsUIModel)
|
||||
|
@ -101,7 +101,10 @@ class WebViewModel {
|
||||
if (url.startsWith(org) ||
|
||||
url.startsWith(citizens) ||
|
||||
url.startsWith(organization)) {
|
||||
replaceWords.add({"word": 'members', "replacement": '名成员'});
|
||||
replaceWords.add({
|
||||
"word": 'members',
|
||||
"replacement": S.current.webview_localization_name_member
|
||||
});
|
||||
replaceWords.addAll(_getLocalizationResource("orgs"));
|
||||
}
|
||||
|
||||
@ -111,9 +114,21 @@ class WebViewModel {
|
||||
|
||||
if (url.startsWith(referral)) {
|
||||
replaceWords.addAll([
|
||||
{"word": 'Total recruits: ', "replacement": '总邀请数:'},
|
||||
{"word": 'Prospects ', "replacement": '未完成的邀请'},
|
||||
{"word": 'Recruits', "replacement": '已完成的邀请'},
|
||||
{
|
||||
"word": 'Total recruits: ',
|
||||
"replacement":
|
||||
S.current.webview_localization_total_invitations
|
||||
},
|
||||
{
|
||||
"word": 'Prospects ',
|
||||
"replacement":
|
||||
S.current.webview_localization_unfinished_invitations
|
||||
},
|
||||
{
|
||||
"word": 'Recruits',
|
||||
"replacement":
|
||||
S.current.webview_localization_finished_invitations
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
@ -304,7 +319,9 @@ class WebViewModel {
|
||||
// send toast
|
||||
webview.evaluateJavaScript("SCTShowToast(\"请完成 Windows Hello 验证以填充密码\")");
|
||||
// decrypt
|
||||
if (await localAuth.authenticate(localizedReason: "请输入设备PIN以自动登录RSI账户") !=
|
||||
if (await localAuth.authenticate(
|
||||
localizedReason:
|
||||
S.current.webview_localization_enter_device_pin) !=
|
||||
true) return;
|
||||
final kv = Win32Credentials.read("SCToolbox_RSI_Account_secret");
|
||||
if (kv == null || kv.key != email) return;
|
||||
|
@ -41,9 +41,17 @@ class AutoL10nTools {
|
||||
// read all dart File
|
||||
final dir = Directory('lib/ui');
|
||||
for (var entity in dir.listSync(recursive: true)) {
|
||||
if (entity is File && entity.path.endsWith('.dart')) {
|
||||
if (entity is File &&
|
||||
entity.path.endsWith('.dart') &&
|
||||
!(entity.path.endsWith(".g.dart") &&
|
||||
entity.path.endsWith(".freezed.dart"))) {
|
||||
print('Processing ${entity.path}...');
|
||||
_replaceDartFile(entity, jsonMap);
|
||||
// sort map with value length
|
||||
final newMap = Map.fromEntries(
|
||||
jsonMap.entries.toList()
|
||||
..sort((a, b) => (b.value as String).length.compareTo((a.value as String).length)),
|
||||
);
|
||||
_replaceDartFile(entity, newMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -56,34 +64,51 @@ class AutoL10nTools {
|
||||
}
|
||||
|
||||
void _replaceDartFile(File entity, jsonMap) {
|
||||
final parseResult = parseFile(
|
||||
path: entity.path, featureSet: FeatureSet.latestLanguageVersion());
|
||||
final unit = parseResult.unit;
|
||||
final visitor = ReplaceAstVisitor(jsonMap);
|
||||
unit.accept(visitor);
|
||||
final output = visitor.buffer.toString();
|
||||
entity.writeAsStringSync(output);
|
||||
for (var key in jsonMap.keys) {
|
||||
if (key == "@@locale") continue;
|
||||
final mapValue = jsonMap[key] as String;
|
||||
if (mapValue.contains("{{") && mapValue.contains("}}")) {
|
||||
print("skipping args value === $mapValue");
|
||||
continue;
|
||||
}
|
||||
// 使用 CheckContainsVisitor.visitStringLiteral 获取是否有匹配的值 ,返回 true false
|
||||
final parseResult = parseFile(
|
||||
path: entity.path, featureSet: FeatureSet.latestLanguageVersion());
|
||||
final unit = parseResult.unit;
|
||||
final visitor = CheckContainsVisitor(mapValue);
|
||||
unit.accept(visitor);
|
||||
if (visitor.hasValue) {
|
||||
// replaceDartFile with line
|
||||
final lines = entity.readAsLinesSync();
|
||||
final newLines = <String>[];
|
||||
for (var line in lines) {
|
||||
if (line.contains(mapValue) && !line.contains("\$")) {
|
||||
line = line.replaceAll(mapValue, "\${S.current.$key}");
|
||||
}
|
||||
newLines.add(line);
|
||||
}
|
||||
entity.writeAsStringSync(newLines.join("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ReplaceAstVisitor extends GeneralizingAstVisitor {
|
||||
final Map<String, String> jsonMap;
|
||||
final buffer = StringBuffer();
|
||||
class CheckContainsVisitor extends GeneralizingAstVisitor {
|
||||
final String mapValue;
|
||||
|
||||
ReplaceAstVisitor(this.jsonMap);
|
||||
CheckContainsVisitor(this.mapValue);
|
||||
|
||||
bool hasValue = false;
|
||||
|
||||
@override
|
||||
visitSimpleStringLiteral(SimpleStringLiteral node) {
|
||||
final value = node.value;
|
||||
if (jsonMap.containsValue(value)) {
|
||||
final key = jsonMap.keys.firstWhere((k) => jsonMap[k] == value);
|
||||
buffer.write('S.current.$key');
|
||||
} else {
|
||||
buffer.write(value);
|
||||
visitStringLiteral(StringLiteral node) {
|
||||
final value = node.stringValue ?? "";
|
||||
if (value == mapValue) {
|
||||
print('Found->visitStringLiteral: $value');
|
||||
hasValue = true;
|
||||
}
|
||||
return super.visitSimpleStringLiteral(node);
|
||||
return super.visitStringLiteral(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MyAstVisitor extends GeneralizingAstVisitor {
|
||||
|
@ -4,7 +4,9 @@ void main(List<String> args) {
|
||||
switch (args.elementAtOrNull(0)) {
|
||||
case "gen":
|
||||
return AutoL10nTools().genL10nFiles();
|
||||
case "replace":
|
||||
return AutoL10nTools().replaceL10nFiles();
|
||||
default:
|
||||
throw Exception("cmd not found");
|
||||
throw Exception("cmd not found");
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_riverpod: ^2.4.10
|
||||
riverpod_annotation: ^2.3.4
|
||||
flutter_hooks: ^0.20.5
|
||||
|
Loading…
Reference in New Issue
Block a user