mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-02-06 15:10:20 +00:00
feat: update cache clear ui
This commit is contained in:
196
lib/ui/tools/dialogs/shader_cache_clean_dialog.dart
Normal file
196
lib/ui/tools/dialogs/shader_cache_clean_dialog.dart
Normal file
@@ -0,0 +1,196 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:starcitizen_doctor/generated/l10n.dart';
|
||||
|
||||
/// 着色器缓存清理对话框
|
||||
class ShaderCacheCleanDialog extends StatefulWidget {
|
||||
final Future<void> Function(String mode) onClean;
|
||||
|
||||
const ShaderCacheCleanDialog({super.key, required this.onClean});
|
||||
|
||||
@override
|
||||
State<ShaderCacheCleanDialog> createState() => _ShaderCacheCleanDialogState();
|
||||
}
|
||||
|
||||
class _ShaderCacheCleanDialogState extends State<ShaderCacheCleanDialog> {
|
||||
bool _isCleaning = false;
|
||||
String? _selectedMode;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ContentDialog(
|
||||
title: Row(
|
||||
children: [
|
||||
const Icon(FontAwesomeIcons.shapes, size: 20),
|
||||
const SizedBox(width: 12),
|
||||
Text(S.current.tools_shader_clean_dialog_title),
|
||||
],
|
||||
),
|
||||
constraints: const BoxConstraints(maxWidth: 500),
|
||||
content: _isCleaning
|
||||
? SizedBox(
|
||||
height: 120,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const ProgressRing(),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.current.tools_action_info_cleaning),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
// 保留最新模式
|
||||
_CleanModeOption(
|
||||
icon: FluentIcons.save,
|
||||
title: S.current.tools_shader_clean_keep_latest,
|
||||
description: S.current.tools_shader_clean_keep_latest_desc,
|
||||
isSelected: _selectedMode == "keep_latest",
|
||||
isRecommended: true,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_selectedMode = "keep_latest";
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// 全部清理模式
|
||||
_CleanModeOption(
|
||||
icon: FluentIcons.delete,
|
||||
title: S.current.tools_shader_clean_all,
|
||||
description: S.current.tools_shader_clean_all_desc,
|
||||
isSelected: _selectedMode == "clean_all",
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_selectedMode = "clean_all";
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
if (!_isCleaning) ...[
|
||||
Button(onPressed: () => Navigator.of(context).pop(), child: Text(S.current.app_common_tip_cancel)),
|
||||
FilledButton(
|
||||
onPressed: _selectedMode == null
|
||||
? null
|
||||
: () async {
|
||||
setState(() {
|
||||
_isCleaning = true;
|
||||
});
|
||||
try {
|
||||
await widget.onClean(_selectedMode!);
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isCleaning = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||
child: Text(S.current.tools_action_start_cleaning),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 清理模式选项组件
|
||||
class _CleanModeOption extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String title;
|
||||
final String description;
|
||||
final bool isSelected;
|
||||
final bool isRecommended;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _CleanModeOption({
|
||||
required this.icon,
|
||||
required this.title,
|
||||
required this.description,
|
||||
required this.isSelected,
|
||||
this.isRecommended = false,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? FluentTheme.of(context).accentColor.withValues(alpha: .15)
|
||||
: FluentTheme.of(context).cardColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: isSelected ? FluentTheme.of(context).accentColor : Colors.transparent, width: 2),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
size: 20,
|
||||
color: isSelected ? FluentTheme.of(context).accentColor : Colors.white.withValues(alpha: .7),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: isSelected ? FluentTheme.of(context).accentColor : Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isRecommended)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF4CAF50),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
S.current.app_common_recommended,
|
||||
style: const TextStyle(fontSize: 11, color: Colors.white, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
description,
|
||||
style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: .6), height: 1.4),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import 'package:xml/xml.dart';
|
||||
|
||||
import 'dialogs/hosts_booster_dialog_ui.dart';
|
||||
import 'dialogs/rsi_launcher_enhance_dialog_ui.dart';
|
||||
import 'dialogs/shader_cache_clean_dialog.dart';
|
||||
import 'yearly_report_ui/yearly_report_ui.dart';
|
||||
|
||||
part 'tools_ui_model.g.dart';
|
||||
@@ -627,62 +628,28 @@ class ToolsUIModel extends _$ToolsUIModel {
|
||||
// 全部清理模式:
|
||||
// 前两个:仅保留 GraphicsSettings
|
||||
// 其他:仅保留 GraphicsSettings
|
||||
await _cleanShaderCacheDirectory(scDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _cleanShaderCache(BuildContext context) async {
|
||||
// 显示对话框让用户选择清理模式
|
||||
final result = await showDialog<String>(
|
||||
await showDialog<String>(
|
||||
context: context,
|
||||
builder: (dialogContext) => ContentDialog(
|
||||
constraints: BoxConstraints(maxWidth: 380),
|
||||
title: Text(S.current.tools_shader_clean_dialog_title),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(S.current.tools_shader_clean_keep_latest),
|
||||
),
|
||||
onPressed: () => Navigator.pop(dialogContext, "keep_latest"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: Button(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(S.current.tools_shader_clean_all),
|
||||
),
|
||||
onPressed: () => Navigator.pop(dialogContext, "clean_all"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [Button(child: Text(S.current.app_common_tip_cancel), onPressed: () => Navigator.pop(dialogContext))],
|
||||
builder: (dialogContext) => ShaderCacheCleanDialog(
|
||||
onClean: (mode) async {
|
||||
state = state.copyWith(working: true);
|
||||
if (mode == "keep_latest") {
|
||||
await cleanShaderCacheKeepLatest();
|
||||
} else {
|
||||
await cleanShaderCache();
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
loadToolsCard(context, skipPathScan: true);
|
||||
state = state.copyWith(working: false);
|
||||
Navigator.of(dialogContext).pop();
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
if (result == null || !context.mounted) return;
|
||||
|
||||
state = state.copyWith(working: true);
|
||||
|
||||
if (result == "keep_latest") {
|
||||
await cleanShaderCacheKeepLatest();
|
||||
} else {
|
||||
await cleanShaderCache();
|
||||
}
|
||||
|
||||
if (!context.mounted) return;
|
||||
loadToolsCard(context, skipPathScan: true);
|
||||
state = state.copyWith(working: false);
|
||||
}
|
||||
|
||||
/// 清理着色器缓存目录,保留 GraphicsSettings 文件夹
|
||||
|
||||
Reference in New Issue
Block a user