feat: Unp4kcState errorMessage

This commit is contained in:
xkeyC 2024-05-05 16:47:42 +08:00
parent 8d2b4983c0
commit 3e5a258cf8
7 changed files with 259 additions and 223 deletions

View File

@ -8,7 +8,7 @@ import 'package:starcitizen_doctor/common/utils/log.dart';
class BinaryModuleConf { class BinaryModuleConf {
static const _modules = { static const _modules = {
"aria2c": "0", "aria2c": "0",
"unp4kc": "0", "unp4kc": "1",
}; };
static Future extractModule(List<String> modules, String workingDir) async { static Future extractModule(List<String> modules, String workingDir) async {

View File

@ -29,6 +29,7 @@ class Unp4kcState with _$Unp4kcState {
required String curPath, required String curPath,
String? endMessage, String? endMessage,
MapEntry<String, String>? tempOpenFile, MapEntry<String, String>? tempOpenFile,
@Default("") String errorMessage,
}) = _Unp4kcState; }) = _Unp4kcState;
} }
@ -72,6 +73,12 @@ class Unp4kCModel extends _$Unp4kCModel {
break; break;
case RsProcessStreamDataType.error: case RsProcessStreamDataType.error:
dPrint("[unp4kc] stderr: ${event.data}"); dPrint("[unp4kc] stderr: ${event.data}");
if (state.errorMessage.isEmpty) {
state = state.copyWith(errorMessage: event.data);
} else {
state = state.copyWith(
errorMessage: "${state.errorMessage}\n${event.data}");
}
break; break;
case RsProcessStreamDataType.exit: case RsProcessStreamDataType.exit:
dPrint("[unp4kc] exit: ${event.data}"); dPrint("[unp4kc] exit: ${event.data}");

View File

@ -24,6 +24,7 @@ mixin _$Unp4kcState {
String? get endMessage => throw _privateConstructorUsedError; String? get endMessage => throw _privateConstructorUsedError;
MapEntry<String, String>? get tempOpenFile => MapEntry<String, String>? get tempOpenFile =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
String get errorMessage => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
$Unp4kcStateCopyWith<Unp4kcState> get copyWith => $Unp4kcStateCopyWith<Unp4kcState> get copyWith =>
@ -42,7 +43,8 @@ abstract class $Unp4kcStateCopyWith<$Res> {
MemoryFileSystem? fs, MemoryFileSystem? fs,
String curPath, String curPath,
String? endMessage, String? endMessage,
MapEntry<String, String>? tempOpenFile}); MapEntry<String, String>? tempOpenFile,
String errorMessage});
} }
/// @nodoc /// @nodoc
@ -64,6 +66,7 @@ class _$Unp4kcStateCopyWithImpl<$Res, $Val extends Unp4kcState>
Object? curPath = null, Object? curPath = null,
Object? endMessage = freezed, Object? endMessage = freezed,
Object? tempOpenFile = freezed, Object? tempOpenFile = freezed,
Object? errorMessage = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
startUp: null == startUp startUp: null == startUp
@ -90,6 +93,10 @@ class _$Unp4kcStateCopyWithImpl<$Res, $Val extends Unp4kcState>
? _value.tempOpenFile ? _value.tempOpenFile
: tempOpenFile // ignore: cast_nullable_to_non_nullable : tempOpenFile // ignore: cast_nullable_to_non_nullable
as MapEntry<String, String>?, as MapEntry<String, String>?,
errorMessage: null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
) as $Val); ) as $Val);
} }
} }
@ -108,7 +115,8 @@ abstract class _$$Unp4kcStateImplCopyWith<$Res>
MemoryFileSystem? fs, MemoryFileSystem? fs,
String curPath, String curPath,
String? endMessage, String? endMessage,
MapEntry<String, String>? tempOpenFile}); MapEntry<String, String>? tempOpenFile,
String errorMessage});
} }
/// @nodoc /// @nodoc
@ -128,6 +136,7 @@ class __$$Unp4kcStateImplCopyWithImpl<$Res>
Object? curPath = null, Object? curPath = null,
Object? endMessage = freezed, Object? endMessage = freezed,
Object? tempOpenFile = freezed, Object? tempOpenFile = freezed,
Object? errorMessage = null,
}) { }) {
return _then(_$Unp4kcStateImpl( return _then(_$Unp4kcStateImpl(
startUp: null == startUp startUp: null == startUp
@ -154,6 +163,10 @@ class __$$Unp4kcStateImplCopyWithImpl<$Res>
? _value.tempOpenFile ? _value.tempOpenFile
: tempOpenFile // ignore: cast_nullable_to_non_nullable : tempOpenFile // ignore: cast_nullable_to_non_nullable
as MapEntry<String, String>?, as MapEntry<String, String>?,
errorMessage: null == errorMessage
? _value.errorMessage
: errorMessage // ignore: cast_nullable_to_non_nullable
as String,
)); ));
} }
} }
@ -167,7 +180,8 @@ class _$Unp4kcStateImpl with DiagnosticableTreeMixin implements _Unp4kcState {
this.fs, this.fs,
required this.curPath, required this.curPath,
this.endMessage, this.endMessage,
this.tempOpenFile}) this.tempOpenFile,
this.errorMessage = ""})
: _files = files; : _files = files;
@override @override
@ -190,10 +204,13 @@ class _$Unp4kcStateImpl with DiagnosticableTreeMixin implements _Unp4kcState {
final String? endMessage; final String? endMessage;
@override @override
final MapEntry<String, String>? tempOpenFile; final MapEntry<String, String>? tempOpenFile;
@override
@JsonKey()
final String errorMessage;
@override @override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
return 'Unp4kcState(startUp: $startUp, files: $files, fs: $fs, curPath: $curPath, endMessage: $endMessage, tempOpenFile: $tempOpenFile)'; return 'Unp4kcState(startUp: $startUp, files: $files, fs: $fs, curPath: $curPath, endMessage: $endMessage, tempOpenFile: $tempOpenFile, errorMessage: $errorMessage)';
} }
@override @override
@ -206,7 +223,8 @@ class _$Unp4kcStateImpl with DiagnosticableTreeMixin implements _Unp4kcState {
..add(DiagnosticsProperty('fs', fs)) ..add(DiagnosticsProperty('fs', fs))
..add(DiagnosticsProperty('curPath', curPath)) ..add(DiagnosticsProperty('curPath', curPath))
..add(DiagnosticsProperty('endMessage', endMessage)) ..add(DiagnosticsProperty('endMessage', endMessage))
..add(DiagnosticsProperty('tempOpenFile', tempOpenFile)); ..add(DiagnosticsProperty('tempOpenFile', tempOpenFile))
..add(DiagnosticsProperty('errorMessage', errorMessage));
} }
@override @override
@ -221,7 +239,9 @@ class _$Unp4kcStateImpl with DiagnosticableTreeMixin implements _Unp4kcState {
(identical(other.endMessage, endMessage) || (identical(other.endMessage, endMessage) ||
other.endMessage == endMessage) && other.endMessage == endMessage) &&
(identical(other.tempOpenFile, tempOpenFile) || (identical(other.tempOpenFile, tempOpenFile) ||
other.tempOpenFile == tempOpenFile)); other.tempOpenFile == tempOpenFile) &&
(identical(other.errorMessage, errorMessage) ||
other.errorMessage == errorMessage));
} }
@override @override
@ -232,7 +252,8 @@ class _$Unp4kcStateImpl with DiagnosticableTreeMixin implements _Unp4kcState {
fs, fs,
curPath, curPath,
endMessage, endMessage,
tempOpenFile); tempOpenFile,
errorMessage);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@ -248,7 +269,8 @@ abstract class _Unp4kcState implements Unp4kcState {
final MemoryFileSystem? fs, final MemoryFileSystem? fs,
required final String curPath, required final String curPath,
final String? endMessage, final String? endMessage,
final MapEntry<String, String>? tempOpenFile}) = _$Unp4kcStateImpl; final MapEntry<String, String>? tempOpenFile,
final String errorMessage}) = _$Unp4kcStateImpl;
@override @override
bool get startUp; bool get startUp;
@ -263,6 +285,8 @@ abstract class _Unp4kcState implements Unp4kcState {
@override @override
MapEntry<String, String>? get tempOpenFile; MapEntry<String, String>? get tempOpenFile;
@override @override
String get errorMessage;
@override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$Unp4kcStateImplCopyWith<_$Unp4kcStateImpl> get copyWith => _$$Unp4kcStateImplCopyWith<_$Unp4kcStateImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;

View File

@ -6,7 +6,7 @@ part of 'unp4kc.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$unp4kCModelHash() => r'be71e2f9c2060df5ed8f1b64cce993058320bac4'; String _$unp4kCModelHash() => r'24f5043f687a5f652a0741b8e6f4a3855fca0101';
/// See also [Unp4kCModel]. /// See also [Unp4kCModel].
@ProviderFor(Unp4kCModel) @ProviderFor(Unp4kCModel)

View File

@ -7,7 +7,7 @@ part of 'advanced_localization_ui_model.dart';
// ************************************************************************** // **************************************************************************
String _$advancedLocalizationUIModelHash() => String _$advancedLocalizationUIModelHash() =>
r'acf91fc467108c3669d8ddd6fed3c24434be4ae8'; r'9fbbeca3af90f992717710633bcf2cd0e1cb06eb';
/// See also [AdvancedLocalizationUIModel]. /// See also [AdvancedLocalizationUIModel].
@ProviderFor(AdvancedLocalizationUIModel) @ProviderFor(AdvancedLocalizationUIModel)

View File

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

View File

@ -6,6 +6,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:re_editor/re_editor.dart'; import 'package:re_editor/re_editor.dart';
import 'package:starcitizen_doctor/common/helper/system_helper.dart'; import 'package:starcitizen_doctor/common/helper/system_helper.dart';
import 'package:starcitizen_doctor/data/app_unp4k_p4k_item_data.dart';
import 'package:starcitizen_doctor/provider/unp4kc.dart'; import 'package:starcitizen_doctor/provider/unp4kc.dart';
import 'package:starcitizen_doctor/widgets/widgets.dart'; import 'package:starcitizen_doctor/widgets/widgets.dart';
import 'package:super_sliver_list/super_sliver_list.dart'; import 'package:super_sliver_list/super_sliver_list.dart';
@ -22,232 +23,236 @@ class UnP4kcUI extends HookConsumerWidget {
return makeDefaultPage(context, return makeDefaultPage(context,
title: S.current.tools_unp4k_title(model.getGamePath()), title: S.current.tools_unp4k_title(model.getGamePath()),
useBodyContainer: false, useBodyContainer: false,
content: state.files == null content: makeBody(context, state, model, files, paths));
? Column( }
crossAxisAlignment: CrossAxisAlignment.start,
children: [ Widget makeBody(BuildContext context, Unp4kcState state, Unp4kCModel model,
Expanded(child: makeLoading(context)), List<AppUnp4kP4kItemData>? files, List<String> paths) {
if (state.endMessage != null) if (state.errorMessage.isNotEmpty) {
Padding( return Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(24),
child: Text( child: Center(
"${state.endMessage}", child: Text(state.errorMessage),
style: const TextStyle(fontSize: 12), ),
), );
), }
], return state.files == null
) ? Column(
: Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
Expanded(child: makeLoading(context)),
if (state.endMessage != null)
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"${state.endMessage}",
style: const TextStyle(fontSize: 12),
),
),
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: FluentTheme.of(context).cardColor.withOpacity(.06)),
height: 36,
padding: const EdgeInsets.only(left: 12, right: 12),
child: SuperListView.builder(
itemCount: paths.length - 1,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
var path = paths[index];
if (path.isEmpty) {
path = "\\";
}
final fullPath =
"${paths.sublist(0, index + 1).join("\\")}\\";
return Row(
children: [
IconButton(
icon: Text(path),
onPressed: () {
model.changeDir(fullPath, fullPath: true);
},
),
const Icon(
FluentIcons.chevron_right,
size: 12,
),
],
);
},
),
),
Expanded(
child: Row(
children: [ children: [
Container( Container(
width: MediaQuery.of(context).size.width * .3,
decoration: BoxDecoration( decoration: BoxDecoration(
color: color: FluentTheme.of(context).cardColor.withOpacity(.01),
FluentTheme.of(context).cardColor.withOpacity(.06)),
height: 36,
padding: const EdgeInsets.only(left: 12, right: 12),
child: SuperListView.builder(
itemCount: paths.length - 1,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
var path = paths[index];
if (path.isEmpty) {
path = "\\";
}
final fullPath =
"${paths.sublist(0, index + 1).join("\\")}\\";
return Row(
children: [
IconButton(
icon: Text(path),
onPressed: () {
model.changeDir(fullPath, fullPath: true);
},
),
const Icon(
FluentIcons.chevron_right,
size: 12,
),
],
);
},
), ),
), child: SuperListView.builder(
Expanded( padding: const EdgeInsets.only(
child: Row( top: 6, bottom: 6, left: 3, right: 12),
children: [ itemBuilder: (BuildContext context, int index) {
Container( final item = files![index];
width: MediaQuery.of(context).size.width * .3, final fileName =
decoration: BoxDecoration( item.name?.replaceAll(state.curPath.trim(), "") ??
color: FluentTheme.of(context)
.cardColor
.withOpacity(.01),
),
child: SuperListView.builder(
padding: const EdgeInsets.only(
top: 6, bottom: 6, left: 3, right: 12),
itemBuilder: (BuildContext context, int index) {
final item = files![index];
final fileName = item.name
?.replaceAll(state.curPath.trim(), "") ??
"?"; "?";
return Container( return Container(
margin: const EdgeInsets.only(top: 4, bottom: 4), margin: const EdgeInsets.only(top: 4, bottom: 4),
decoration: BoxDecoration( decoration: BoxDecoration(
color: FluentTheme.of(context) color: FluentTheme.of(context)
.cardColor .cardColor
.withOpacity(.05), .withOpacity(.05),
), ),
child: IconButton( child: IconButton(
onPressed: () { onPressed: () {
if (item.isDirectory ?? false) { if (item.isDirectory ?? false) {
model.changeDir(fileName); model.changeDir(fileName);
} else { } else {
model.openFile(item.name ?? ""); model.openFile(item.name ?? "");
} }
}, },
icon: Padding( icon: Padding(
padding: padding: const EdgeInsets.only(left: 4, right: 4),
const EdgeInsets.only(left: 4, right: 4), child: Row(
child: Row( children: [
children: [ if (item.isDirectory ?? false)
if (item.isDirectory ?? false) const Icon(
const Icon( FluentIcons.folder_fill,
FluentIcons.folder_fill, color: Color.fromRGBO(255, 224, 138, 1),
color: )
Color.fromRGBO(255, 224, 138, 1), else if (fileName.endsWith(".xml"))
) const Icon(
else if (fileName.endsWith(".xml")) FluentIcons.file_code,
const Icon( )
FluentIcons.file_code, else
) const Icon(
else FluentIcons.open_file,
const Icon( ),
FluentIcons.open_file, const SizedBox(width: 12),
), Expanded(
const SizedBox(width: 12), child: Column(
Expanded( crossAxisAlignment:
child: Column( CrossAxisAlignment.start,
crossAxisAlignment: children: [
CrossAxisAlignment.start, Row(
children: [ children: [
Row( Expanded(
children: [ child: Text(
Expanded( fileName,
child: Text( style: const TextStyle(
fileName, fontSize: 13),
style: const TextStyle( textAlign: TextAlign.start,
fontSize: 13),
textAlign: TextAlign.start,
),
),
],
),
if (!(item.isDirectory ??
true)) ...[
const SizedBox(height: 1),
Row(
children: [
Text(
FileSize.getSize(item.size),
style: TextStyle(
fontSize: 10,
color: Colors.white
.withOpacity(.6)),
),
const SizedBox(width: 12),
Text(
"${item.dateTime}",
style: TextStyle(
fontSize: 10,
color: Colors.white
.withOpacity(.6)),
),
],
), ),
], ),
], ],
), ),
), if (!(item.isDirectory ?? true)) ...[
const SizedBox(width: 3), const SizedBox(height: 1),
Icon( Row(
FluentIcons.chevron_right, children: [
size: 14, Text(
color: Colors.white.withOpacity(.6), FileSize.getSize(item.size),
) style: TextStyle(
], fontSize: 10,
), color: Colors.white
), .withOpacity(.6)),
),
);
},
itemCount: files?.length ?? 0,
),
),
Expanded(
child: Container(
child: state.tempOpenFile == null
? Center(
child:
Text(S.current.tools_unp4k_view_file),
)
: state.tempOpenFile?.key == "loading"
? makeLoading(context)
: Padding(
padding: const EdgeInsets.all(12),
child: Column(
children: [
if (state.tempOpenFile?.key == "text")
Expanded(
child: _TextTempWidget(
state.tempOpenFile?.value ??
""))
else
Expanded(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(S.current
.tools_unp4k_msg_unknown_file_type(
state.tempOpenFile
?.value ??
"")),
const SizedBox(height: 32),
FilledButton(
child: Padding(
padding:
const EdgeInsets
.all(4),
child: Text(S.current
.action_open_folder),
),
onPressed: () {
SystemHelper.openDir(
state.tempOpenFile
?.value ??
"");
})
],
), ),
), const SizedBox(width: 12),
) Text(
"${item.dateTime}",
style: TextStyle(
fontSize: 10,
color: Colors.white
.withOpacity(.6)),
),
],
),
],
], ],
), ),
), ),
)) const SizedBox(width: 3),
], Icon(
)), FluentIcons.chevron_right,
if (state.endMessage != null) size: 14,
Padding( color: Colors.white.withOpacity(.6),
padding: const EdgeInsets.all(8.0), )
child: Text( ],
"${state.endMessage}", ),
style: const TextStyle(fontSize: 12), ),
), ),
);
},
itemCount: files?.length ?? 0,
), ),
),
Expanded(
child: Container(
child: state.tempOpenFile == null
? Center(
child: Text(S.current.tools_unp4k_view_file),
)
: state.tempOpenFile?.key == "loading"
? makeLoading(context)
: Padding(
padding: const EdgeInsets.all(12),
child: Column(
children: [
if (state.tempOpenFile?.key == "text")
Expanded(
child: _TextTempWidget(
state.tempOpenFile?.value ?? ""))
else
Expanded(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(S.current
.tools_unp4k_msg_unknown_file_type(
state.tempOpenFile
?.value ??
"")),
const SizedBox(height: 32),
FilledButton(
child: Padding(
padding:
const EdgeInsets.all(4),
child: Text(S.current
.action_open_folder),
),
onPressed: () {
SystemHelper.openDir(state
.tempOpenFile
?.value ??
"");
})
],
),
),
)
],
),
),
))
], ],
)); )),
if (state.endMessage != null)
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"${state.endMessage}",
style: const TextStyle(fontSize: 12),
),
),
],
);
} }
} }