561 lines
17 KiB
C#
561 lines
17 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Windows;
|
|
using System.Windows.Data;
|
|
using System.Windows.Input;
|
|
using System.Windows.Threading;
|
|
using Crysome.Common.Model;
|
|
using Crysome.Common.Network.Packets;
|
|
using Crysome.Common.Network.Packets.Client;
|
|
using Crysome.Common.Network.Packets.Server;
|
|
using Crysome.Server.Model;
|
|
using Crysome.Server.Network;
|
|
using Microsoft.Win32;
|
|
|
|
namespace Crysome.Server.ViewModel;
|
|
|
|
public class FileExplorerViewModel : ViewModelBase, IDisposable
|
|
{
|
|
private bool _downloadProgressVisible;
|
|
|
|
private string _downloadStatusText;
|
|
|
|
private double _downloadProgress;
|
|
|
|
private string _pendingDownloadSavePath;
|
|
|
|
private Stopwatch _downloadStopwatch;
|
|
|
|
private readonly MainViewModel _mainVm;
|
|
|
|
private bool _disposed;
|
|
|
|
private string[] _drives;
|
|
|
|
private FileSystemEntry _currentDirectory;
|
|
|
|
private FileSystemEntry _selectedFile;
|
|
|
|
private string _sortMode = "Name";
|
|
|
|
public bool DownloadProgressVisible
|
|
{
|
|
get
|
|
{
|
|
return _downloadProgressVisible;
|
|
}
|
|
set
|
|
{
|
|
_downloadProgressVisible = value;
|
|
OnPropertyChanged(() => DownloadProgressVisible);
|
|
}
|
|
}
|
|
|
|
public string DownloadStatusText
|
|
{
|
|
get
|
|
{
|
|
return _downloadStatusText;
|
|
}
|
|
set
|
|
{
|
|
_downloadStatusText = value;
|
|
OnPropertyChanged(() => DownloadStatusText);
|
|
}
|
|
}
|
|
|
|
public double DownloadProgress
|
|
{
|
|
get
|
|
{
|
|
return _downloadProgress;
|
|
}
|
|
set
|
|
{
|
|
_downloadProgress = value;
|
|
OnPropertyChanged(() => DownloadProgress);
|
|
}
|
|
}
|
|
|
|
public ObservableCollection<FileSystemEntry> Files { get; set; }
|
|
|
|
public ICollectionView FilesView { get; private set; }
|
|
|
|
public Stack<FileSystemEntry> BackHistory { get; set; }
|
|
|
|
public Stack<FileSystemEntry> ForwardHistory { get; set; }
|
|
|
|
public bool CanGoBackward => BackHistory.Count > 0;
|
|
|
|
public bool CanGoForward => ForwardHistory.Count > 0;
|
|
|
|
public string[] Drives
|
|
{
|
|
get
|
|
{
|
|
return _drives;
|
|
}
|
|
set
|
|
{
|
|
_drives = value;
|
|
OnPropertyChanged(() => Drives);
|
|
}
|
|
}
|
|
|
|
public FileSystemEntry CurrentDirectory
|
|
{
|
|
get
|
|
{
|
|
return _currentDirectory;
|
|
}
|
|
set
|
|
{
|
|
_currentDirectory = value;
|
|
OnPropertyChanged(() => CurrentDirectory);
|
|
}
|
|
}
|
|
|
|
public FileSystemEntry SelectedFile
|
|
{
|
|
get
|
|
{
|
|
return _selectedFile;
|
|
}
|
|
set
|
|
{
|
|
_selectedFile = value;
|
|
OnPropertyChanged(() => _selectedFile);
|
|
}
|
|
}
|
|
|
|
public string SortMode
|
|
{
|
|
get
|
|
{
|
|
return _sortMode;
|
|
}
|
|
set
|
|
{
|
|
_sortMode = value ?? "Name";
|
|
OnPropertyChanged(() => SortMode);
|
|
ApplySort();
|
|
}
|
|
}
|
|
|
|
public string[] SortOptions { get; } = new string[4] { "Name", "DateModified", "Size", "Type" };
|
|
|
|
public ICommand NavigateCommand { get; set; }
|
|
|
|
public ICommand NavigateSelectedCommand { get; set; }
|
|
|
|
public ICommand OpenCommand { get; set; }
|
|
|
|
public ICommand SaveAsCommand { get; set; }
|
|
|
|
public ICommand UploadCommand { get; set; }
|
|
|
|
public ICommand PropertiesCommand { get; set; }
|
|
|
|
public ICommand NavigateUpCommand { get; set; }
|
|
|
|
public ICommand NavigateForwardCommand { get; set; }
|
|
|
|
public ICommand NavigateBackCommand { get; set; }
|
|
|
|
public ICommand DeleteFileCommand { get; set; }
|
|
|
|
public ClientInfo Client { get; set; }
|
|
|
|
public ICommand GoBackToClientsCommand { get; set; }
|
|
|
|
public FileExplorerViewModel(CrysomeServer server, ClientInfo client, MainViewModel mainVm)
|
|
{
|
|
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0109: Expected O, but got Unknown
|
|
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0154: Expected O, but got Unknown
|
|
FileExplorerViewModel fileExplorerViewModel = this;
|
|
_mainVm = mainVm;
|
|
Files = new ObservableCollection<FileSystemEntry>();
|
|
FilesView = CollectionViewSource.GetDefaultView(Files);
|
|
ApplySort();
|
|
BackHistory = new Stack<FileSystemEntry>();
|
|
ForwardHistory = new Stack<FileSystemEntry>();
|
|
Client = client;
|
|
_mainVm.ClientsVM.RegisterActiveFileExplorer(client.Owner, this);
|
|
if (server.ClientCount > 0)
|
|
{
|
|
long num = _mainVm.ClientsVM.NextExplorerOpId();
|
|
_mainVm.ClientsVM.RegisterGetDirectoryCallback(client.Owner, num, delegate(GetDirectoryResponsePacket p)
|
|
{
|
|
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
|
|
{
|
|
fileExplorerViewModel.ApplyGetDirectoryResponse(p);
|
|
});
|
|
});
|
|
client.Owner.SendPacket((IPacket)new GetDirectoryRequestPacket(string.Empty, num));
|
|
long requestId = _mainVm.ClientsVM.NextExplorerOpId();
|
|
_mainVm.ClientsVM.RegisterGetDrivesCallback(client.Owner, requestId, delegate(GetDrivesResponsePacket p)
|
|
{
|
|
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
|
|
{
|
|
fileExplorerViewModel.ApplyGetDrivesResponse(p);
|
|
});
|
|
});
|
|
client.Owner.SendPacket((IPacket)new GetDrivesRequestPacket
|
|
{
|
|
RequestId = requestId
|
|
});
|
|
}
|
|
NavigateCommand = new RelayCommand<string>(NavigateWithHistory);
|
|
NavigateSelectedCommand = new RelayCommand<string>(NavigateSelected);
|
|
OpenCommand = new RelayCommand<string>(OpenSelected);
|
|
SaveAsCommand = new RelayCommand<string>(SaveAsSelected);
|
|
UploadCommand = new RelayCommand<string>(delegate
|
|
{
|
|
fileExplorerViewModel.UploadFile();
|
|
});
|
|
PropertiesCommand = new RelayCommand<string>(ShowProperties);
|
|
NavigateUpCommand = new RelayCommand<string>(NavigateUp);
|
|
NavigateForwardCommand = new RelayCommand<string>(NavigateForward);
|
|
NavigateBackCommand = new RelayCommand<string>(NavigateBack);
|
|
DeleteFileCommand = new RelayCommand<string>(DeleteFile);
|
|
GoBackToClientsCommand = new RelayCommand<string>(delegate
|
|
{
|
|
mainVm.GoToClients();
|
|
});
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!_disposed)
|
|
{
|
|
_disposed = true;
|
|
if (Client?.Owner != null)
|
|
{
|
|
_mainVm.ClientsVM.UnregisterActiveFileExplorer(Client.Owner, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ApplySort()
|
|
{
|
|
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
|
|
if (FilesView == null)
|
|
{
|
|
return;
|
|
}
|
|
using (FilesView.DeferRefresh())
|
|
{
|
|
((Collection<SortDescription>)(object)FilesView.SortDescriptions).Clear();
|
|
switch (SortMode)
|
|
{
|
|
case "DateModified":
|
|
((Collection<SortDescription>)(object)FilesView.SortDescriptions).Add(new SortDescription("LastWriteUtcTicks", ListSortDirection.Descending));
|
|
break;
|
|
case "Size":
|
|
((Collection<SortDescription>)(object)FilesView.SortDescriptions).Add(new SortDescription("Size", ListSortDirection.Descending));
|
|
break;
|
|
case "Type":
|
|
((Collection<SortDescription>)(object)FilesView.SortDescriptions).Add(new SortDescription("Type", ListSortDirection.Ascending));
|
|
((Collection<SortDescription>)(object)FilesView.SortDescriptions).Add(new SortDescription("Name", ListSortDirection.Ascending));
|
|
break;
|
|
default:
|
|
((Collection<SortDescription>)(object)FilesView.SortDescriptions).Add(new SortDescription("Name", ListSortDirection.Ascending));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ApplyGetDirectoryResponse(GetDirectoryResponsePacket directoryResponse)
|
|
{
|
|
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0028: Expected O, but got Unknown
|
|
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0113: Expected O, but got Unknown
|
|
//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01b0: Expected O, but got Unknown
|
|
Files.Clear();
|
|
CurrentDirectory = new FileSystemEntry(directoryResponse.Name, directoryResponse.Path, 0L, (FileType)0, 0L, (byte[])null);
|
|
OnPropertyChanged(() => CanGoBackward);
|
|
OnPropertyChanged(() => CanGoForward);
|
|
string[] folders = directoryResponse.Folders;
|
|
int num = ((folders != null) ? folders.Length : 0);
|
|
long[] folderLastWriteUtcTicks = directoryResponse.FolderLastWriteUtcTicks;
|
|
byte[][] folderIconPng = directoryResponse.FolderIconPng;
|
|
for (int num2 = 0; num2 < num; num2++)
|
|
{
|
|
long num3 = ((folderLastWriteUtcTicks != null && num2 < folderLastWriteUtcTicks.Length) ? folderLastWriteUtcTicks[num2] : 0);
|
|
byte[] array = ((folderIconPng != null && num2 < folderIconPng.Length) ? folderIconPng[num2] : null);
|
|
Files.Add(new FileSystemEntry(directoryResponse.Folders[num2], Path.Combine(CurrentDirectory.Path, directoryResponse.Folders[num2]), 0L, (FileType)0, num3, array));
|
|
}
|
|
string[] files = directoryResponse.Files;
|
|
int num4 = ((files != null) ? files.Length : 0);
|
|
long[] fileLastWriteUtcTicks = directoryResponse.FileLastWriteUtcTicks;
|
|
byte[][] fileIconPng = directoryResponse.FileIconPng;
|
|
for (int num5 = 0; num5 < num4; num5++)
|
|
{
|
|
long num6 = ((fileLastWriteUtcTicks != null && num5 < fileLastWriteUtcTicks.Length) ? fileLastWriteUtcTicks[num5] : 0);
|
|
byte[] array2 = ((fileIconPng != null && num5 < fileIconPng.Length) ? fileIconPng[num5] : null);
|
|
Files.Add(new FileSystemEntry(directoryResponse.Files[num5], Path.Combine(CurrentDirectory.Path, directoryResponse.Files[num5]), directoryResponse.FileSizes[num5], (FileType)1, num6, array2));
|
|
}
|
|
ApplySort();
|
|
}
|
|
|
|
public void ApplyGetDrivesResponse(GetDrivesResponsePacket getDrivesPacket)
|
|
{
|
|
Drives = getDrivesPacket.Drives;
|
|
}
|
|
|
|
public void ApplyNotifyStatus(NotifyStatusResponsePacket statusPacket)
|
|
{
|
|
_mainVm.ClientsVM?.EnqueueStatus(statusPacket.StatusMessage);
|
|
}
|
|
|
|
private void Navigate(string path)
|
|
{
|
|
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0050: Expected O, but got Unknown
|
|
long num = _mainVm.ClientsVM.NextExplorerOpId();
|
|
_mainVm.ClientsVM.RegisterGetDirectoryCallback(Client.Owner, num, delegate(GetDirectoryResponsePacket p)
|
|
{
|
|
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
|
|
{
|
|
ApplyGetDirectoryResponse(p);
|
|
});
|
|
});
|
|
Client.Owner.SendPacket((IPacket)new GetDirectoryRequestPacket(path, num));
|
|
}
|
|
|
|
private void NavigateWithHistory(string path)
|
|
{
|
|
if (CurrentDirectory != null && path != CurrentDirectory.Path)
|
|
{
|
|
BackHistory.Push(CurrentDirectory);
|
|
}
|
|
Navigate(path);
|
|
}
|
|
|
|
private void NavigateSelected(string s)
|
|
{
|
|
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
|
if (SelectedFile != null && (int)SelectedFile.Type == 0)
|
|
{
|
|
NavigateWithHistory(SelectedFile.Path);
|
|
}
|
|
}
|
|
|
|
private void NavigateUp(string s)
|
|
{
|
|
NavigateWithHistory(Path.Combine(CurrentDirectory.Path, ".."));
|
|
}
|
|
|
|
private void NavigateForward(string s)
|
|
{
|
|
BackHistory.Push(CurrentDirectory);
|
|
FileSystemEntry val = ForwardHistory.Pop();
|
|
Navigate(val.Path);
|
|
}
|
|
|
|
private void NavigateBack(string s)
|
|
{
|
|
ForwardHistory.Push(CurrentDirectory);
|
|
FileSystemEntry val = BackHistory.Pop();
|
|
Navigate(val.Path);
|
|
}
|
|
|
|
private void DeleteFile(string s)
|
|
{
|
|
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0050: Expected O, but got Unknown
|
|
if (SelectedFile != null)
|
|
{
|
|
FileSystemEntry selectedFile = SelectedFile;
|
|
if (MessageBox.Show("Delete " + selectedFile.Name + "?", "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
|
{
|
|
Client.Owner.SendPacket((IPacket)new DeleteFileRequestPacket(selectedFile.Path));
|
|
_mainVm.ClientsVM?.EnqueueStatus("Delete sent for " + selectedFile.Name);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OpenSelected(string s)
|
|
{
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
|
if (SelectedFile != null && (int)SelectedFile.Type == 0)
|
|
{
|
|
NavigateWithHistory(SelectedFile.Path);
|
|
}
|
|
}
|
|
|
|
private void SaveAsSelected(string s)
|
|
{
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_010e: Expected O, but got Unknown
|
|
if (SelectedFile == null)
|
|
{
|
|
return;
|
|
}
|
|
if ((int)SelectedFile.Type == 0)
|
|
{
|
|
_mainVm.ClientsVM?.EnqueueStatus("Select a file to download.");
|
|
return;
|
|
}
|
|
SaveFileDialog saveFileDialog = new SaveFileDialog
|
|
{
|
|
FileName = SelectedFile.Name,
|
|
Filter = "All files|*.*",
|
|
DefaultExt = Path.GetExtension(SelectedFile.Name)
|
|
};
|
|
if (saveFileDialog.ShowDialog() != true)
|
|
{
|
|
return;
|
|
}
|
|
string fileName = saveFileDialog.FileName;
|
|
_pendingDownloadSavePath = fileName;
|
|
DownloadProgressVisible = true;
|
|
DownloadProgress = 0.0;
|
|
DownloadStatusText = "Downloading...";
|
|
_downloadStopwatch = Stopwatch.StartNew();
|
|
long num = _mainVm.ClientsVM.NextExplorerOpId();
|
|
_mainVm.ClientsVM.RegisterReadFileCallback(Client.Owner, num, delegate(ReadFileResponsePacket resp)
|
|
{
|
|
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
|
|
{
|
|
CompleteDownloadSave(resp);
|
|
});
|
|
});
|
|
Client.Owner.SendPacket((IPacket)new ReadFileRequestPacket(SelectedFile.Path, num));
|
|
}
|
|
|
|
private void CompleteDownloadSave(ReadFileResponsePacket resp)
|
|
{
|
|
string pendingDownloadSavePath = _pendingDownloadSavePath;
|
|
_pendingDownloadSavePath = null;
|
|
try
|
|
{
|
|
if (resp.Success && resp.Data != null)
|
|
{
|
|
File.WriteAllBytes(pendingDownloadSavePath, resp.Data);
|
|
TimeSpan timeSpan = _downloadStopwatch?.Elapsed ?? TimeSpan.Zero;
|
|
_mainVm.ClientsVM?.EnqueueStatus($"Saved to {pendingDownloadSavePath} ({resp.Data.Length / 1024} KB in {timeSpan.TotalSeconds:F1}s)");
|
|
}
|
|
else
|
|
{
|
|
_mainVm.ClientsVM?.EnqueueStatus("Download failed: " + (((resp != null) ? resp.ErrorMessage : null) ?? "Unknown error"));
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_mainVm.ClientsVM?.EnqueueStatus("Save failed: " + ex.Message);
|
|
}
|
|
DownloadProgressVisible = false;
|
|
DownloadStatusText = "";
|
|
}
|
|
|
|
private void UploadFile()
|
|
{
|
|
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0196: Expected O, but got Unknown
|
|
if (CurrentDirectory == null)
|
|
{
|
|
return;
|
|
}
|
|
OpenFileDialog openFileDialog = new OpenFileDialog
|
|
{
|
|
Filter = "All files|*.*"
|
|
};
|
|
if (openFileDialog.ShowDialog() != true)
|
|
{
|
|
return;
|
|
}
|
|
byte[] array;
|
|
try
|
|
{
|
|
array = File.ReadAllBytes(openFileDialog.FileName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_mainVm.ClientsVM?.EnqueueStatus("Upload read error: " + ex.Message);
|
|
return;
|
|
}
|
|
long num = (long)_mainVm.ClientsVM.Store.Settings.MaxSendFileSizeMB * 1024L * 1024;
|
|
if (num > 0 && array.Length > num)
|
|
{
|
|
_mainVm.ClientsVM?.EnqueueStatus("File too large (limit " + _mainVm.ClientsVM.Store.Settings.MaxSendFileSizeMB + " MB)");
|
|
return;
|
|
}
|
|
string name = Path.GetFileName(openFileDialog.FileName);
|
|
string destPath = Path.Combine(CurrentDirectory.Path, name);
|
|
long transferId = _mainVm.ClientsVM.NextExplorerOpId();
|
|
DownloadProgressVisible = true;
|
|
DownloadStatusText = "Uploading...";
|
|
_mainVm.ClientsVM.RegisterWriteFileCallback(Client.Owner, transferId, delegate(WriteFileResponsePacket resp)
|
|
{
|
|
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
|
|
{
|
|
DownloadProgressVisible = false;
|
|
DownloadStatusText = "";
|
|
if (resp.Success)
|
|
{
|
|
_mainVm.ClientsVM?.EnqueueStatus("Uploaded " + name);
|
|
Navigate(CurrentDirectory.Path);
|
|
}
|
|
else
|
|
{
|
|
_mainVm.ClientsVM?.EnqueueStatus("Upload failed: " + (resp.ErrorMessage ?? "?"));
|
|
}
|
|
});
|
|
});
|
|
Client.Owner.SendPacket((IPacket)new WriteFileRequestPacket
|
|
{
|
|
DestPath = destPath,
|
|
TransferId = transferId,
|
|
Data = array
|
|
});
|
|
}
|
|
|
|
private void ShowProperties(string s)
|
|
{
|
|
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
|
|
if (SelectedFile != null)
|
|
{
|
|
FileSystemEntry selectedFile = SelectedFile;
|
|
string value = (((int)selectedFile.Type == 0) ? "—" : FormatFileSize(selectedFile.Size));
|
|
string value2 = ((selectedFile.LastWriteUtcTicks > 0) ? new DateTime(selectedFile.LastWriteUtcTicks, DateTimeKind.Utc).ToLocalTime().ToString("yyyy-MM-dd HH:mm") : "—");
|
|
MessageBox.Show($"Name: {selectedFile.Name}\nPath: {selectedFile.Path}\nType: {selectedFile.Type}\nSize: {value}\nModified: {value2}", "Properties", MessageBoxButton.OK, MessageBoxImage.Asterisk);
|
|
}
|
|
}
|
|
|
|
private static string FormatFileSize(long bytes)
|
|
{
|
|
if (bytes < 1024)
|
|
{
|
|
return bytes + " B";
|
|
}
|
|
if (bytes < 1048576)
|
|
{
|
|
return ((double)bytes / 1024.0).ToString("F1") + " KB";
|
|
}
|
|
if (bytes < 1073741824)
|
|
{
|
|
return ((double)bytes / 1048576.0).ToString("F1") + " MB";
|
|
}
|
|
return ((double)bytes / 1073741824.0).ToString("F1") + " GB";
|
|
}
|
|
}
|