This commit is contained in:
Artjom Graf 2018-12-26 13:48:40 +03:00
Родитель af17f41c79
Коммит 51b57574e0
11 изменённых файлов: 90 добавлений и 34 удалений

Просмотреть файл

@ -104,6 +104,7 @@
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
@ -114,16 +115,20 @@
Classes="Rounded"
IsVisible="{Binding CanLogout}"
Command="{Binding Logout}" />
<StackPanel Grid.Column="1" Orientation="Horizontal" Margin="10">
<Button Grid.Column="1"
Content="Delete"
Classes="Rounded"
Command="{Binding DeleteSelectedFile}" />
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="10">
<TextBlock Text="You selected: " Foreground="#aaaaaa" />
<TextBlock Text="{Binding SelectedFile.Name}"
Foreground="#888888" />
</StackPanel>
<Button Grid.Column="2"
<Button Grid.Column="3"
Content="Upload"
Classes="Rounded"
Command="{Binding UploadToCurrentPath}" />
<Button Grid.Column="3"
<Button Grid.Column="4"
Content="Download"
Classes="Rounded"
Command="{Binding DownloadSelectedFile}" />

Просмотреть файл

@ -47,9 +47,7 @@ namespace Camelotia.Presentation.Tests
foreach (var model in real)
expected.Should().Contain(drive =>
model.Name == drive.Name &&
model.IsFolder == false &&
model.IsDrive);
model.Name == drive.Name && model.IsFolder);
}
[Fact]

Просмотреть файл

@ -95,7 +95,7 @@ namespace Camelotia.Presentation.Tests
[Fact]
public void ShouldBeAbleToOpenSelectedPath() => new TestScheduler().With(scheduler =>
{
var file = new FileModel("foo", Separator + "foo", true, false, string.Empty);
var file = new FileModel("foo", Separator + "foo", true, string.Empty);
_provider.Get(Separator).Returns(Enumerable.Repeat(file, 1));
_authViewModel.IsAuthenticated.Returns(true);
_provider.InitialPath.Returns(Separator);

Просмотреть файл

@ -115,6 +115,7 @@
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
@ -124,16 +125,19 @@
Style="{StaticResource ButtonRevealStyle}"
Visibility="{x:Bind ViewModel.CanLogout, Mode=OneWay}"
Command="{x:Bind ViewModel.Logout, Mode=OneWay}" />
<StackPanel Grid.Column="1" Orientation="Horizontal" Margin="10">
<Button Grid.Column="1" Content="Delete" Margin="0 0 3 0"
Style="{StaticResource ButtonRevealStyle}"
Command="{x:Bind ViewModel.DeleteSelectedFile, Mode=OneWay}" />
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="10">
<TextBlock Text="You selected:" Margin="0 0 3 0" TextTrimming="CharacterEllipsis"
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}" />
<TextBlock Text="{x:Bind ViewModel.SelectedFile.Name, Mode=OneWay}"
Foreground="{ThemeResource AppBarSeparatorForegroundThemeBrush}" />
</StackPanel>
<Button Grid.Column="2" Content="Upload" Margin="6 6 0 6"
<Button Grid.Column="3" Content="Upload" Margin="6 6 0 6"
Style="{StaticResource ButtonRevealStyle}"
Command="{x:Bind ViewModel.UploadToCurrentPath, Mode=OneWay}" />
<Button Grid.Column="3" Content="Download" Margin="6"
<Button Grid.Column="4" Content="Download" Margin="6"
Style="{StaticResource ButtonRevealStyle}"
Command="{x:Bind ViewModel.DownloadSelectedFile, Mode=OneWay}" />
</Grid>

Просмотреть файл

@ -16,7 +16,9 @@ namespace Camelotia.Presentation.Interfaces
ICommand DownloadSelectedFile { get; }
ICommand UploadToCurrentPath { get; }
ICommand DeleteSelectedFile { get; }
ICommand Refresh { get; }
ICommand Logout { get; }

Просмотреть файл

@ -24,6 +24,7 @@ namespace Camelotia.Presentation.ViewModels
private readonly ObservableAsPropertyHelper<bool> _isCurrentPathEmpty;
private readonly ReactiveCommand<Unit, Unit> _downloadSelectedFile;
private readonly ReactiveCommand<Unit, Unit> _uploadToCurrentPath;
private readonly ReactiveCommand<Unit, Unit> _deleteSelectedFile;
private readonly ObservableAsPropertyHelper<string> _currentPath;
private readonly ObservableAsPropertyHelper<bool> _hasErrors;
private readonly ObservableAsPropertyHelper<bool> _isLoading;
@ -66,7 +67,7 @@ namespace Camelotia.Presentation.ViewModels
var canOpenCurrentPath = this
.WhenAnyValue(x => x.SelectedFile)
.Select(file => file != null && (file.IsFolder || file.IsDrive))
.Select(file => file != null && file.IsFolder)
.CombineLatest(_refresh.IsExecuting, (folder, busy) => folder && !busy);
_open = ReactiveCommand.Create(
@ -123,7 +124,7 @@ namespace Camelotia.Presentation.ViewModels
var canDownloadSelectedFile = this
.WhenAnyValue(x => x.SelectedFile)
.Select(file => file != null && !file.IsFolder && !file.IsDrive)
.Select(file => file != null && !file.IsFolder)
.DistinctUntilChanged();
_downloadSelectedFile = ReactiveCommand.CreateFromObservable(
@ -141,7 +142,7 @@ namespace Camelotia.Presentation.ViewModels
.Subscribe(Console.WriteLine);
this.WhenAnyValue(x => x.SelectedFile)
.Where(file => file != null && (file.IsFolder || file.IsDrive))
.Where(file => file != null && file.IsFolder)
.Buffer(2, 1)
.Select(files => (files.First().Path, files.Last().Path))
.DistinctUntilChanged()
@ -159,6 +160,16 @@ namespace Camelotia.Presentation.ViewModels
_logout = ReactiveCommand.CreateFromTask(provider.Logout, canLogout);
_canLogout = canLogout
.ToProperty(this, x => x.CanLogout, scheduler: currentThread);
var canDeleteSelection = this
.WhenAnyValue(x => x.SelectedFile)
.Select(file => file != null && !file.IsFolder);
_deleteSelectedFile = ReactiveCommand.CreateFromTask(
() => provider.Delete(SelectedFile),
canDeleteSelection);
_deleteSelectedFile.InvokeCommand(Refresh);
Auth = authViewModel;
Activator = new ViewModelActivator();
@ -183,7 +194,9 @@ namespace Camelotia.Presentation.ViewModels
public ICommand DownloadSelectedFile => _downloadSelectedFile;
public ICommand UploadToCurrentPath => _uploadToCurrentPath;
public ICommand DeleteSelectedFile => _deleteSelectedFile;
public bool IsCurrentPathEmpty => _isCurrentPathEmpty.Value;
public IEnumerable<FileModel> Files => _files.Value;

Просмотреть файл

@ -22,6 +22,8 @@ namespace Camelotia.Services.Interfaces
Task DownloadFile(string from, Stream to);
Task Delete(FileModel file);
IObservable<bool> IsAuthorized { get; }
bool SupportsDirectAuth { get; }

Просмотреть файл

@ -2,12 +2,11 @@ namespace Camelotia.Services.Models
{
public sealed class FileModel
{
public FileModel(string name, string path, bool isFolder, bool isDrive, string size)
public FileModel(string name, string path, bool isFolder, string size)
{
Name = name;
Path = path;
IsFolder = isFolder;
IsDrive = isDrive;
Size = size;
}
@ -17,8 +16,6 @@ namespace Camelotia.Services.Models
public bool IsFolder { get; }
public bool IsDrive { get; }
public string Size { get; }
}
}

Просмотреть файл

@ -20,7 +20,7 @@ namespace Camelotia.Services.Providers
public IObservable<bool> IsAuthorized { get; } = Observable.Return(true);
public bool SupportsDirectAuth => false;
public bool SupportsOAuth => false;
public string InitialPath => string.Empty;
@ -38,19 +38,19 @@ namespace Camelotia.Services.Providers
var driveQuery = from entity in GetAllDrives()
where entity.IsReady
let size = ByteConverter.BytesToString(entity.AvailableFreeSpace)
select new FileModel(entity.Name, entity.Name, false, true, size);
select new FileModel(entity.Name, entity.Name, true, size);
return driveQuery
.ToList()
.AsEnumerable();
}
if (!Directory.Exists(path))
throw new ArgumentException("Directory doesn't exist.");
var query = from entity in Directory.GetFileSystemEntries(path)
let isDirectory = IsDirectory(entity)
let size = isDirectory ? "*" : ByteConverter.BytesToString(new FileInfo(entity).Length)
select new FileModel(Path.GetFileName(entity), entity, isDirectory, false, size);
var query = from entity in Directory.GetFileSystemEntries(path)
let isDirectory = IsDirectory(entity)
let size = isDirectory ? "*" : ByteConverter.BytesToString(new FileInfo(entity).Length)
select new FileModel(Path.GetFileName(entity), entity, isDirectory, size);
return query
.ToList()
@ -60,7 +60,7 @@ namespace Camelotia.Services.Providers
public async Task DownloadFile(string from, Stream to)
{
if (IsDirectory(from)) throw new InvalidOperationException("Can't download directory.");
using (var fileStream = File.OpenRead(from))
{
fileStream.Seek(0, SeekOrigin.Begin);
@ -71,7 +71,7 @@ namespace Camelotia.Services.Providers
public async Task UploadFile(string to, Stream from, string name)
{
if (!IsDirectory(to)) throw new InvalidOperationException("Can't upload to a non-directory.");
var path = Path.Combine(to, name);
using (var fileStream = File.Create(path))
{
@ -80,6 +80,13 @@ namespace Camelotia.Services.Providers
}
}
public Task Delete(FileModel file) => Task.Run(() =>
{
var isDirectory = IsDirectory(file.Path);
if (isDirectory) Directory.Delete(file.Path, false);
else File.Delete(file.Path);
});
private static string GetSizeOnAllDisks()
{
var totalBytes = GetAllDrives()

Просмотреть файл

@ -14,6 +14,7 @@ using VkNet.Enums.Filters;
using VkNet.Model;
using VkNet;
using VkNet.Abstractions;
using VkNet.Model.Attachments;
namespace Camelotia.Services.Providers
{
@ -78,19 +79,31 @@ namespace Camelotia.Services.Providers
var size = string.Empty;
if (document.Size.HasValue)
size = ByteConverter.BytesToString(document.Size.Value);
return new FileModel(document.Title, document.Uri, false, false, size);
return new FileModel(document.Title, document.Id.ToString(), false, size);
});
}
public async Task DownloadFile(string from, Stream to)
{
var isValidUriString = Uri.IsWellFormedUriString(from, UriKind.Absolute);
var id = long.Parse(from);
var users = await _api.Users.GetAsync(new long[0]);
var currentUser = users.First();
var documents = await _api.Docs.GetByIdAsync(new[] {new Document {Id = id, OwnerId = currentUser.Id}});
var document = documents.First();
Console.WriteLine (document.Uri);
var uri = document.Uri;
var isValidUriString = Uri.IsWellFormedUriString(uri, UriKind.Absolute);
if (!isValidUriString) throw new InvalidOperationException("Uri is invalid.");
using (var http = new HttpClient())
using (var response = await http.GetAsync(from).ConfigureAwait(false))
using (var response = await http.GetAsync(uri).ConfigureAwait(false))
using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
await stream.CopyToAsync(to).ConfigureAwait(false);
await to.FlushAsync();
to.Close();
}
public async Task UploadFile(string to, Stream from, string name)
@ -111,7 +124,15 @@ namespace Camelotia.Services.Providers
var error = $"Unable to upload {name}{ext} \n{message}";
throw new Exception(error);
}
}
}
public async Task Delete(FileModel file)
{
var id = long.Parse(file.Path);
var users = await _api.Users.GetAsync(new long[0]);
var currentUser = users.First();
await _api.Docs.DeleteAsync(currentUser.Id, id);
}
private async void EnsureLoggedInIfTokenSaved()

Просмотреть файл

@ -69,7 +69,6 @@ namespace Camelotia.Services.Providers
file.Name,
file.Path.Replace("disk:", ""),
file.Type == "dir",
false,
ByteConverter.BytesToString(file.Size)));
return models;
@ -113,6 +112,14 @@ namespace Camelotia.Services.Providers
}
}
public async Task Delete(FileModel file)
{
var encodedPath = WebUtility.UrlEncode(file.Path);
var pathUrl = CloudApiGetPathBase + encodedPath;
using (var response = await _http.DeleteAsync(pathUrl).ConfigureAwait(false))
response.EnsureSuccessStatusCode();
}
public async Task Logout()
{
await _tokenStorage.WriteToken<YandexFileSystemProvider>(null);