feat: use rename previews in batch tool

This commit is contained in:
ngfchl
2026-07-18 11:37:58 +08:00
parent e900354232
commit a0acd6060d
+33 -12
View File
@@ -6,6 +6,7 @@ import 'package:shadcn_ui/shadcn_ui.dart';
import '../core/storage/storage_manager.dart';
import '../models/cloud_file.dart';
import '../models/batch_rename.dart';
import '../models/media_library.dart';
import '../providers/auth_provider.dart';
import '../providers/file_provider.dart';
@@ -327,6 +328,15 @@ class _BatchRenameToolState extends ConsumerState<_BatchRenameTool> {
final _replace = TextEditingController();
bool _preserveExtension = true;
bool _running = false;
late List<BatchRenameRule> _rules;
@override
void initState() {
super.initState();
_rules = [
BatchRenameRule(id: 'replace', kind: BatchRenameRuleKind.replace),
];
}
@override
void dispose() {
@@ -336,13 +346,15 @@ class _BatchRenameToolState extends ConsumerState<_BatchRenameTool> {
}
String _newName(CloudFile file) {
final old = file.name;
if (!_preserveExtension || file.isDirectory) {
return old.replaceAll(_find.text, _replace.text);
}
final split = old.lastIndexOf('.');
if (split <= 0) return old.replaceAll(_find.text, _replace.text);
return '${old.substring(0, split).replaceAll(_find.text, _replace.text)}${old.substring(split)}';
final rule = _rules.first.copyWith(
pattern: _find.text,
replacement: _replace.text,
);
return buildRenamePreviews(
[file],
[rule],
preserveExtension: _preserveExtension,
).first.newName;
}
Future<void> _apply(List<CloudFile> files) async {
@@ -363,7 +375,10 @@ class _BatchRenameToolState extends ConsumerState<_BatchRenameTool> {
Widget build(BuildContext context) {
final cs = ShadTheme.of(context).colorScheme;
final files = ref.watch(fileProvider).files;
final changed = files.where((file) => _newName(file) != file.name).toList();
final previews = buildRenamePreviews(files, [
_rules.first.copyWith(pattern: _find.text, replacement: _replace.text),
], preserveExtension: _preserveExtension);
final changed = previews.where((item) => item.applicable).toList();
return Padding(
padding: const EdgeInsets.all(18),
child: Column(
@@ -399,7 +414,10 @@ class _BatchRenameToolState extends ConsumerState<_BatchRenameTool> {
),
const SizedBox(width: 12),
ShadButton(
onPressed: _running ? null : () => _apply(files),
onPressed: _running
? null
: () =>
_apply(changed.map((item) => item.file).toList()),
child: Text(_running ? '正在应用' : '应用 ${changed.length}'),
),
],
@@ -420,7 +438,8 @@ class _BatchRenameToolState extends ConsumerState<_BatchRenameTool> {
Divider(height: 1, color: cs.border),
itemBuilder: (context, index) {
final file = files[index];
final next = _newName(file);
final preview = previews[index];
final next = preview.newName;
return ListTile(
dense: true,
leading: Icon(
@@ -431,9 +450,11 @@ class _BatchRenameToolState extends ConsumerState<_BatchRenameTool> {
),
title: Text(file.name),
subtitle: Text(
next,
preview.error ?? next,
style: TextStyle(
color: next == file.name
color: preview.error != null
? cs.destructive
: next == file.name
? cs.mutedForeground
: cs.primary,
),