feat:重新实现汉化更新

This commit is contained in:
xkeyC 2024-03-10 21:25:03 +08:00
parent d54a84698c
commit 1c73217ea7
3 changed files with 124 additions and 26 deletions

View File

@ -15,6 +15,7 @@ import 'dialogs/home_countdown_dialog_ui.dart';
import 'dialogs/home_md_content_dialog_ui.dart'; import 'dialogs/home_md_content_dialog_ui.dart';
import 'home_ui_model.dart'; import 'home_ui_model.dart';
import 'localization/localization_dialog_ui.dart'; import 'localization/localization_dialog_ui.dart';
import 'localization/localization_ui_model.dart';
class HomeUI extends HookConsumerWidget { class HomeUI extends HookConsumerWidget {
const HomeUI({super.key}); const HomeUI({super.key});
@ -23,6 +24,7 @@ class HomeUI extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final homeState = ref.watch(homeUIModelProvider); final homeState = ref.watch(homeUIModelProvider);
final model = ref.watch(homeUIModelProvider.notifier); final model = ref.watch(homeUIModelProvider.notifier);
ref.watch(localizationUIModelProvider);
return Stack( return Stack(
children: [ children: [
Center( Center(
@ -48,7 +50,7 @@ class HomeUI extends HookConsumerWidget {
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
], ],
...makeIndex(context, model, homeState) ...makeIndex(context, model, homeState, ref)
], ],
), ),
), ),
@ -75,8 +77,8 @@ class HomeUI extends HookConsumerWidget {
); );
} }
List<Widget> makeIndex( List<Widget> makeIndex(BuildContext context, HomeUIModel model,
BuildContext context, HomeUIModel model, HomeUIModelState homeState) { HomeUIModelState homeState, WidgetRef ref) {
const double width = 280; const double width = 280;
return [ return [
Stack( Stack(
@ -176,7 +178,7 @@ class HomeUI extends HookConsumerWidget {
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text(homeState.lastScreenInfo, maxLines: 1), Text(homeState.lastScreenInfo, maxLines: 1),
makeIndexActionLists(context, model, homeState), makeIndexActionLists(context, model, homeState, ref),
]; ];
} }
@ -426,8 +428,8 @@ class HomeUI extends HookConsumerWidget {
return const FaIcon(FontAwesomeIcons.rss, size: 14); return const FaIcon(FontAwesomeIcons.rss, size: 14);
} }
Widget makeIndexActionLists( Widget makeIndexActionLists(BuildContext context, HomeUIModel model,
BuildContext context, HomeUIModel model, HomeUIModelState homeState) { HomeUIModelState homeState, WidgetRef ref) {
final items = [ final items = [
_HomeItemData("game_doctor", "一键诊断", "一键诊断星际公民常见问题", _HomeItemData("game_doctor", "一键诊断", "一键诊断星际公民常见问题",
FluentIcons.auto_deploy_settings), FluentIcons.auto_deploy_settings),
@ -447,7 +449,7 @@ class HomeUI extends HookConsumerWidget {
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = items.elementAt(index); final item = items.elementAt(index);
return HoverButton( return HoverButton(
onPressed: () => _onMenuTap(context, item.key, homeState), onPressed: () => _onMenuTap(context, item.key, homeState, ref),
builder: (BuildContext context, Set<ButtonStates> states) { builder: (BuildContext context, Set<ButtonStates> states) {
return Container( return Container(
width: 300, width: 300,
@ -749,8 +751,8 @@ class HomeUI extends HookConsumerWidget {
context: context, builder: (context) => const HomeCountdownDialogUI()); context: context, builder: (context) => const HomeCountdownDialogUI());
} }
_onMenuTap( _onMenuTap(BuildContext context, String key, HomeUIModelState homeState,
BuildContext context, String key, HomeUIModelState homeState) async { WidgetRef ref) async {
const String gameInstallReqInfo = const String gameInstallReqInfo =
"该功能需要一个有效的安装位置\n\n如果您的游戏未下载完成,请等待下载完毕后使用此功能。\n\n如果您的游戏已下载完毕但未识别,请启动一次游戏后重新打开盒子 或 在设置选项中手动设置安装位置。"; "该功能需要一个有效的安装位置\n\n如果您的游戏未下载完成,请等待下载完毕后使用此功能。\n\n如果您的游戏已下载完毕但未识别,请启动一次游戏后重新打开盒子 或 在设置选项中手动设置安装位置。";
switch (key) { switch (key) {
@ -759,10 +761,13 @@ class HomeUI extends HookConsumerWidget {
showToast(context, gameInstallReqInfo); showToast(context, gameInstallReqInfo);
break; break;
} }
final model = ref.watch(homeUIModelProvider.notifier);
model.checkLocalizationUpdate();
await showDialog( await showDialog(
context: context, context: context,
dismissWithEsc: false, dismissWithEsc: false,
builder: (BuildContext context) => const LocalizationDialogUI()); builder: (BuildContext context) => const LocalizationDialogUI());
model.checkLocalizationUpdate(skipReload: true);
break; break;
default: default:
context.push("/index/$key"); context.push("/index/$key");

View File

@ -16,6 +16,7 @@ import 'package:starcitizen_doctor/common/conf/url_conf.dart';
import 'package:starcitizen_doctor/common/helper/log_helper.dart'; import 'package:starcitizen_doctor/common/helper/log_helper.dart';
import 'package:starcitizen_doctor/common/helper/system_helper.dart'; import 'package:starcitizen_doctor/common/helper/system_helper.dart';
import 'package:starcitizen_doctor/common/io/rs_http.dart'; import 'package:starcitizen_doctor/common/io/rs_http.dart';
import 'package:starcitizen_doctor/common/utils/async.dart';
import 'package:starcitizen_doctor/common/utils/base_utils.dart'; import 'package:starcitizen_doctor/common/utils/base_utils.dart';
import 'package:starcitizen_doctor/common/utils/log.dart'; import 'package:starcitizen_doctor/common/utils/log.dart';
import 'package:starcitizen_doctor/common/utils/provider.dart'; import 'package:starcitizen_doctor/common/utils/provider.dart';
@ -26,8 +27,10 @@ import 'package:starcitizen_doctor/ui/home/dialogs/home_game_login_dialog_ui.dar
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
import 'package:html/parser.dart' as html; import 'package:html/parser.dart' as html;
import 'package:html/dom.dart' as html_dom; import 'package:html/dom.dart' as html_dom;
import 'package:windows_ui/windows_ui.dart';
import '../webview/webview.dart'; import '../webview/webview.dart';
import 'localization/localization_ui_model.dart';
part 'home_ui_model.freezed.dart'; part 'home_ui_model.freezed.dart';
@ -199,7 +202,7 @@ class HomeUIModel extends _$HomeUIModel {
); );
_appUpdateTimer = Timer.periodic(const Duration(minutes: 30), (timer) { _appUpdateTimer = Timer.periodic(const Duration(minutes: 30), (timer) {
_checkLocalizationUpdate(); checkLocalizationUpdate();
}); });
ref.onDispose(() { ref.onDispose(() {
@ -237,7 +240,7 @@ class HomeUIModel extends _$HomeUIModel {
dPrint(e); dPrint(e);
} }
// check Localization update // check Localization update
_checkLocalizationUpdate(); checkLocalizationUpdate();
} }
Future<void> _updateSCServerStatus() async { Future<void> _updateSCServerStatus() async {
@ -262,7 +265,41 @@ class HomeUIModel extends _$HomeUIModel {
} }
} }
void _checkLocalizationUpdate() {} Future<void> checkLocalizationUpdate({bool skipReload = false}) async {
dPrint("_checkLocalizationUpdate");
final updates = await (ref.read(localizationUIModelProvider.notifier))
.checkLangUpdate(skipReload: skipReload)
.unwrap<List<String>>();
if (updates == null || updates.isEmpty) {
state = state.copyWith(localizationUpdateInfo: null);
return;
}
state =
state.copyWith(localizationUpdateInfo: MapEntry(updates.first, true));
if (_appUpdateTimer != null) {
_appUpdateTimer?.cancel();
_appUpdateTimer = null;
//
final toastNotifier =
ToastNotificationManager.createToastNotifierWithId("SC汉化盒子");
if (toastNotifier != null) {
final toastContent = ToastNotificationManager.getTemplateContent(
ToastTemplateType.toastText02);
if (toastContent != null) {
final xmlNodeList = toastContent.getElementsByTagName('text');
const title = '汉化有新版本!';
final content = '您在 ${updates.first} 安装的汉化有新版本啦!';
xmlNodeList.item(0)?.appendChild(toastContent.createTextNode(title));
xmlNodeList
.item(1)
?.appendChild(toastContent.createTextNode(content));
final toastNotification =
ToastNotification.createToastNotification(toastContent);
toastNotifier.show(toastNotification);
}
}
}
}
// ignore: avoid_build_context_in_providers // ignore: avoid_build_context_in_providers
launchRSI(BuildContext context) async { launchRSI(BuildContext context) async {

View File

@ -9,6 +9,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:starcitizen_doctor/api/analytics.dart'; import 'package:starcitizen_doctor/api/analytics.dart';
import 'package:starcitizen_doctor/api/api.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/conf/url_conf.dart';
import 'package:starcitizen_doctor/common/helper/system_helper.dart'; import 'package:starcitizen_doctor/common/helper/system_helper.dart';
import 'package:starcitizen_doctor/common/io/rs_http.dart'; import 'package:starcitizen_doctor/common/io/rs_http.dart';
@ -64,7 +65,10 @@ class LocalizationUIModel extends _$LocalizationUIModel {
return state; return state;
} }
_init() async { Future<void> _init() async {
if (_scInstallPath == "not_install") {
return;
}
if (!_customizeDir.existsSync()) { if (!_customizeDir.existsSync()) {
await _customizeDir.create(recursive: true); await _customizeDir.create(recursive: true);
} }
@ -75,14 +79,20 @@ class LocalizationUIModel extends _$LocalizationUIModel {
_customizeDirListenSub?.cancel(); _customizeDirListenSub?.cancel();
_customizeDirListenSub = null; _customizeDirListenSub = null;
}); });
_loadData(); await _loadData();
} }
_loadData() async { final Map<String, Map<String, ScLocalizationData>>
_allVersionLocalizationData = {};
Future<void> _loadData() async {
_allVersionLocalizationData.clear();
await _updateStatus(); await _updateStatus();
_scanCustomizeDir(); _scanCustomizeDir();
final l = await Api.getScLocalizationData(state.selectedLanguage!).unwrap(); for (var lang in languageSupport.keys) {
final l = await Api.getScLocalizationData(lang).unwrap();
if (l != null) { if (l != null) {
if (lang == state.selectedLanguage) {
final apiLocalizationData = <String, ScLocalizationData>{}; final apiLocalizationData = <String, ScLocalizationData>{};
for (var element in l) { for (var element in l) {
final isPTU = !_scInstallPath.contains("LIVE"); final isPTU = !_scInstallPath.contains("LIVE");
@ -94,6 +104,13 @@ class LocalizationUIModel extends _$LocalizationUIModel {
} }
state = state.copyWith(apiLocalizationData: apiLocalizationData); state = state.copyWith(apiLocalizationData: apiLocalizationData);
} }
final map = <String, ScLocalizationData>{};
for (var element in l) {
map[element.versionName ?? ""] = element;
}
_allVersionLocalizationData[lang] = map;
}
}
} }
void checkUserCfg(BuildContext context) async { void checkUserCfg(BuildContext context) async {
@ -368,7 +385,46 @@ class LocalizationUIModel extends _$LocalizationUIModel {
return "自定义文件"; return "自定义文件";
} }
Future checkLangUpdate() async { Future<List<String>> checkLangUpdate({bool skipReload = false}) async {
if (_scInstallPath == "not_install") {
return [];
}
if (!skipReload || (state.apiLocalizationData?.isEmpty ?? true)) {
await _init();
}
final homeState = ref.read(homeUIModelProvider);
if (homeState.scInstallPaths.isEmpty) return [];
List<String> updates = [];
for (var scInstallPath in homeState.scInstallPaths) {
//
final scDataDir = Directory("$scInstallPath\\data\\Localization");
//
final dirList = await scDataDir.list().toList();
for (var element in dirList) {
for (var lang in languageSupport.keys) {
if (element.path.contains(lang)) {
final installedVersion =
await _getInstalledIniVersion("${element.path}\\global.ini");
final curData = _allVersionLocalizationData[lang];
dPrint("check Localization update $scInstallPath");
if (!(curData?.keys.contains(installedVersion) ?? false)) {
// has update
for (var channel in ConstConf.gameChannels) {
if (scInstallPath.contains(channel)) {
dPrint("check Localization update: has update -> $channel");
updates.add(channel);
}
}
} else {
dPrint("check Localization update: up to date");
}
}
}
}
}
return updates;
} }
} }