Merge pull request #876 from Kingtous/flutter_desktop
add: file transfer dual logic with bridge
This commit is contained in:
commit
1fc8957c1c
@ -11,7 +11,6 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
|
|
||||||
import '../../common.dart';
|
import '../../common.dart';
|
||||||
import '../../mobile/widgets/dialog.dart';
|
|
||||||
import '../../models/model.dart';
|
import '../../models/model.dart';
|
||||||
|
|
||||||
class FileManagerPage extends StatefulWidget {
|
class FileManagerPage extends StatefulWidget {
|
||||||
@ -25,7 +24,8 @@ class FileManagerPage extends StatefulWidget {
|
|||||||
class _FileManagerPageState extends State<FileManagerPage>
|
class _FileManagerPageState extends State<FileManagerPage>
|
||||||
with AutomaticKeepAliveClientMixin {
|
with AutomaticKeepAliveClientMixin {
|
||||||
final _selectedItems = SelectedItems();
|
final _selectedItems = SelectedItems();
|
||||||
final _breadCrumbScroller = ScrollController();
|
final _breadCrumbLocalScroller = ScrollController();
|
||||||
|
final _breadCrumbRemoteScroller = ScrollController();
|
||||||
|
|
||||||
/// FFI with name file_transfer_id
|
/// FFI with name file_transfer_id
|
||||||
FFI get _ffi => ffi('ft_${widget.id}');
|
FFI get _ffi => ffi('ft_${widget.id}');
|
||||||
@ -66,135 +66,11 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
if (model.selectMode) {
|
if (model.selectMode) {
|
||||||
model.toggleSelectMode();
|
model.toggleSelectMode();
|
||||||
} else {
|
|
||||||
goBack();
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: MyTheme.grayBg,
|
backgroundColor: MyTheme.grayBg,
|
||||||
appBar: AppBar(
|
|
||||||
leading: Row(children: [
|
|
||||||
IconButton(icon: Icon(Icons.close), onPressed: clientClose),
|
|
||||||
]),
|
|
||||||
centerTitle: true,
|
|
||||||
// title: ToggleSwitch(
|
|
||||||
// initialLabelIndex: model.isLocal ? 0 : 1,
|
|
||||||
// activeBgColor: [MyTheme.idColor],
|
|
||||||
// inactiveBgColor: MyTheme.grayBg,
|
|
||||||
// inactiveFgColor: Colors.black54,
|
|
||||||
// totalSwitches: 2,
|
|
||||||
// minWidth: 100,
|
|
||||||
// fontSize: 15,
|
|
||||||
// iconSize: 18,
|
|
||||||
// labels: [translate("Local"), translate("Remote")],
|
|
||||||
// icons: [Icons.phone_android_sharp, Icons.screen_share],
|
|
||||||
// onToggle: (index) {
|
|
||||||
// final current = model.isLocal ? 0 : 1;
|
|
||||||
// if (index != current) {
|
|
||||||
// model.togglePage();
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
actions: [
|
|
||||||
PopupMenuButton<String>(
|
|
||||||
icon: Icon(Icons.more_vert),
|
|
||||||
itemBuilder: (context) {
|
|
||||||
return [
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.refresh, color: Colors.black),
|
|
||||||
SizedBox(width: 5),
|
|
||||||
Text(translate("Refresh File"))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
value: "refresh",
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.check, color: Colors.black),
|
|
||||||
SizedBox(width: 5),
|
|
||||||
Text(translate("Multi Select"))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
value: "select",
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.folder_outlined,
|
|
||||||
color: Colors.black),
|
|
||||||
SizedBox(width: 5),
|
|
||||||
Text(translate("Create Folder"))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
value: "folder",
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
model.currentShowHidden
|
|
||||||
? Icons.check_box_outlined
|
|
||||||
: Icons.check_box_outline_blank,
|
|
||||||
color: Colors.black),
|
|
||||||
SizedBox(width: 5),
|
|
||||||
Text(translate("Show Hidden Files"))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
value: "hidden",
|
|
||||||
)
|
|
||||||
];
|
|
||||||
},
|
|
||||||
onSelected: (v) {
|
|
||||||
if (v == "refresh") {
|
|
||||||
model.refresh();
|
|
||||||
} else if (v == "select") {
|
|
||||||
_selectedItems.clear();
|
|
||||||
model.toggleSelectMode();
|
|
||||||
} else if (v == "folder") {
|
|
||||||
final name = TextEditingController();
|
|
||||||
DialogManager.show((setState, close) =>
|
|
||||||
CustomAlertDialog(
|
|
||||||
title: Text(translate("Create Folder")),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
TextFormField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: translate(
|
|
||||||
"Please enter the folder name"),
|
|
||||||
),
|
|
||||||
controller: name,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
style: flatButtonStyle,
|
|
||||||
onPressed: () => close(false),
|
|
||||||
child: Text(translate("Cancel"))),
|
|
||||||
ElevatedButton(
|
|
||||||
style: flatButtonStyle,
|
|
||||||
onPressed: () {
|
|
||||||
if (name.value.text.isNotEmpty) {
|
|
||||||
model.createDir(PathUtil.join(
|
|
||||||
model.currentDir.path,
|
|
||||||
name.value.text,
|
|
||||||
model.currentIsWindows));
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Text(translate("OK")))
|
|
||||||
]));
|
|
||||||
} else if (v == "hidden") {
|
|
||||||
model.toggleShowHidden();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: Row(
|
body: Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(flex: 1, child: body(isLocal: true)),
|
Flexible(flex: 1, child: body(isLocal: true)),
|
||||||
@ -213,11 +89,110 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
return !_selectedItems.isOtherPage(model.isLocal);
|
return !_selectedItems.isOtherPage(model.isLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget menu({bool isLocal = false}) {
|
||||||
|
return PopupMenuButton<String>(
|
||||||
|
icon: Icon(Icons.more_vert),
|
||||||
|
itemBuilder: (context) {
|
||||||
|
return [
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.refresh, color: Colors.black),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
Text(translate("Refresh File"))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
value: "refresh",
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.check, color: Colors.black),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
Text(translate("Multi Select"))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
value: "select",
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.folder_outlined,
|
||||||
|
color: Colors.black),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
Text(translate("Create Folder"))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
value: "folder",
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
model.currentShowHidden
|
||||||
|
? Icons.check_box_outlined
|
||||||
|
: Icons.check_box_outline_blank,
|
||||||
|
color: Colors.black),
|
||||||
|
SizedBox(width: 5),
|
||||||
|
Text(translate("Show Hidden Files"))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
value: "hidden",
|
||||||
|
)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
onSelected: (v) {
|
||||||
|
if (v == "refresh") {
|
||||||
|
model.refresh();
|
||||||
|
} else if (v == "select") {
|
||||||
|
_selectedItems.clear();
|
||||||
|
model.toggleSelectMode();
|
||||||
|
} else if (v == "folder") {
|
||||||
|
final name = TextEditingController();
|
||||||
|
DialogManager.show((setState, close) =>
|
||||||
|
CustomAlertDialog(
|
||||||
|
title: Text(translate("Create Folder")),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: translate(
|
||||||
|
"Please enter the folder name"),
|
||||||
|
),
|
||||||
|
controller: name,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
style: flatButtonStyle,
|
||||||
|
onPressed: () => close(false),
|
||||||
|
child: Text(translate("Cancel"))),
|
||||||
|
ElevatedButton(
|
||||||
|
style: flatButtonStyle,
|
||||||
|
onPressed: () {
|
||||||
|
if (name.value.text.isNotEmpty) {
|
||||||
|
model.createDir(PathUtil.join(
|
||||||
|
model.currentDir.path,
|
||||||
|
name.value.text,
|
||||||
|
model.currentIsWindows));
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(translate("OK")))
|
||||||
|
]));
|
||||||
|
} else if (v == "hidden") {
|
||||||
|
model.toggleShowHidden(local: isLocal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Widget body({bool isLocal = false}) {
|
Widget body({bool isLocal = false}) {
|
||||||
final fd = isLocal ? model.currentLocalDir : model.currentRemoteDir;
|
final fd = isLocal ? model.currentLocalDir : model.currentRemoteDir;
|
||||||
final entries = fd.entries;
|
final entries = fd.entries;
|
||||||
return Column(children: [
|
return Column(children: [
|
||||||
headTools(),
|
headTools(isLocal),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: entries.length + 1,
|
itemCount: entries.length + 1,
|
||||||
@ -301,8 +276,8 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (entries[index].isDirectory) {
|
if (entries[index].isDirectory) {
|
||||||
model.openDirectory(entries[index].path);
|
model.openDirectory(entries[index].path, isLocal: isLocal);
|
||||||
breadCrumbScrollToEnd();
|
breadCrumbScrollToEnd(isLocal);
|
||||||
} else {
|
} else {
|
||||||
// Perform file-related tasks.
|
// Perform file-related tasks.
|
||||||
}
|
}
|
||||||
@ -322,20 +297,21 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
goBack() {
|
goBack({bool? isLocal}) {
|
||||||
model.goToParentDirectory();
|
model.goToParentDirectory(isLocal: isLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
breadCrumbScrollToEnd() {
|
breadCrumbScrollToEnd(bool isLocal) {
|
||||||
|
final controller = isLocal ? _breadCrumbLocalScroller : _breadCrumbRemoteScroller;
|
||||||
Future.delayed(Duration(milliseconds: 200), () {
|
Future.delayed(Duration(milliseconds: 200), () {
|
||||||
_breadCrumbScroller.animateTo(
|
controller.animateTo(
|
||||||
_breadCrumbScroller.position.maxScrollExtent,
|
controller.position.maxScrollExtent,
|
||||||
duration: Duration(milliseconds: 200),
|
duration: Duration(milliseconds: 200),
|
||||||
curve: Curves.fastLinearToSlowEaseIn);
|
curve: Curves.fastLinearToSlowEaseIn);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget headTools() => Container(
|
Widget headTools(bool isLocal) => Container(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -353,16 +329,18 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
path = PathUtil.join(path, item, model.currentIsWindows);
|
path = PathUtil.join(path, item, model.currentIsWindows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model.openDirectory(path);
|
model.openDirectory(path, isLocal: isLocal);
|
||||||
}),
|
}, isLocal),
|
||||||
divider: Icon(Icons.chevron_right),
|
divider: Icon(Icons.chevron_right),
|
||||||
overflow: ScrollableOverflow(controller: _breadCrumbScroller),
|
overflow: ScrollableOverflow(controller: isLocal ? _breadCrumbLocalScroller : _breadCrumbRemoteScroller),
|
||||||
)),
|
)),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.arrow_upward),
|
icon: Icon(Icons.arrow_upward),
|
||||||
onPressed: goBack,
|
onPressed: () {
|
||||||
|
goBack(isLocal: isLocal);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
PopupMenuButton<SortBy>(
|
PopupMenuButton<SortBy>(
|
||||||
icon: Icon(Icons.sort),
|
icon: Icon(Icons.sort),
|
||||||
@ -375,7 +353,10 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
))
|
))
|
||||||
.toList();
|
.toList();
|
||||||
},
|
},
|
||||||
onSelected: model.changeSortStyle),
|
onSelected: (sort) {
|
||||||
|
model.changeSortStyle(sort, isLocal: isLocal);
|
||||||
|
}),
|
||||||
|
menu(isLocal: isLocal)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -486,8 +467,8 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<BreadCrumbItem> getPathBreadCrumbItems(
|
List<BreadCrumbItem> getPathBreadCrumbItems(
|
||||||
void Function() onHome, void Function(List<String>) onPressed) {
|
void Function() onHome, void Function(List<String>) onPressed, bool isLocal) {
|
||||||
final path = model.currentShortPath;
|
final path = model.shortPath(isLocal);
|
||||||
final list = PathUtil.split(path, model.currentIsWindows);
|
final list = PathUtil.split(path, model.currentIsWindows);
|
||||||
final breadCrumbList = [
|
final breadCrumbList = [
|
||||||
BreadCrumbItem(
|
BreadCrumbItem(
|
||||||
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_hbb/desktop/pages/file_manager_page.dart';
|
import 'package:flutter_hbb/desktop/pages/file_manager_page.dart';
|
||||||
import 'package:flutter_hbb/desktop/widgets/titlebar_widget.dart';
|
import 'package:flutter_hbb/desktop/widgets/titlebar_widget.dart';
|
||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
/// File Transfer for multi tabs
|
/// File Transfer for multi tabs
|
||||||
class FileManagerTabPage extends StatefulWidget {
|
class FileManagerTabPage extends StatefulWidget {
|
||||||
@ -21,7 +22,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
|
|||||||
// refactor List<int> when using multi-tab
|
// refactor List<int> when using multi-tab
|
||||||
// this singleton is only for test
|
// this singleton is only for test
|
||||||
List<String> connectionIds = List.empty(growable: true);
|
List<String> connectionIds = List.empty(growable: true);
|
||||||
var initialIndex = 0;
|
var initialIndex = 0.obs;
|
||||||
|
|
||||||
_FileManagerTabPageState(Map<String, dynamic> params) {
|
_FileManagerTabPageState(Map<String, dynamic> params) {
|
||||||
if (params['id'] != null) {
|
if (params['id'] != null) {
|
||||||
@ -37,21 +38,15 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
|
|||||||
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
|
"call ${call.method} with args ${call.arguments} from window ${fromWindowId}");
|
||||||
// for simplify, just replace connectionId
|
// for simplify, just replace connectionId
|
||||||
if (call.method == "new_file_transfer") {
|
if (call.method == "new_file_transfer") {
|
||||||
setState(() {
|
final args = jsonDecode(call.arguments);
|
||||||
final args = jsonDecode(call.arguments);
|
final id = args['id'];
|
||||||
final id = args['id'];
|
final indexOf = connectionIds.indexOf(id);
|
||||||
final indexOf = connectionIds.indexOf(id);
|
if (indexOf >= 0) {
|
||||||
if (indexOf >= 0) {
|
initialIndex.value = indexOf;
|
||||||
setState(() {
|
} else {
|
||||||
initialIndex = indexOf;
|
connectionIds.add(id);
|
||||||
});
|
initialIndex.value = connectionIds.length - 1;
|
||||||
} else {
|
}
|
||||||
connectionIds.add(id);
|
|
||||||
setState(() {
|
|
||||||
initialIndex = connectionIds.length - 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -59,51 +54,53 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: DefaultTabController(
|
body: Obx(
|
||||||
initialIndex: initialIndex,
|
()=> DefaultTabController(
|
||||||
length: connectionIds.length,
|
initialIndex: initialIndex.value,
|
||||||
animationDuration: Duration.zero,
|
length: connectionIds.length,
|
||||||
child: Column(
|
animationDuration: Duration.zero,
|
||||||
children: [
|
child: Column(
|
||||||
DesktopTitleBar(
|
children: [
|
||||||
child: TabBar(
|
DesktopTitleBar(
|
||||||
isScrollable: true,
|
child: TabBar(
|
||||||
labelColor: Colors.white,
|
isScrollable: true,
|
||||||
physics: NeverScrollableScrollPhysics(),
|
labelColor: Colors.white,
|
||||||
indicatorColor: Colors.white,
|
physics: NeverScrollableScrollPhysics(),
|
||||||
tabs: connectionIds
|
indicatorColor: Colors.white,
|
||||||
.map((e) => Tab(
|
tabs: connectionIds
|
||||||
child: Row(
|
.map((e) => Tab(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
Text(e),
|
children: [
|
||||||
SizedBox(
|
Text(e),
|
||||||
width: 4,
|
SizedBox(
|
||||||
),
|
width: 4,
|
||||||
InkWell(
|
),
|
||||||
onTap: () {
|
InkWell(
|
||||||
onRemoveId(e);
|
onTap: () {
|
||||||
},
|
onRemoveId(e);
|
||||||
child: Icon(
|
},
|
||||||
Icons.highlight_remove,
|
child: Icon(
|
||||||
size: 20,
|
Icons.highlight_remove,
|
||||||
))
|
size: 20,
|
||||||
],
|
))
|
||||||
),
|
],
|
||||||
))
|
),
|
||||||
.toList()),
|
))
|
||||||
),
|
.toList()),
|
||||||
Expanded(
|
),
|
||||||
child: TabBarView(
|
Expanded(
|
||||||
children: connectionIds
|
child: TabBarView(
|
||||||
.map((e) => Container(
|
children: connectionIds
|
||||||
child: FileManagerPage(
|
.map((e) => Container(
|
||||||
key: ValueKey(e),
|
child: FileManagerPage(
|
||||||
id: e))) //RemotePage(key: ValueKey(e), id: e))
|
key: ValueKey(e),
|
||||||
.toList()),
|
id: e))) //RemotePage(key: ValueKey(e), id: e))
|
||||||
)
|
.toList()),
|
||||||
],
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -114,9 +111,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage>
|
|||||||
if (indexOf == -1) {
|
if (indexOf == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setState(() {
|
connectionIds.removeAt(indexOf);
|
||||||
connectionIds.removeAt(indexOf);
|
initialIndex.value = max(0, initialIndex.value - 1);
|
||||||
initialIndex = max(0, initialIndex - 1);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,21 @@ class FileModel extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String shortPath(bool isLocal) {
|
||||||
|
final dir = isLocal ? currentLocalDir : currentRemoteDir;
|
||||||
|
if (dir.path.startsWith(currentHome)) {
|
||||||
|
var path = dir.path.replaceFirst(currentHome, "");
|
||||||
|
if (path.length == 0) return "";
|
||||||
|
if (path[0] == "/" || path[0] == "\\") {
|
||||||
|
// remove more '/' or '\'
|
||||||
|
path = path.replaceFirst(path[0], "");
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
} else {
|
||||||
|
return dir.path.replaceFirst(currentHome, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool get currentShowHidden =>
|
bool get currentShowHidden =>
|
||||||
_isLocal ? _localOption.showHidden : _remoteOption.showHidden;
|
_isLocal ? _localOption.showHidden : _remoteOption.showHidden;
|
||||||
|
|
||||||
@ -265,9 +280,9 @@ class FileModel extends ChangeNotifier {
|
|||||||
openDirectory(currentHome);
|
openDirectory(currentHome);
|
||||||
}
|
}
|
||||||
|
|
||||||
goToParentDirectory() {
|
goToParentDirectory({bool? isLocal}) {
|
||||||
final parent = PathUtil.dirname(currentDir.path, currentIsWindows);
|
final parent = PathUtil.dirname(currentDir.path, currentIsWindows);
|
||||||
openDirectory(parent);
|
openDirectory(parent, isLocal: isLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendFiles(SelectedItems items) {
|
sendFiles(SelectedItems items) {
|
||||||
@ -282,17 +297,10 @@ class FileModel extends ChangeNotifier {
|
|||||||
items.isLocal! ? _localOption.isWindows : _remoteOption.isWindows;
|
items.isLocal! ? _localOption.isWindows : _remoteOption.isWindows;
|
||||||
final showHidden =
|
final showHidden =
|
||||||
items.isLocal! ? _localOption.showHidden : _remoteOption.showHidden;
|
items.isLocal! ? _localOption.showHidden : _remoteOption.showHidden;
|
||||||
items.items.forEach((from) {
|
items.items.forEach((from) async {
|
||||||
_jobId++;
|
_jobId++;
|
||||||
final msg = {
|
await _ffi.target?.bind.sessionSendFiles(id: '${_ffi.target?.getId()}', actId: _jobId, path: from.path, to: PathUtil.join(toPath, from.name, isWindows)
|
||||||
"id": _jobId.toString(),
|
,fileNum: 0, includeHidden: showHidden, isRemote: !(items.isLocal!));
|
||||||
"path": from.path,
|
|
||||||
"to": PathUtil.join(toPath, from.name, isWindows),
|
|
||||||
"file_num": "0",
|
|
||||||
"show_hidden": showHidden.toString(),
|
|
||||||
"is_remote": (!(items.isLocal!)).toString()
|
|
||||||
};
|
|
||||||
_ffi.target?.setByName("send_files", jsonEncode(msg));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,43 +493,34 @@ class FileModel extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendRemoveFile(String path, int fileNum, bool isLocal) {
|
sendRemoveFile(String path, int fileNum, bool isLocal) {
|
||||||
final msg = {
|
_ffi.target?.bind.sessionRemoveFile(id: '${_ffi.target?.getId()}', actId: _jobId, path: path, isRemote: !isLocal, fileNum: fileNum);
|
||||||
"id": _jobId.toString(),
|
|
||||||
"path": path,
|
|
||||||
"file_num": fileNum.toString(),
|
|
||||||
"is_remote": (!(isLocal)).toString()
|
|
||||||
};
|
|
||||||
_ffi.target?.setByName("remove_file", jsonEncode(msg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendRemoveEmptyDir(String path, int fileNum, bool isLocal) {
|
sendRemoveEmptyDir(String path, int fileNum, bool isLocal) {
|
||||||
final msg = {
|
_ffi.target?.bind.sessionRemoveAllEmptyDirs(id: '${_ffi.target?.getId()}', actId: _jobId, path: path, isRemote: !isLocal);
|
||||||
"id": _jobId.toString(),
|
|
||||||
"path": path,
|
|
||||||
"is_remote": (!isLocal).toString()
|
|
||||||
};
|
|
||||||
_ffi.target?.setByName("remove_all_empty_dirs", jsonEncode(msg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createDir(String path) {
|
createDir(String path) async {
|
||||||
_jobId++;
|
_jobId++;
|
||||||
final msg = {
|
_ffi.target?.bind.sessionCreateDir(id: '${_ffi.target?.getId()}', actId: _jobId, path: path, isRemote: !isLocal);
|
||||||
"id": _jobId.toString(),
|
|
||||||
"path": path,
|
|
||||||
"is_remote": (!isLocal).toString()
|
|
||||||
};
|
|
||||||
_ffi.target?.setByName("create_dir", jsonEncode(msg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelJob(int id) {
|
cancelJob(int id) async {
|
||||||
_ffi.target?.setByName("cancel_job", id.toString());
|
_ffi.target?.bind.sessionCancelJob(id: '${_ffi.target?.getId()}', actId: id);
|
||||||
jobReset();
|
jobReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
changeSortStyle(SortBy sort) {
|
changeSortStyle(SortBy sort, {bool? isLocal}) {
|
||||||
_sortStyle = sort;
|
_sortStyle = sort;
|
||||||
_currentLocalDir.changeSortStyle(sort);
|
if (isLocal == null) {
|
||||||
_currentRemoteDir.changeSortStyle(sort);
|
// compatible for mobile logic
|
||||||
|
_currentLocalDir.changeSortStyle(sort);
|
||||||
|
_currentRemoteDir.changeSortStyle(sort);
|
||||||
|
} else if (isLocal) {
|
||||||
|
_currentLocalDir.changeSortStyle(sort);
|
||||||
|
} else {
|
||||||
|
_currentRemoteDir.changeSortStyle(sort);
|
||||||
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ class RustDeskMultiWindowManager {
|
|||||||
case WindowType.RemoteDesktop:
|
case WindowType.RemoteDesktop:
|
||||||
return _remoteDesktopWindowId;
|
return _remoteDesktopWindowId;
|
||||||
case WindowType.FileTransfer:
|
case WindowType.FileTransfer:
|
||||||
break;
|
return _fileTransferWindowId;
|
||||||
case WindowType.PortForward:
|
case WindowType.PortForward:
|
||||||
break;
|
break;
|
||||||
case WindowType.Unknown:
|
case WindowType.Unknown:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user