feat: Guide UI

This commit is contained in:
xkeyC 2024-11-03 18:32:12 +08:00
parent 0577b54f9c
commit 8a58719908
21 changed files with 555 additions and 37 deletions

View File

@ -12,6 +12,7 @@ import 'package:path_provider/path_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:starcitizen_doctor/common/conf/const_conf.dart';
import 'package:starcitizen_doctor/common/utils/log.dart';
import 'package:starcitizen_doctor/ui/guide/guide_ui.dart';
import 'package:starcitizen_doctor/ui/home/performance/performance_ui.dart';
import 'package:starcitizen_doctor/ui/splash_ui.dart';
import 'package:device_info_plus/device_info_plus.dart';
@ -92,6 +93,10 @@ GoRouter router(Ref ref) {
myPageBuilder(context, state, const UnP4kcUI()),
),
]),
GoRoute(
path: '/guide',
pageBuilder: (context, state) =>
myPageBuilder(context, state, const GuideUI()))
],
);
}
@ -194,6 +199,8 @@ class AppGlobalModel extends _$AppGlobalModel {
return "${state.applicationSupportDir}/._upgrade";
}
bool isInOnlineMode() => state.networkVersionData != null;
// ignore: avoid_build_context_in_providers
Future<bool> checkUpdate(BuildContext context) async {
if (!ConstConf.isMSE) {

View File

@ -6,7 +6,7 @@ part of 'app.dart';
// RiverpodGenerator
// **************************************************************************
String _$routerHash() => r'26e97b5ddc5161364251fe92399786a0eb9904db';
String _$routerHash() => r'cdf659da46a6dfbab2368a85be2f803f54823142';
/// See also [router].
@ProviderFor(router)
@ -22,7 +22,7 @@ final routerProvider = AutoDisposeProvider<GoRouter>.internal(
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef RouterRef = AutoDisposeProviderRef<GoRouter>;
String _$appGlobalModelHash() => r'cf3d526a61cbadea4252c6f8e096a527d5cef50f';
String _$appGlobalModelHash() => r'69ebc282feb714060ad3f9e0dd21ff55f4c46c0d';
/// See also [AppGlobalModel].
@ProviderFor(AppGlobalModel)

View File

@ -35,6 +35,8 @@ class URLConf {
"$rssApiHome/baidu/tieba/user/%E7%81%AC%E7%81%ACG%E7%81%AC%E7%81%AC&";
static const feedbackUrl = "https://txc.qq.com/products/614843";
static const feedbackFAQUrl =
"https://support.qq.com/products/410309/faqs-more/?id=160084";
static String get devReleaseUrl => "$gitApiHome/SCToolBox/Release/releases";

View File

@ -176,6 +176,8 @@ class MessageLookup extends MessageLookupByLibrary {
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
"about_action_btn_faq":
MessageLookupByLibrary.simpleMessage("Common problem"),
"about_action_email":
MessageLookupByLibrary.simpleMessage("Email: xkeyc@qq.com"),
"about_action_open_source":
@ -474,6 +476,23 @@ class MessageLookup extends MessageLookupByLibrary {
"downloader_title_downloading":
MessageLookupByLibrary.simpleMessage("Downloading"),
"downloader_title_ended": MessageLookupByLibrary.simpleMessage("Over"),
"guide_action_complete_setup":
MessageLookupByLibrary.simpleMessage("Complete settings"),
"guide_action_get_help": MessageLookupByLibrary.simpleMessage("Help"),
"guide_action_info_no_game_path_warning":
MessageLookupByLibrary.simpleMessage(
"You have not chose the game installation path, do you confirm the complete settings?\n\nAfter the guidance page is turned off, you need to manually go to the setting page to operate."),
"guide_action_info_no_launcher_path_warning":
MessageLookupByLibrary.simpleMessage(
"You have not chose the launcher installation path, do you confirm the complete settings?\n\nAfter the guidance page is turned off, you need to manually go to the setting page to operate."),
"guide_dialog_confirm_complete_setup":
MessageLookupByLibrary.simpleMessage(
"Confirm the complete settings?"),
"guide_info_check_settings": MessageLookupByLibrary.simpleMessage(
"Please check whether the following settings are correct. If there is any error, please click on the right icon to correct it."),
"guide_info_game_download_note": MessageLookupByLibrary.simpleMessage(
"* If your game is being downloaded, start the game once after completing the download and click the refresh button. If you only use the starter to enhance the Chineseization, make sure that the starter path is correct and click to complete the settings."),
"guide_title_welcome": MessageLookupByLibrary.simpleMessage("Welcome"),
"home_action_cancel": MessageLookupByLibrary.simpleMessage("Cancel"),
"home_action_dps_calculator_localization":
MessageLookupByLibrary.simpleMessage("DPS calculator Localization"),
@ -975,6 +994,11 @@ class MessageLookup extends MessageLookupByLibrary {
"Tool station access acceleration"),
"setting_action_view_log":
MessageLookupByLibrary.simpleMessage("View log"),
"setting_toast_select_game_file": MessageLookupByLibrary.simpleMessage(
"Select the corresponding game file to: bin64/StarCitizen.exe"),
"setting_toast_select_launcher_exe":
MessageLookupByLibrary.simpleMessage(
"Select the starter EXE file: \"RSI LAUNCHER.EXE\""),
"settings_app_language":
MessageLookupByLibrary.simpleMessage("Language"),
"settings_app_language_auto":

View File

@ -161,6 +161,7 @@ class MessageLookup extends MessageLookupByLibrary {
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
"about_action_btn_faq": MessageLookupByLibrary.simpleMessage("常见问题"),
"about_action_email":
MessageLookupByLibrary.simpleMessage("邮箱: xkeyc@qq.com"),
"about_action_open_source": MessageLookupByLibrary.simpleMessage("开源"),
@ -428,6 +429,22 @@ class MessageLookup extends MessageLookupByLibrary {
"downloader_title_downloading":
MessageLookupByLibrary.simpleMessage("下载中"),
"downloader_title_ended": MessageLookupByLibrary.simpleMessage("已结束"),
"guide_action_complete_setup":
MessageLookupByLibrary.simpleMessage("完成设置"),
"guide_action_get_help": MessageLookupByLibrary.simpleMessage("获取帮助"),
"guide_action_info_no_game_path_warning":
MessageLookupByLibrary.simpleMessage(
"您尚未选择游戏安装路径,是否确认完成设置?\n\n引导页关闭后,需要您手动前往设置页操作。"),
"guide_action_info_no_launcher_path_warning":
MessageLookupByLibrary.simpleMessage(
"您尚未选择启动器安装路径,是否确认完成设置?\n\n引导页关闭后,需要您手动前往设置页操作。"),
"guide_dialog_confirm_complete_setup":
MessageLookupByLibrary.simpleMessage("确认完成设置?"),
"guide_info_check_settings": MessageLookupByLibrary.simpleMessage(
"请检查以下设置是否正确,如有错误请点击右侧图标更正后继续使用"),
"guide_info_game_download_note": MessageLookupByLibrary.simpleMessage(
"* 若您的游戏正在下载,请在完成下载后启动一次游戏,并点击刷新按钮。若您只使用启动器增强汉化,确保启动器路径正确后点击完成设置即可"),
"guide_title_welcome": MessageLookupByLibrary.simpleMessage("欢迎"),
"home_action_cancel": MessageLookupByLibrary.simpleMessage("取消"),
"home_action_dps_calculator_localization":
MessageLookupByLibrary.simpleMessage("DPS计算器汉化"),
@ -870,6 +887,11 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("工具站访问加速"),
"setting_action_view_log":
MessageLookupByLibrary.simpleMessage("查看log"),
"setting_toast_select_game_file": MessageLookupByLibrary.simpleMessage(
"选择对应游戏文件到: Bin64/StarCitizen.exe"),
"setting_toast_select_launcher_exe":
MessageLookupByLibrary.simpleMessage(
"选择启动器 exe 文件“RSI Launcher.exe”"),
"settings_app_language": MessageLookupByLibrary.simpleMessage("语言"),
"settings_app_language_auto":
MessageLookupByLibrary.simpleMessage("自动"),

View File

@ -161,6 +161,7 @@ class MessageLookup extends MessageLookupByLibrary {
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
"about_action_btn_faq": MessageLookupByLibrary.simpleMessage("常見問題"),
"about_action_email": MessageLookupByLibrary.simpleMessage("電子信箱"),
"about_action_open_source":
MessageLookupByLibrary.simpleMessage("專案開源 (Github)"),
@ -427,6 +428,22 @@ class MessageLookup extends MessageLookupByLibrary {
"downloader_title_downloading":
MessageLookupByLibrary.simpleMessage("下載中"),
"downloader_title_ended": MessageLookupByLibrary.simpleMessage("已結束"),
"guide_action_complete_setup":
MessageLookupByLibrary.simpleMessage("完成設置"),
"guide_action_get_help": MessageLookupByLibrary.simpleMessage("獲取幫助"),
"guide_action_info_no_game_path_warning":
MessageLookupByLibrary.simpleMessage(
"您尚未選擇遊戲安裝路徑,是否確認完成設置?\n\n引導頁關閉後,需要您手動前往設置頁操作。"),
"guide_action_info_no_launcher_path_warning":
MessageLookupByLibrary.simpleMessage(
"您尚未選擇啟動器安裝路徑,是否確認完成設置?\n\n引導頁關閉後,需要您手動前往設置頁操作。"),
"guide_dialog_confirm_complete_setup":
MessageLookupByLibrary.simpleMessage("確認完成設置?"),
"guide_info_check_settings": MessageLookupByLibrary.simpleMessage(
"請檢查以下設置是否正確,如有錯誤請點擊右側圖標更正後繼續使用"),
"guide_info_game_download_note": MessageLookupByLibrary.simpleMessage(
"* 若您的遊戲正在下載,請在完成下載後啟動一次遊戲,並點擊刷新按鈕。若您只使用啟動器增強漢化,確保啟動器路徑正確後點擊完成設置即可"),
"guide_title_welcome": MessageLookupByLibrary.simpleMessage("歡迎"),
"home_action_cancel": MessageLookupByLibrary.simpleMessage("取消"),
"home_action_dps_calculator_localization":
MessageLookupByLibrary.simpleMessage("DPS計算器"),
@ -874,6 +891,11 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("網站加速"),
"setting_action_view_log":
MessageLookupByLibrary.simpleMessage("查看log"),
"setting_toast_select_game_file": MessageLookupByLibrary.simpleMessage(
"選擇對應遊戲文件到: Bin64/StarCitizen.exe"),
"setting_toast_select_launcher_exe":
MessageLookupByLibrary.simpleMessage(
"選擇啟動器 exe 文件“RSI Launcher.exe”"),
"settings_app_language": MessageLookupByLibrary.simpleMessage("語言"),
"settings_app_language_auto":
MessageLookupByLibrary.simpleMessage("自動"),

View File

@ -4913,6 +4913,116 @@ class S {
args: [],
);
}
/// `Common problem`
String get about_action_btn_faq {
return Intl.message(
'Common problem',
name: 'about_action_btn_faq',
desc: '',
args: [],
);
}
/// `Welcome`
String get guide_title_welcome {
return Intl.message(
'Welcome',
name: 'guide_title_welcome',
desc: '',
args: [],
);
}
/// `Please check whether the following settings are correct. If there is any error, please click on the right icon to correct it.`
String get guide_info_check_settings {
return Intl.message(
'Please check whether the following settings are correct. If there is any error, please click on the right icon to correct it.',
name: 'guide_info_check_settings',
desc: '',
args: [],
);
}
/// `* If your game is being downloaded, start the game once after completing the download and click the refresh button. If you only use the starter to enhance the Chineseization, make sure that the starter path is correct and click to complete the settings.`
String get guide_info_game_download_note {
return Intl.message(
'* If your game is being downloaded, start the game once after completing the download and click the refresh button. If you only use the starter to enhance the Chineseization, make sure that the starter path is correct and click to complete the settings.',
name: 'guide_info_game_download_note',
desc: '',
args: [],
);
}
/// `Help`
String get guide_action_get_help {
return Intl.message(
'Help',
name: 'guide_action_get_help',
desc: '',
args: [],
);
}
/// `Complete settings`
String get guide_action_complete_setup {
return Intl.message(
'Complete settings',
name: 'guide_action_complete_setup',
desc: '',
args: [],
);
}
/// `Confirm the complete settings?`
String get guide_dialog_confirm_complete_setup {
return Intl.message(
'Confirm the complete settings?',
name: 'guide_dialog_confirm_complete_setup',
desc: '',
args: [],
);
}
/// `You have not chose the launcher installation path, do you confirm the complete settings?\n\nAfter the guidance page is turned off, you need to manually go to the setting page to operate.`
String get guide_action_info_no_launcher_path_warning {
return Intl.message(
'You have not chose the launcher installation path, do you confirm the complete settings?\n\nAfter the guidance page is turned off, you need to manually go to the setting page to operate.',
name: 'guide_action_info_no_launcher_path_warning',
desc: '',
args: [],
);
}
/// `You have not chose the game installation path, do you confirm the complete settings?\n\nAfter the guidance page is turned off, you need to manually go to the setting page to operate.`
String get guide_action_info_no_game_path_warning {
return Intl.message(
'You have not chose the game installation path, do you confirm the complete settings?\n\nAfter the guidance page is turned off, you need to manually go to the setting page to operate.',
name: 'guide_action_info_no_game_path_warning',
desc: '',
args: [],
);
}
/// `Select the starter EXE file: "RSI LAUNCHER.EXE"`
String get setting_toast_select_launcher_exe {
return Intl.message(
'Select the starter EXE file: "RSI LAUNCHER.EXE"',
name: 'setting_toast_select_launcher_exe',
desc: '',
args: [],
);
}
/// `Select the corresponding game file to: bin64/StarCitizen.exe`
String get setting_toast_select_game_file {
return Intl.message(
'Select the corresponding game file to: bin64/StarCitizen.exe',
name: 'setting_toast_select_game_file',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<S> {

View File

@ -968,5 +968,16 @@
"settings_title_general": "Universal",
"settings_item_dns": "Use built -in DNS",
"settings_item_dns_info": "After opening, the problem of DNS pollution in some areas may be solved",
"settings_title_game": "Game"
"settings_title_game": "Game",
"about_action_btn_faq": "Common problem",
"guide_title_welcome": "Welcome",
"guide_info_check_settings": "Please check whether the following settings are correct. If there is any error, please click on the right icon to correct it.",
"guide_info_game_download_note": "* If your game is being downloaded, start the game once after completing the download and click the refresh button. If you only use the starter to enhance the Chineseization, make sure that the starter path is correct and click to complete the settings.",
"guide_action_get_help": "Help",
"guide_action_complete_setup": "Complete settings",
"guide_dialog_confirm_complete_setup": "Confirm the complete settings?",
"guide_action_info_no_launcher_path_warning": "You have not chose the launcher installation path, do you confirm the complete settings?\n\nAfter the guidance page is turned off, you need to manually go to the setting page to operate.",
"guide_action_info_no_game_path_warning": "You have not chose the game installation path, do you confirm the complete settings?\n\nAfter the guidance page is turned off, you need to manually go to the setting page to operate.",
"setting_toast_select_launcher_exe": "Select the starter EXE file: \"RSI LAUNCHER.EXE\"",
"setting_toast_select_game_file": "Select the corresponding game file to: bin64/StarCitizen.exe"
}

View File

@ -801,5 +801,16 @@
"settings_title_general": "通用",
"settings_item_dns": "使用内置 DNS",
"settings_item_dns_info": "开启后可能解决部分地区 DNS 污染的问题",
"settings_title_game": "游戏"
"settings_title_game": "游戏",
"about_action_btn_faq": "常见问题",
"guide_title_welcome": "欢迎",
"guide_info_check_settings": "请检查以下设置是否正确,如有错误请点击右侧图标更正后继续使用",
"guide_info_game_download_note": "* 若您的游戏正在下载,请在完成下载后启动一次游戏,并点击刷新按钮。若您只使用启动器增强汉化,确保启动器路径正确后点击完成设置即可",
"guide_action_get_help": "获取帮助",
"guide_action_complete_setup": "完成设置",
"guide_dialog_confirm_complete_setup": "确认完成设置?",
"guide_action_info_no_launcher_path_warning": "您尚未选择启动器安装路径,是否确认完成设置?\n\n引导页关闭后需要您手动前往设置页操作。",
"guide_action_info_no_game_path_warning": "您尚未选择游戏安装路径,是否确认完成设置?\n\n引导页关闭后需要您手动前往设置页操作。",
"setting_toast_select_launcher_exe": "选择启动器 exe 文件“RSI Launcher.exe”",
"setting_toast_select_game_file": "选择对应游戏文件到: Bin64/StarCitizen.exe"
}

View File

@ -801,5 +801,16 @@
"settings_title_general": "通用",
"settings_item_dns": "使用內置 DNS",
"settings_item_dns_info": "開啟後可能解決部分地區 DNS 污染的問題",
"settings_title_game": "遊戲"
"settings_title_game": "遊戲",
"about_action_btn_faq": "常見問題",
"guide_title_welcome": "歡迎",
"guide_info_check_settings": "請檢查以下設置是否正確,如有錯誤請點擊右側圖標更正後繼續使用",
"guide_info_game_download_note": "* 若您的遊戲正在下載,請在完成下載後啟動一次遊戲,並點擊刷新按鈕。若您只使用啟動器增強漢化,確保啟動器路徑正確後點擊完成設置即可",
"guide_action_get_help": "獲取幫助",
"guide_action_complete_setup": "完成設置",
"guide_dialog_confirm_complete_setup": "確認完成設置?",
"guide_action_info_no_launcher_path_warning": "您尚未選擇啟動器安裝路徑,是否確認完成設置?\n\n引導頁關閉後需要您手動前往設置頁操作。",
"guide_action_info_no_game_path_warning": "您尚未選擇遊戲安裝路徑,是否確認完成設置?\n\n引導頁關閉後需要您手動前往設置頁操作。",
"setting_toast_select_launcher_exe": "選擇啟動器 exe 文件“RSI Launcher.exe”",
"setting_toast_select_game_file": "選擇對應遊戲文件到: Bin64/StarCitizen.exe"
}

View File

@ -99,6 +99,23 @@ class AboutUI extends HookConsumerWidget {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Row(
children: [
const Icon(FontAwesomeIcons.question),
const SizedBox(width: 8),
Text(
S.current.about_action_btn_faq,
style: TextStyle(
fontSize: 14, color: Colors.white.withOpacity(.6)),
),
],
),
onPressed: () {
launchUrlString(URLConf.feedbackFAQUrl);
},
),
const SizedBox(width: 24),
IconButton(
icon: Row(
children: [
@ -262,4 +279,4 @@ class AboutUI extends HookConsumerWidget {
}
}
}
}
}

248
lib/ui/guide/guide_ui.dart Normal file
View File

@ -0,0 +1,248 @@
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:starcitizen_doctor/common/conf/const_conf.dart';
import 'package:starcitizen_doctor/common/conf/url_conf.dart';
import 'package:starcitizen_doctor/ui/settings/settings_ui_model.dart';
import 'package:starcitizen_doctor/ui/tools/tools_ui_model.dart';
import 'package:starcitizen_doctor/widgets/widgets.dart';
import 'package:url_launcher/url_launcher_string.dart';
class GuideUI extends HookConsumerWidget {
const GuideUI({super.key});
static const version = 1;
@override
Widget build(BuildContext context, WidgetRef ref) {
final toolsState = ref.watch(toolsUIModelProvider);
final toolsModel = ref.read(toolsUIModelProvider.notifier);
final settingModel = ref.read(settingsUIModelProvider.notifier);
useEffect(() {
addPostFrameCallback(() {
toolsModel.reScanPath(context, checkActive: true, skipToast: true);
});
return null;
}, []);
return makeDefaultPage(
context,
automaticallyImplyLeading: false,
titleRow: Align(
alignment: AlignmentDirectional.centerStart,
child: Row(
children: [
Image.asset(
"assets/app_logo_mini.png",
width: 20,
height: 20,
fit: BoxFit.cover,
),
const SizedBox(width: 12),
Text(
S.current.app_index_version_info(
ConstConf.appVersion, ConstConf.isMSE ? "" : " Dev"),
)
],
),
),
content: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset("assets/app_logo.png", width: 192, height: 192),
SizedBox(height: 12),
Text(
S.current.guide_title_welcome,
style: TextStyle(
fontSize: 38,
),
),
SizedBox(height: 24),
Text(S.current.guide_info_check_settings),
SizedBox(height: 32),
Container(
padding: EdgeInsets.symmetric(horizontal: 32),
child: Row(
children: [
Expanded(
child: Column(
children: [
makeGameLauncherPathSelect(
context, toolsModel, toolsState, settingModel),
const SizedBox(height: 12),
makeGamePathSelect(
context, toolsModel, toolsState, settingModel),
],
),
),
SizedBox(width: 12),
Button(
onPressed: () => toolsModel.reScanPath(context,
checkActive: true, skipToast: true),
child: const Padding(
padding: EdgeInsets.only(
top: 30, bottom: 30, left: 12, right: 12),
child: Icon(FluentIcons.refresh),
),
),
],
)),
SizedBox(height: 12),
Padding(
padding: const EdgeInsets.only(right: 32, left: 32),
child: Row(
children: [
Expanded(
child: Text(
S.current.guide_info_game_download_note,
style: TextStyle(
fontSize: 12, color: Colors.white.withOpacity(.6)),
textAlign: TextAlign.end,
),
),
],
),
),
SizedBox(height: 38),
Row(
children: [
Spacer(),
Button(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: Text(S.current.guide_action_get_help),
),
onPressed: () {
launchUrlString(URLConf.feedbackFAQUrl);
},
),
SizedBox(width: 24),
FilledButton(
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: Text(S.current.guide_action_complete_setup),
),
onPressed: () async {
if (toolsState.rsiLauncherInstallPaths.isEmpty) {
final ok = await showConfirmDialogs(
context,
S.current.guide_dialog_confirm_complete_setup,
Text(S.current
.guide_action_info_no_launcher_path_warning));
if (!ok) return;
}
if (toolsState.scInstallPaths.isEmpty) {
if (!context.mounted) return;
final ok = await showConfirmDialogs(
context,
S.current.guide_dialog_confirm_complete_setup,
Text(S
.current.guide_action_info_no_game_path_warning));
if (!ok) return;
}
final appConf = await Hive.openBox("app_conf");
await appConf.put("guide_version", version);
if (!context.mounted) return;
context.pop();
},
),
SizedBox(width: 32),
],
),
SizedBox(height: 128),
],
),
),
);
}
Widget makeGameLauncherPathSelect(BuildContext context, ToolsUIModel model,
ToolsUIState state, SettingsUIModel settingModel) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(S.current.tools_info_rsi_launcher_location),
const SizedBox(width: 6),
Expanded(
child: SizedBox(
height: 36,
child: ComboBox<String>(
isExpanded: true,
value: state.rsiLauncherInstalledPath,
items: [
for (final path in state.rsiLauncherInstallPaths)
ComboBoxItem(
value: path,
child: Text(path),
)
],
onChanged: (v) {
model.onChangeLauncherPath(v!);
},
),
),
),
const SizedBox(width: 8),
Button(
child: const Padding(
padding: EdgeInsets.all(6),
child: Icon(FluentIcons.folder_search),
),
onPressed: () async {
await settingModel.setLauncherPath(context);
if (!context.mounted) return;
model.reScanPath(context, checkActive: true, skipToast: true);
},
),
],
);
}
Widget makeGamePathSelect(BuildContext context, ToolsUIModel model,
ToolsUIState state, SettingsUIModel settingModel) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(S.current.tools_info_game_install_location),
const SizedBox(width: 6),
Expanded(
child: SizedBox(
height: 36,
child: ComboBox<String>(
isExpanded: true,
value: state.scInstalledPath,
items: [
for (final path in state.scInstallPaths)
ComboBoxItem(
value: path,
child: Text(path),
)
],
onChanged: (v) {
model.onChangeGamePath(v!);
},
),
),
),
const SizedBox(width: 8),
Button(
child: const Padding(
padding: EdgeInsets.all(6),
child: Icon(FluentIcons.folder_search),
),
onPressed: () async {
await settingModel.setGamePath(context);
if (!context.mounted) return;
model.reScanPath(context, checkActive: true, skipToast: true);
})
],
);
}
}

View File

@ -1,12 +1,15 @@
import 'package:card_swiper/card_swiper.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_tilt/flutter_tilt.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart';
import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:starcitizen_doctor/api/analytics.dart';
import 'package:starcitizen_doctor/ui/guide/guide_ui.dart';
import 'package:starcitizen_doctor/ui/tools/tools_ui_model.dart';
import 'package:starcitizen_doctor/widgets/widgets.dart';
import 'package:url_launcher/url_launcher_string.dart';
@ -25,6 +28,12 @@ class HomeUI extends HookConsumerWidget {
final homeState = ref.watch(homeUIModelProvider);
final model = ref.watch(homeUIModelProvider.notifier);
ref.watch(localizationUIModelProvider);
useEffect(() {
_checkGuide(context, model);
return null;
}, const []);
return Stack(
children: [
Center(
@ -819,6 +828,19 @@ class HomeUI extends HookConsumerWidget {
}
return const Color.fromRGBO(49, 227, 88, .8);
}
Future _checkGuide(BuildContext context, HomeUIModel model) async {
final appConf = await Hive.openBox("app_conf");
final guideVersion = appConf.get("guide_version", defaultValue: 0);
if (guideVersion < GuideUI.version) {
await Future.delayed(Duration(milliseconds: 200));
if (!context.mounted) return;
await context.push("/guide");
await model.reScanPath();
await model.checkLocalizationUpdate();
return;
}
}
}
class _HomeItemData {

View File

@ -16,11 +16,6 @@ class SettingsUI extends HookConsumerWidget {
final appGlobalModel = ref.read(appGlobalModelProvider.notifier);
return ListView(padding: const EdgeInsets.all(16), children: [
makeTitle(S.current.settings_title_general),
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)),
const SizedBox(height: 12),
makeSettingsItem(
const Icon(FontAwesomeIcons.language, size: 20),
S.current.settings_app_language,
@ -32,8 +27,13 @@ class SettingsUI extends HookConsumerWidget {
showGoIcon: false,
),
const SizedBox(height: 12),
makeSettingsItem(
const Icon(FontAwesomeIcons.networkWired, size: 20), S.current.settings_item_dns,
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)),
const SizedBox(height: 12),
makeSettingsItem(const Icon(FontAwesomeIcons.networkWired, size: 20),
S.current.settings_item_dns,
subTitle: S.current.settings_item_dns_info,
switchStatus: sate.isUseInternalDNS,
onSwitch: model.onChangeUseInternalDNS,
@ -177,4 +177,4 @@ class SettingsUI extends HookConsumerWidget {
),
);
}
}
}

View File

@ -69,10 +69,13 @@ class SettingsUIModel extends _$SettingsUIModel {
}
Future<void> setLauncherPath(BuildContext context) async {
await showToast(context, "${S.current.setting_toast_select_launcher_exe}");
final r = await FilePicker.platform.pickFiles(
dialogTitle: S.current.setting_action_info_select_rsi_launcher_location,
type: FileType.custom,
allowedExtensions: ["exe"]);
dialogTitle: S.current.setting_action_info_select_rsi_launcher_location,
type: FileType.custom,
allowedExtensions: ["exe"],
lockParentWindow: true,
);
if (r == null || r.files.firstOrNull?.path == null) return;
final fileName = r.files.first.path!;
if (fileName.endsWith("\\RSI Launcher.exe")) {
@ -87,10 +90,13 @@ class SettingsUIModel extends _$SettingsUIModel {
}
Future<void> setGamePath(BuildContext context) async {
await showToast(context, "${S.current.setting_toast_select_game_file}");
final r = await FilePicker.platform.pickFiles(
dialogTitle: S.current.setting_action_info_select_game_install_location,
type: FileType.custom,
allowedExtensions: ["exe"]);
dialogTitle: S.current.setting_action_info_select_game_install_location,
type: FileType.custom,
allowedExtensions: ["exe"],
lockParentWindow: true,
);
if (r == null || r.files.firstOrNull?.path == null) return;
final fileName = r.files.first.path!;
dPrint(fileName);
@ -211,7 +217,8 @@ class SettingsUIModel extends _$SettingsUIModel {
Future _loadUseInternalDNS() async {
final userBox = await Hive.openBox("app_conf");
final isUseInternalDNS = userBox.get("isUseInternalDNS", defaultValue: false);
final isUseInternalDNS =
userBox.get("isUseInternalDNS", defaultValue: false);
state = state.copyWith(isUseInternalDNS: isUseInternalDNS);
}
}
}

View File

@ -6,7 +6,7 @@ part of 'settings_ui_model.dart';
// RiverpodGenerator
// **************************************************************************
String _$settingsUIModelHash() => r'de58885742e29aae6b1226c16c03655a6a6b018d';
String _$settingsUIModelHash() => r'27193efaa8964e8a097daf8dbabf93bb1fdcab3c';
/// See also [SettingsUIModel].
@ProviderFor(SettingsUIModel)

View File

@ -75,7 +75,7 @@ class SplashUI extends HookConsumerWidget {
await _showAlert(context, appConf);
}
try {
await URLConf.checkHost();
await URLConf.checkHost();
} catch (e) {
dPrint("checkHost Error:$e");
}

View File

@ -208,8 +208,8 @@ class ToolsUI extends HookConsumerWidget {
)
],
onChanged: (v) {
model.loadToolsCard(context, skipPathScan: true);
model.onChangeGamePath(v!);
model.loadToolsCard(context, skipPathScan: true);
},
),
),
@ -253,8 +253,8 @@ class ToolsUI extends HookConsumerWidget {
)
],
onChanged: (v) {
model.loadToolsCard(context, skipPathScan: true);
model.onChangeLauncherPath(v!);
model.loadToolsCard(context, skipPathScan: true);
},
),
),

View File

@ -11,6 +11,7 @@ import 'package:go_router/go_router.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:starcitizen_doctor/api/analytics.dart';
import 'package:starcitizen_doctor/api/api.dart';
import 'package:starcitizen_doctor/common/conf/const_conf.dart';
import 'package:starcitizen_doctor/common/conf/url_conf.dart';
import 'package:starcitizen_doctor/common/helper/log_helper.dart';
import 'package:starcitizen_doctor/common/helper/system_helper.dart';
@ -245,7 +246,8 @@ class ToolsUIModel extends _$ToolsUIModel {
/// -----------------------------------------------------------------------------------------
/// -----------------------------------------------------------------------------------------
Future<void> reScanPath(BuildContext context) async {
Future<void> reScanPath(BuildContext context,
{bool checkActive = false, bool skipToast = false}) async {
var scInstallPaths = <String>[];
var rsiLauncherInstallPaths = <String>[];
var scInstalledPath = "";
@ -266,7 +268,7 @@ class ToolsUIModel extends _$ToolsUIModel {
return;
}
scInstallPaths = await SCLoggerHelper.getGameInstallPath(listData,
checkExists: false, withVersion: ["LIVE", "PTU", "EPTU"]);
checkExists: checkActive, withVersion: ConstConf.gameChannels);
if (scInstallPaths.isNotEmpty) {
scInstalledPath = scInstallPaths.first;
}
@ -282,13 +284,15 @@ class ToolsUIModel extends _$ToolsUIModel {
showToast(context, S.current.tools_action_info_log_file_parse_failed);
}
if (rsiLauncherInstalledPath == "") {
if (!context.mounted) return;
showToast(context, S.current.tools_action_info_rsi_launcher_not_found);
}
if (scInstalledPath == "") {
if (!context.mounted) return;
showToast(context, S.current.tools_action_info_star_citizen_not_found);
if (!skipToast) {
if (rsiLauncherInstalledPath == "") {
if (!context.mounted) return;
showToast(context, S.current.tools_action_info_rsi_launcher_not_found);
}
if (scInstalledPath == "") {
if (!context.mounted) return;
showToast(context, S.current.tools_action_info_star_citizen_not_found);
}
}
}

View File

@ -6,7 +6,7 @@ part of 'tools_ui_model.dart';
// RiverpodGenerator
// **************************************************************************
String _$toolsUIModelHash() => r'cc75badc7ad810d2a8cef3d2a5188b1b68079aa3';
String _$toolsUIModelHash() => r'b0f314abe69c56d4e5e1ac0e89d848b55daabb4f';
/// See also [ToolsUIModel].
@ProviderFor(ToolsUIModel)

View File

@ -71,7 +71,7 @@ class AutoL10nTools {
if (entity is File &&
entity.path.endsWith('.dart') &&
!(entity.path.endsWith(".g.dart") &&
entity.path.endsWith(".freezed.dart"))) {
!entity.path.endsWith(".freezed.dart"))) {
print('Processing ${entity.path}...');
// sort map with value length
final newMap = Map<String, dynamic>.fromEntries(