From a66ed70532c29080e00e516b4e0622e20dc2ab7b Mon Sep 17 00:00:00 2001 From: RafayAhmad7548 Date: Thu, 14 Aug 2025 15:45:41 +0500 Subject: [PATCH] move working --- lib/sftp_explorer.dart | 67 ++++++++++++++++++++++++++++++ lib/sftp_provider.dart | 12 ++++++ lib/sftp_worker.dart | 24 +++++++++++ lib/widgets/operation_buttons.dart | 6 ++- 4 files changed, 107 insertions(+), 2 deletions(-) diff --git a/lib/sftp_explorer.dart b/lib/sftp_explorer.dart index 7c4f4b6..3fdc9b8 100644 --- a/lib/sftp_explorer.dart +++ b/lib/sftp_explorer.dart @@ -1,10 +1,12 @@ import 'dart:io'; +import 'package:dartssh2/dartssh2.dart'; import 'package:file_picker/file_picker.dart'; import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; import 'package:fluxcloud/main.dart'; import 'package:fluxcloud/sftp_provider.dart'; +import 'package:path/path.dart'; import 'package:provider/provider.dart'; import 'widgets/operation_buttons.dart'; @@ -74,6 +76,7 @@ class SftpExplorer extends StatelessWidget { ], ), floatingActionButton: _buildFABs(context), + bottomNavigationBar: _buildCopyMoveButton(context), body: PopScope( canPop: false, onPopInvokedWithResult: (_, _) { @@ -203,4 +206,68 @@ class SftpExplorer extends StatelessWidget { ); } + Widget _buildCopyMoveButton(BuildContext context) { + return Selector?, bool)>( + selector: (_, sftpProvider) => (sftpProvider.toBeMovedOrCopied, sftpProvider.isCopy), + builder: (_, data, __) { + final (toBeMovedOrCopied, isCopy) = data; + if (toBeMovedOrCopied == null) { + return const SizedBox.shrink(); + } + return Padding( + padding: const EdgeInsets.all(12), + child: Row( + spacing: 10, + children: [ + Expanded(child: ElevatedButton( + onPressed: () async { + final sftpProvider = context.read(); + for (final filePath in toBeMovedOrCopied) { + try { + if (isCopy) { + + } + else { + final fileName = basename(filePath); + await sftpProvider.sftpWorker.rename(filePath, '${sftpProvider.path}$fileName'); + } + } + catch (e) { + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(buildErrorSnackBar(context, e.toString())); + } + } + } + sftpProvider.setCopyOrMoveFiles(null, isCopy); + sftpProvider.listDir(); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + foregroundColor: Theme.of(context).colorScheme.onSecondaryContainer + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Text(isCopy ? 'Copy Here' : 'Move Here'), + ), + )), + IconButton( + onPressed: () { + context.read().setCopyOrMoveFiles(null, isCopy); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + foregroundColor: Theme.of(context).colorScheme.onSecondaryContainer + ), + icon: Padding( + padding: const EdgeInsets.all(4), + child: Icon(Icons.close), + ), + ) + ], + ), + ); + } + ); + } + } diff --git a/lib/sftp_provider.dart b/lib/sftp_provider.dart index 1059298..e3e12fd 100644 --- a/lib/sftp_provider.dart +++ b/lib/sftp_provider.dart @@ -11,6 +11,9 @@ class SftpProvider extends ChangeNotifier { double? _uploadProgress; double? _downloadProgress; + + List? _toBeMovedOrCopied; + bool _isCopy = false; SftpProvider(this._sftpWorker) { listDir(); @@ -24,6 +27,9 @@ class SftpProvider extends ChangeNotifier { double? get uploadProgress => _uploadProgress; double? get downloadProgress => _downloadProgress; + + List? get toBeMovedOrCopied => _toBeMovedOrCopied; + bool get isCopy => _isCopy; Future listDir() async { _isLoading = true; @@ -54,4 +60,10 @@ class SftpProvider extends ChangeNotifier { notifyListeners(); } + void setCopyOrMoveFiles(List? files, bool isCopy) { + _toBeMovedOrCopied = files; + _isCopy = isCopy; + notifyListeners(); + } + } diff --git a/lib/sftp_worker.dart b/lib/sftp_worker.dart index c6aaaae..87697bf 100644 --- a/lib/sftp_worker.dart +++ b/lib/sftp_worker.dart @@ -50,6 +50,13 @@ class DownloadFile extends SftpCommand { DownloadFile(this.file, this.path, this.downloadPath); } +class Copy extends SftpCommand { + final String filePath; + final String copyToPath; + + Copy(this.filePath, this.copyToPath); +} + class SftpWorker { @@ -227,6 +234,15 @@ class SftpWorker { } case DownloadFile(): downloadController.add((id, command)); + case Copy(:final filePath, :final copyToPath): + try { + // TODO: complete this + sendPort.send((id, 0)); + } + on SftpStatusError catch (e) { + sendPort.send((id, RemoteError(e.message, ''))); + } + } }); } @@ -309,4 +325,12 @@ class SftpWorker { return controller.stream; } + Future copy(String filePath, String copyToPath) async { + final completer = Completer.sync(); + final id = _idCounter++; + _activeRequests[id] = completer; + _commands.send((id, Copy(filePath, copyToPath))); + await completer.future; + } + } diff --git a/lib/widgets/operation_buttons.dart b/lib/widgets/operation_buttons.dart index 578657b..82bc312 100644 --- a/lib/widgets/operation_buttons.dart +++ b/lib/widgets/operation_buttons.dart @@ -20,13 +20,15 @@ class OperationButtons extends StatelessWidget { children: [ IconButton( onPressed: () { - + final filePaths = dirEntries.map((dirEntry) => '${sftpProvider.path}${dirEntry.filename}').toList(); + sftpProvider.setCopyOrMoveFiles(filePaths, false); }, icon: Icon(Icons.drive_file_move) ), IconButton( onPressed: () { - + final filePaths = dirEntries.map((dirEntry) => '${sftpProvider.path}${dirEntry.filename}').toList(); + sftpProvider.setCopyOrMoveFiles(filePaths, true); }, icon: Icon(Icons.copy) ),