Backup
This commit is contained in:
parent
d4a926ddad
commit
b991570285
@ -36,12 +36,17 @@ class SftpManagerTab
|
||||
private float $lastRemoteClickTime = 0.0;
|
||||
private ProgressBar $transferProgressBar;
|
||||
private Label $transferInfoLabel;
|
||||
private Label $transferBytesLabel;
|
||||
private array $pendingUploadQueue = [];
|
||||
private int $totalUploadFiles = 0;
|
||||
private int $completedUploadFiles = 0;
|
||||
private int $totalUploadBytes = 0;
|
||||
private int $completedUploadBytes = 0;
|
||||
private array $pendingDownloadQueue = [];
|
||||
private int $totalDownloadFiles = 0;
|
||||
private int $completedDownloadFiles = 0;
|
||||
private int $totalDownloadBytes = 0;
|
||||
private int $completedDownloadBytes = 0;
|
||||
|
||||
public function __construct(
|
||||
string &$apiKey,
|
||||
@ -112,9 +117,11 @@ class SftpManagerTab
|
||||
|
||||
// Transfer-Info + ProgressBar
|
||||
$this->transferInfoLabel = new Label('Kein Transfer aktiv', 'text-xs text-gray-600 mt-2');
|
||||
$this->transferBytesLabel = new Label('', 'text-xs text-gray-600');
|
||||
$this->transferProgressBar = new ProgressBar('mt-1');
|
||||
$this->transferProgressBar->setValue(0.0);
|
||||
$transferContainer->addComponent($this->transferInfoLabel);
|
||||
$transferContainer->addComponent($this->transferBytesLabel);
|
||||
$transferContainer->addComponent($this->transferProgressBar);
|
||||
|
||||
$this->tab->addComponent($localBrowserContainer);
|
||||
@ -807,26 +814,30 @@ class SftpManagerTab
|
||||
$remoteDir = '/';
|
||||
}
|
||||
|
||||
// Upload-Größe vorab bestimmen
|
||||
$stats = $this->calculateLocalUploadStats($localPath, $localRow);
|
||||
$totalBytes = $stats['bytes'];
|
||||
$fileCount = $stats['files'];
|
||||
$dirCount = $stats['dirs'];
|
||||
// Upload-Queue inkl. Byte-Größen vorbereiten
|
||||
$this->pendingUploadQueue = $this->buildUploadQueue($localPath, $localRow, $remoteDir);
|
||||
$this->totalUploadFiles = count($this->pendingUploadQueue);
|
||||
$this->completedUploadFiles = 0;
|
||||
$this->totalUploadBytes = 0;
|
||||
$this->completedUploadBytes = 0;
|
||||
|
||||
foreach ($this->pendingUploadQueue as $item) {
|
||||
$this->totalUploadBytes += (int) ($item['size'] ?? 0);
|
||||
}
|
||||
|
||||
$this->transferProgressBar->setValue(0.0);
|
||||
$this->transferInfoLabel->setText(
|
||||
sprintf(
|
||||
'Upload: %d Dateien, %d Ordner (%.2f MB)',
|
||||
$fileCount,
|
||||
$dirCount,
|
||||
$totalBytes > 0 ? ($totalBytes / (1024 * 1024)) : 0,
|
||||
'Upload: %d Dateien',
|
||||
$this->totalUploadFiles,
|
||||
),
|
||||
);
|
||||
$this->transferBytesLabel->setText(
|
||||
sprintf(
|
||||
'0.00 / %.2f MB',
|
||||
$this->totalUploadBytes > 0 ? ($this->totalUploadBytes / (1024 * 1024)) : 0,
|
||||
),
|
||||
);
|
||||
|
||||
// Upload-Queue für virtuelle ProgressBar vorbereiten
|
||||
$this->pendingUploadQueue = $this->buildUploadQueue($localPath, $localRow, $remoteDir);
|
||||
$this->totalUploadFiles = count($this->pendingUploadQueue);
|
||||
$this->completedUploadFiles = 0;
|
||||
|
||||
if ($this->totalUploadFiles <= 0) {
|
||||
$this->transferProgressBar->setValue(1.0);
|
||||
@ -904,6 +915,7 @@ class SftpManagerTab
|
||||
$queue[] = [
|
||||
'local' => $localPath,
|
||||
'remote' => $remoteBase . '/' . basename($localPath),
|
||||
'size' => is_file($localPath) ? (int) @filesize($localPath) : 0,
|
||||
];
|
||||
return $queue;
|
||||
}
|
||||
@ -941,6 +953,7 @@ class SftpManagerTab
|
||||
$queue[] = [
|
||||
'local' => $localChild,
|
||||
'remote' => $remoteChild,
|
||||
'size' => is_file($localChild) ? (int) @filesize($localChild) : 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -973,6 +986,7 @@ class SftpManagerTab
|
||||
$item = array_shift($this->pendingUploadQueue);
|
||||
$localPath = $item['local'];
|
||||
$remotePath = $item['remote'];
|
||||
$fileSize = (int) ($item['size'] ?? 0);
|
||||
|
||||
$selectedServerRef = &$serverListTab->selectedServer;
|
||||
$sftpTab = $this;
|
||||
@ -1020,7 +1034,7 @@ class SftpManagerTab
|
||||
return ['error' => $e->getMessage()];
|
||||
}
|
||||
},
|
||||
function ($result) use ($sftpTab, &$currentPrivateKeyPath, $serverListTab, $statusLabel) {
|
||||
function ($result) use ($sftpTab, &$currentPrivateKeyPath, $serverListTab, $statusLabel, $fileSize) {
|
||||
if (isset($result['error'])) {
|
||||
$sftpTab->transferInfoLabel->setText('Upload fehlgeschlagen: ' . $result['error']);
|
||||
$statusLabel->setText('Fehler beim Hochladen: ' . $result['error']);
|
||||
@ -1029,9 +1043,17 @@ class SftpManagerTab
|
||||
|
||||
if (isset($result['success'])) {
|
||||
$sftpTab->completedUploadFiles++;
|
||||
$progress = $sftpTab->totalUploadFiles > 0
|
||||
? ($sftpTab->completedUploadFiles / $sftpTab->totalUploadFiles)
|
||||
: 1.0;
|
||||
$sftpTab->completedUploadBytes += $fileSize;
|
||||
|
||||
$progress = 0.0;
|
||||
if ($sftpTab->totalUploadBytes > 0) {
|
||||
$progress = $sftpTab->completedUploadBytes / $sftpTab->totalUploadBytes;
|
||||
} elseif ($sftpTab->totalUploadFiles > 0) {
|
||||
$progress = $sftpTab->completedUploadFiles / $sftpTab->totalUploadFiles;
|
||||
} else {
|
||||
$progress = 1.0;
|
||||
}
|
||||
|
||||
$sftpTab->transferProgressBar->setValue($progress);
|
||||
$sftpTab->transferInfoLabel->setText(
|
||||
sprintf(
|
||||
@ -1040,6 +1062,17 @@ class SftpManagerTab
|
||||
$sftpTab->totalUploadFiles,
|
||||
),
|
||||
);
|
||||
$sftpTab->transferBytesLabel->setText(
|
||||
sprintf(
|
||||
'%.2f / %.2f MB',
|
||||
$sftpTab->completedUploadBytes > 0
|
||||
? ($sftpTab->completedUploadBytes / (1024 * 1024))
|
||||
: 0,
|
||||
$sftpTab->totalUploadBytes > 0
|
||||
? ($sftpTab->totalUploadBytes / (1024 * 1024))
|
||||
: 0,
|
||||
),
|
||||
);
|
||||
|
||||
// Nächste Datei starten
|
||||
$sftpTab->startNextUploadTask($currentPrivateKeyPath, $serverListTab, $statusLabel);
|
||||
@ -1081,6 +1114,7 @@ class SftpManagerTab
|
||||
$item = array_shift($this->pendingDownloadQueue);
|
||||
$remotePath = $item['remote'];
|
||||
$localPath = $item['local'];
|
||||
$fileSize = (int) ($item['size'] ?? 0);
|
||||
|
||||
$selectedServerRef = &$serverListTab->selectedServer;
|
||||
$sftpTab = $this;
|
||||
@ -1119,7 +1153,7 @@ class SftpManagerTab
|
||||
return ['error' => $e->getMessage()];
|
||||
}
|
||||
},
|
||||
function ($result) use ($sftpTab, &$currentPrivateKeyPath, $serverListTab, $statusLabel, $localRootDir) {
|
||||
function ($result) use ($sftpTab, &$currentPrivateKeyPath, $serverListTab, $statusLabel, $localRootDir, $fileSize) {
|
||||
if (isset($result['error'])) {
|
||||
$sftpTab->transferInfoLabel->setText('Download fehlgeschlagen: ' . $result['error']);
|
||||
$statusLabel->setText('Fehler beim Herunterladen: ' . $result['error']);
|
||||
@ -1128,9 +1162,17 @@ class SftpManagerTab
|
||||
|
||||
if (isset($result['success'])) {
|
||||
$sftpTab->completedDownloadFiles++;
|
||||
$progress = $sftpTab->totalDownloadFiles > 0
|
||||
? ($sftpTab->completedDownloadFiles / $sftpTab->totalDownloadFiles)
|
||||
: 1.0;
|
||||
$sftpTab->completedDownloadBytes += $fileSize;
|
||||
|
||||
$progress = 0.0;
|
||||
if ($sftpTab->totalDownloadBytes > 0) {
|
||||
$progress = $sftpTab->completedDownloadBytes / $sftpTab->totalDownloadBytes;
|
||||
} elseif ($sftpTab->totalDownloadFiles > 0) {
|
||||
$progress = $sftpTab->completedDownloadFiles / $sftpTab->totalDownloadFiles;
|
||||
} else {
|
||||
$progress = 1.0;
|
||||
}
|
||||
|
||||
$sftpTab->transferProgressBar->setValue($progress);
|
||||
$sftpTab->transferInfoLabel->setText(
|
||||
sprintf(
|
||||
@ -1139,6 +1181,17 @@ class SftpManagerTab
|
||||
$sftpTab->totalDownloadFiles,
|
||||
),
|
||||
);
|
||||
$sftpTab->transferBytesLabel->setText(
|
||||
sprintf(
|
||||
'%.2f / %.2f MB',
|
||||
$sftpTab->completedDownloadBytes > 0
|
||||
? ($sftpTab->completedDownloadBytes / (1024 * 1024))
|
||||
: 0,
|
||||
$sftpTab->totalDownloadBytes > 0
|
||||
? ($sftpTab->totalDownloadBytes / (1024 * 1024))
|
||||
: 0,
|
||||
),
|
||||
);
|
||||
|
||||
// Nächste Datei herunterladen
|
||||
$sftpTab->startNextDownloadTask($currentPrivateKeyPath, $serverListTab, $statusLabel, $localRootDir);
|
||||
@ -1219,19 +1272,24 @@ class SftpManagerTab
|
||||
$queue = [];
|
||||
$files = 0;
|
||||
$dirs = 0;
|
||||
$totalBytes = 0;
|
||||
|
||||
$isDir = (bool) ($remoteRow['isDir'] ?? false);
|
||||
if (!$isDir) {
|
||||
$stat = $sftp->stat($remotePath);
|
||||
$size = (int) ($stat['size'] ?? 0);
|
||||
$queue[] = [
|
||||
'remote' => $remotePath,
|
||||
'local' => rtrim($localDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . basename($remotePath),
|
||||
'size' => $size,
|
||||
];
|
||||
$files = 1;
|
||||
$totalBytes = $size;
|
||||
} else {
|
||||
$rootLocal = rtrim($localDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . basename($remotePath);
|
||||
|
||||
$collect = null;
|
||||
$collect = function (string $srcDir, string $dstDir) use (&$collect, $sftp, &$queue, &$files, &$dirs) {
|
||||
$collect = function (string $srcDir, string $dstDir) use (&$collect, $sftp, &$queue, &$files, &$dirs, &$totalBytes) {
|
||||
$dirs++;
|
||||
|
||||
$entries = $sftp->nlist($srcDir);
|
||||
@ -1253,11 +1311,14 @@ class SftpManagerTab
|
||||
if ($isDirChild) {
|
||||
$collect($remoteChild, $localChild);
|
||||
} else {
|
||||
$size = (int) ($stat['size'] ?? 0);
|
||||
$queue[] = [
|
||||
'remote' => $remoteChild,
|
||||
'local' => $localChild,
|
||||
'size' => $size,
|
||||
];
|
||||
$files++;
|
||||
$totalBytes += $size;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1271,6 +1332,7 @@ class SftpManagerTab
|
||||
'files' => $files,
|
||||
'dirs' => $dirs,
|
||||
'localDir' => $localDir,
|
||||
'totalBytes' => $totalBytes,
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
return ['error' => $e->getMessage()];
|
||||
@ -1292,14 +1354,18 @@ class SftpManagerTab
|
||||
$queue = $result['queue'] ?? [];
|
||||
$files = (int) ($result['files'] ?? 0);
|
||||
$dirs = (int) ($result['dirs'] ?? 0);
|
||||
$totalBytes = (int) ($result['totalBytes'] ?? 0);
|
||||
|
||||
$sftpTab->pendingDownloadQueue = $queue;
|
||||
$sftpTab->totalDownloadFiles = count($queue);
|
||||
$sftpTab->completedDownloadFiles = 0;
|
||||
$sftpTab->totalDownloadBytes = $totalBytes;
|
||||
$sftpTab->completedDownloadBytes = 0;
|
||||
|
||||
if ($sftpTab->totalDownloadFiles <= 0) {
|
||||
$sftpTab->transferProgressBar->setValue(1.0);
|
||||
$sftpTab->transferInfoLabel->setText('Keine Dateien zum Herunterladen');
|
||||
$sftpTab->transferBytesLabel->setText('');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1311,6 +1377,12 @@ class SftpManagerTab
|
||||
$dirs,
|
||||
),
|
||||
);
|
||||
$sftpTab->transferBytesLabel->setText(
|
||||
sprintf(
|
||||
'0.00 / %.2f MB',
|
||||
$totalBytes > 0 ? ($totalBytes / (1024 * 1024)) : 0,
|
||||
),
|
||||
);
|
||||
|
||||
$localDir = $result['localDir'] ?? '';
|
||||
$sftpTab->startNextDownloadTask($currentPrivateKeyPath, $serverListTab, $statusLabel, $localDir);
|
||||
|
||||
@ -13,7 +13,7 @@ class FileBrowser extends Container
|
||||
private $onRenameFile = null;
|
||||
private $onDeleteFile = null;
|
||||
private bool $isRemote = false;
|
||||
private ?string $lastClickPath = null;
|
||||
private null|string $lastClickPath = null;
|
||||
private float $lastClickTime = 0.0;
|
||||
|
||||
public function __construct(string $initialPath = '.', bool $isRemote = false, string $style = '')
|
||||
@ -136,10 +136,7 @@ class FileBrowser extends Container
|
||||
$now = microtime(true);
|
||||
$doubleClickThreshold = 0.4; // Sekunden
|
||||
|
||||
if (
|
||||
$fileBrowser->lastClickPath !== $path ||
|
||||
($now - $fileBrowser->lastClickTime) > $doubleClickThreshold
|
||||
) {
|
||||
if ($fileBrowser->lastClickPath !== $path || ($now - $fileBrowser->lastClickTime) > $doubleClickThreshold) {
|
||||
// Erster Klick: nur merken
|
||||
$fileBrowser->lastClickPath = $path;
|
||||
$fileBrowser->lastClickTime = $now;
|
||||
@ -288,16 +285,14 @@ class FileBrowser extends Container
|
||||
public function renderActionsCell(array $rowData, int $rowIndex): Container
|
||||
{
|
||||
// Match the cell style from Table (100px width for icon buttons)
|
||||
$container = new Container(
|
||||
'w-25 py-1 border-r border-gray-300 flex flex-row items-center justify-center gap-1',
|
||||
);
|
||||
$container = new Container('w-25 border-r border-gray-300 flex flex-row items-center justify-center gap-1');
|
||||
|
||||
// Only show action buttons for files (not directories)
|
||||
if (!($rowData['isDir'] ?? false) && !empty($rowData['path'])) {
|
||||
$fileBrowser = $this;
|
||||
|
||||
// Edit button
|
||||
$editButton = new Button('', 'p-1 text-blue-500 hover:text-blue-600 flex items-center justify-center');
|
||||
$editButton = new Button('', 'text-blue-500 hover:text-blue-600 flex items-center justify-center');
|
||||
$editIcon = new Icon(\PHPNative\Tailwind\Data\Icon::edit, 16, 'text-blue-500');
|
||||
$editButton->setIcon($editIcon);
|
||||
$editButton->setOnClick(function () use ($fileBrowser, $rowData) {
|
||||
@ -308,7 +303,7 @@ class FileBrowser extends Container
|
||||
$container->addComponent($editButton);
|
||||
|
||||
// Rename button
|
||||
$renameButton = new Button('', 'p-1 text-amber-500 hover:text-amber-600 flex items-center justify-center');
|
||||
$renameButton = new Button('', 'text-amber-500 hover:text-amber-600 flex items-center justify-center');
|
||||
$renameIcon = new Icon(\PHPNative\Tailwind\Data\Icon::pen, 16, 'text-amber-500');
|
||||
$renameButton->setIcon($renameIcon);
|
||||
$renameButton->setOnClick(function () use ($fileBrowser, $rowData) {
|
||||
@ -319,7 +314,7 @@ class FileBrowser extends Container
|
||||
$container->addComponent($renameButton);
|
||||
|
||||
// Delete button
|
||||
$deleteButton = new Button('', 'p-1 text-red-500 hover:text-red-600 flex items-center justify-center');
|
||||
$deleteButton = new Button('', 'text-red-500 hover:text-red-600 flex items-center justify-center');
|
||||
$deleteIcon = new Icon(\PHPNative\Tailwind\Data\Icon::trash, 16, 'text-red-500');
|
||||
$deleteButton->setIcon($deleteIcon);
|
||||
$deleteButton->setOnClick(function () use ($fileBrowser, $rowData) {
|
||||
|
||||
@ -91,18 +91,6 @@ class Table extends Container
|
||||
if ($preserveScroll && $scrollPosition !== null) {
|
||||
$this->bodyContainer->setScrollPosition($scrollPosition['x'], $scrollPosition['y']);
|
||||
}
|
||||
|
||||
// Debug-Ausgabe: Größe des Tabellen-Body und Viewport
|
||||
$bodySize = $this->bodyContainer->getContentSize();
|
||||
$bodyViewport = $this->bodyContainer->getContentViewport();
|
||||
error_log(
|
||||
sprintf(
|
||||
'Table body debug: rows=%d, contentHeight=%d, viewportHeight=%d',
|
||||
count($data),
|
||||
(int) ($bodySize['height'] ?? 0),
|
||||
(int) $bodyViewport->height,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user