file rename (#9089)

Signed-off-by: 21pages <sunboeasy@gmail.com>
This commit is contained in:
21pages
2024-08-16 12:55:58 +08:00
committed by GitHub
parent 579e0fac36
commit ed18e3c786
59 changed files with 507 additions and 50 deletions

View File

@@ -33,6 +33,8 @@ class CmFileModel {
_onFileRemove(evt['remove']);
} else if (evt['create_dir'] != null) {
_onDirCreate(evt['create_dir']);
} else if (evt['rename'] != null) {
_onRename(evt['rename']);
}
}
@@ -59,8 +61,6 @@ class CmFileModel {
_dealOneJob(dynamic l, bool calcSpeed) {
final data = TransferJobSerdeData.fromJson(l);
Client? client =
gFFI.serverModel.clients.firstWhereOrNull((e) => e.id == data.connId);
var jobTable = _jobTables[data.connId];
if (jobTable == null) {
debugPrint("jobTable should not be null");
@@ -70,12 +70,7 @@ class CmFileModel {
if (job == null) {
job = CmFileLog();
jobTable.add(job);
final currentSelectedTab =
gFFI.serverModel.tabController.state.value.selectedTabInfo;
if (!(gFFI.chatModel.isShowCMSidePage &&
currentSelectedTab.key == data.connId.toString())) {
client?.unreadChatMessageCount.value += 1;
}
_addUnread(data.connId);
}
job.id = data.id;
job.action =
@@ -167,8 +162,6 @@ class CmFileModel {
try {
dynamic d = jsonDecode(log);
FileActionLog data = FileActionLog.fromJson(d);
Client? client =
gFFI.serverModel.clients.firstWhereOrNull((e) => e.id == data.connId);
var jobTable = _jobTables[data.connId];
if (jobTable == null) {
debugPrint("jobTable should not be null");
@@ -179,17 +172,45 @@ class CmFileModel {
..fileName = data.path
..action = CmFileAction.createDir
..state = JobState.done);
final currentSelectedTab =
gFFI.serverModel.tabController.state.value.selectedTabInfo;
if (!(gFFI.chatModel.isShowCMSidePage &&
currentSelectedTab.key == data.connId.toString())) {
client?.unreadChatMessageCount.value += 1;
}
_addUnread(data.connId);
jobTable.refresh();
} catch (e) {
debugPrint('$e');
}
}
_onRename(dynamic log) {
try {
dynamic d = jsonDecode(log);
FileRenamenLog data = FileRenamenLog.fromJson(d);
var jobTable = _jobTables[data.connId];
if (jobTable == null) {
debugPrint("jobTable should not be null");
return;
}
final fileName = '${data.path} -> ${data.newName}';
jobTable.add(CmFileLog()
..id = 0
..fileName = fileName
..action = CmFileAction.rename
..state = JobState.done);
_addUnread(data.connId);
jobTable.refresh();
} catch (e) {
debugPrint('$e');
}
}
_addUnread(int connId) {
Client? client =
gFFI.serverModel.clients.firstWhereOrNull((e) => e.id == connId);
final currentSelectedTab =
gFFI.serverModel.tabController.state.value.selectedTabInfo;
if (!(gFFI.chatModel.isShowCMSidePage &&
currentSelectedTab.key == connId.toString())) {
client?.unreadChatMessageCount.value += 1;
}
}
}
enum CmFileAction {
@@ -198,6 +219,7 @@ enum CmFileAction {
localToRemote,
remove,
createDir,
rename,
}
class CmFileLog {
@@ -285,3 +307,22 @@ class FileActionLog {
dir: d['dir'] ?? false,
);
}
class FileRenamenLog {
int connId = 0;
String path = '';
String newName = '';
FileRenamenLog({
required this.connId,
required this.path,
required this.newName,
});
FileRenamenLog.fromJson(dynamic d)
: this(
connId: d['connId'] ?? 0,
path: d['path'] ?? '',
newName: d['newName'] ?? '',
);
}

View File

@@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/common/widgets/dialog.dart';
import 'package:flutter_hbb/utils/event_loop.dart';
import 'package:get/get.dart';
import 'package:path/path.dart' as path;
@@ -642,6 +643,77 @@ class FileController {
path: path,
isRemote: !isLocal);
}
Future<void> renameAction(Entry item, bool isLocal) async {
final textEditingController = TextEditingController(text: item.name);
String? errorText;
dialogManager?.show((setState, close, context) {
textEditingController.addListener(() {
if (errorText != null) {
setState(() {
errorText = null;
});
}
});
submit() async {
final newName = textEditingController.text;
if (newName.isEmpty || newName == item.name) {
close();
return;
}
if (directory.value.entries.any((e) => e.name == newName)) {
setState(() {
errorText = translate("Already exists");
});
return;
}
if (!PathUtil.validName(newName, options.value.isWindows)) {
setState(() {
if (item.isDirectory) {
errorText = translate("Invalid folder name");
} else {
errorText = translate("Invalid file name");
}
});
return;
}
await bind.sessionRenameFile(
sessionId: sessionId,
actId: JobController.jobID.next(),
path: item.path,
newName: newName,
isRemote: !isLocal);
close();
}
return CustomAlertDialog(
content: Column(
children: [
DialogTextField(
title: '${translate('Rename')} ${item.name}',
controller: textEditingController,
errorText: errorText,
),
],
),
actions: [
dialogButton(
"Cancel",
icon: Icon(Icons.close_rounded),
onPressed: close,
isOutline: true,
),
dialogButton(
"OK",
icon: Icon(Icons.done_rounded),
onPressed: submit,
),
],
onSubmit: submit,
onCancel: close,
);
});
}
}
class JobController {
@@ -1083,6 +1155,13 @@ class PathUtil {
final pathUtil = isWindows ? windowsContext : posixContext;
return pathUtil.dirname(path);
}
static bool validName(String name, bool isWindows) {
final unixFileNamePattern = RegExp(r'^[^/\0]+$');
final windowsFileNamePattern = RegExp(r'^[^<>:"/\\|?*]+$');
final reg = isWindows ? windowsFileNamePattern : unixFileNamePattern;
return reg.hasMatch(name);
}
}
class DirectoryOptions {