Add auto refresh feature (#12)
* Update ReactiveUI * Autorefresh feature * Borders, structural equality * Update gui on uwp * Update Avalonia pic * Disable buttons while refreshing * Mention ReactiveUI * Fix spacing issues on uwp * Fix IsCurrentPathEmpty skipping signals
This commit is contained in:
Родитель
9a28d291c5
Коммит
e04bdf6b2a
|
@ -328,3 +328,6 @@ ASALocalRun/
|
|||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Fody files
|
||||
*.xsd
|
|
@ -9,6 +9,7 @@
|
|||
<PackageReference Include="Avalonia" Version="0.7.0" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.7.0" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.7.0" />
|
||||
<PackageReference Include="Splat.NLog" Version="1.0.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -4,9 +4,9 @@ using Camelotia.Presentation.Avalonia.Services;
|
|||
using Camelotia.Presentation.Interfaces;
|
||||
using Camelotia.Presentation.ViewModels;
|
||||
using Camelotia.Services.Providers;
|
||||
using Camelotia.Services.Storages;
|
||||
using ReactiveUI;
|
||||
using Avalonia;
|
||||
using Camelotia.Services.Storages;
|
||||
|
||||
namespace Camelotia.Presentation.Avalonia
|
||||
{
|
||||
|
|
|
@ -5,23 +5,24 @@
|
|||
xmlns:models="clr-namespace:Camelotia.Services.Models;assembly=Camelotia.Services"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:views="clr-namespace:Camelotia.Presentation.Avalonia.Views"
|
||||
mc:Ignorable="d" Background="#ffffff">
|
||||
mc:Ignorable="d" Background="#f7f7f7">
|
||||
<Grid>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="42" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="4*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0"
|
||||
Command="{Binding Back}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Classes="Rounded"
|
||||
Content="Back" />
|
||||
<TextBlock Grid.Column="1"
|
||||
|
@ -31,108 +32,134 @@
|
|||
Margin="15 0" />
|
||||
<Button Grid.Column="2"
|
||||
Command="{Binding Open}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Classes="Rounded"
|
||||
Content="Open" />
|
||||
<Button Grid.Column="3"
|
||||
Command="{Binding Refresh}"
|
||||
Classes="Rounded"
|
||||
Content="Refresh" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="1">
|
||||
<ListBox Padding="0"
|
||||
Foreground="#000000"
|
||||
SelectionMode="Toggle"
|
||||
Items="{Binding Files}"
|
||||
BorderBrush="Transparent"
|
||||
IsVisible="{Binding IsReady}"
|
||||
SelectedItem="{Binding SelectedFile, Mode=TwoWay}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="models:FileModel">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Margin="8" Grid.Column="0">
|
||||
<TextBlock Text="{Binding Name}"
|
||||
TextWrapping="Wrap"
|
||||
FontSize="14" />
|
||||
<TextBlock Text="Directory"
|
||||
IsVisible="{Binding IsFolder}"
|
||||
Foreground="#777777"
|
||||
FontSize="12" />
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="#999999"
|
||||
Text="{Binding Size}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<Grid IsVisible="{Binding HasErrors}" Background="#ffffff">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Ellipse Width="10" Height="10"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="#ff0000"
|
||||
Margin="10" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Text="Can't perform the operation, an error has occured."
|
||||
Foreground="#000000" />
|
||||
</StackPanel>
|
||||
<Border Grid.Row="1" BorderBrush="#f2f2f2" BorderThickness="0 2 0 2">
|
||||
<Grid>
|
||||
<ListBox Padding="0"
|
||||
BorderThickness="0"
|
||||
Background="Transparent"
|
||||
SelectionMode="Toggle"
|
||||
Items="{Binding Files}"
|
||||
IsVisible="{Binding IsReady}"
|
||||
SelectedItem="{Binding SelectedFile, Mode=TwoWay}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="models:FileModel">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Margin="8" Grid.Column="0">
|
||||
<TextBlock Text="{Binding Name}"
|
||||
TextWrapping="Wrap"
|
||||
FontSize="14" />
|
||||
<TextBlock Text="Directory"
|
||||
IsVisible="{Binding IsFolder}"
|
||||
Foreground="#777777"
|
||||
FontSize="12" />
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="#999999"
|
||||
Text="{Binding Size}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<Grid IsVisible="{Binding HasErrors}" Background="#f7f7f7">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Ellipse Width="10" Height="10"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="#ff0000"
|
||||
Margin="10" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Text="Can't perform the operation, an error has occured."
|
||||
Foreground="#000000" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid IsVisible="{Binding IsCurrentPathEmpty}" Background="#f7f7f7">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Ellipse Width="10" Height="10"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="#ff0000"
|
||||
Margin="10" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Text="Whoops, no files here!"
|
||||
Foreground="#000000" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid IsVisible="{Binding IsLoading}" Background="#f7f7f7">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<ProgressBar HorizontalAlignment="Stretch"
|
||||
IsIndeterminate="{Binding IsLoading}" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Text="Please, wait..."
|
||||
Foreground="#000000" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid IsVisible="{Binding IsCurrentPathEmpty}" Background="#ffffff">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<Ellipse Width="10" Height="10"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="#ff0000"
|
||||
Margin="10" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Text="Whoops, no files here!"
|
||||
Foreground="#000000" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid IsVisible="{Binding IsLoading}" Background="#ffffff">
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<ProgressBar HorizontalAlignment="Stretch"
|
||||
IsIndeterminate="{Binding IsLoading}" />
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
Text="Please, wait..."
|
||||
Foreground="#000000" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0"
|
||||
Content="Logout"
|
||||
Classes="Rounded"
|
||||
IsVisible="{Binding CanLogout}"
|
||||
Command="{Binding Logout}" />
|
||||
<Button Grid.Column="1"
|
||||
Content="Delete"
|
||||
Classes="Rounded"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding DeleteSelectedFile}" />
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="10">
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal"
|
||||
Margin="5" VerticalAlignment="Center">
|
||||
<TextBlock Text="You selected: " Foreground="#aaaaaa" />
|
||||
<TextBlock Text="{Binding SelectedFile.Name}"
|
||||
Foreground="#888888" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="3"
|
||||
<Button Grid.Column="2"
|
||||
Content="Upload"
|
||||
Classes="Rounded"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding UploadToCurrentPath}" />
|
||||
<Button Grid.Column="4"
|
||||
<Button Grid.Column="3"
|
||||
Content="Download"
|
||||
Classes="Rounded"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding DownloadSelectedFile}" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0"
|
||||
Content="Logout"
|
||||
Classes="Rounded"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding Logout}" />
|
||||
<Button Grid.Column="1"
|
||||
Content="Unselect"
|
||||
Classes="Rounded"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding UnselectFile}" />
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal"
|
||||
Margin="5" VerticalAlignment="Center">
|
||||
<TextBlock Text="Refreshing in: " Foreground="#aaaaaa" />
|
||||
<TextBlock Text="{Binding RefreshingIn}"
|
||||
Foreground="#888888" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="3"
|
||||
Content="Refresh"
|
||||
Classes="Rounded"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding Refresh}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid IsVisible="{Binding Auth.IsAnonymous}">
|
||||
<views:AuthView DataContext="{Binding Auth}" />
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="5.5.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="ReactiveUI.Testing" Version="9.5.1" />
|
||||
<PackageReference Include="ReactiveUI.Testing" Version="9.8.23" />
|
||||
<PackageReference Include="NSubstitute" Version="3.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0" Margin="6"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
|
@ -33,16 +33,11 @@
|
|||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Margin="15 0" />
|
||||
<Button Grid.Column="2" Margin="6 6 0 6"
|
||||
<Button Grid.Column="2" Margin="6"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{x:Bind ViewModel.Open, Mode=OneWay}"
|
||||
Content="Open" />
|
||||
<Button Grid.Column="3" Margin="6"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{x:Bind ViewModel.Refresh, Mode=OneWay}"
|
||||
Content="Refresh" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="1">
|
||||
<ListBox BorderBrush="Transparent"
|
||||
|
@ -60,20 +55,33 @@
|
|||
<DataTemplate x:DataType="models:FileModel">
|
||||
<Grid Margin="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="24" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="📁"
|
||||
FontFamily="Segoe UI Symbol"
|
||||
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
|
||||
Visibility="{x:Bind IsFolder}"
|
||||
FontSize="14" />
|
||||
<TextBlock Grid.Column="0"
|
||||
Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Foreground="{ThemeResource AppBarSeparatorForegroundThemeBrush}"
|
||||
Visibility="{x:Bind IsFile}"
|
||||
FontSize="14" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{x:Bind Name, Mode=OneTime}"
|
||||
TextWrapping="Wrap"
|
||||
FontSize="14" />
|
||||
<TextBlock Grid.Column="1"
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="Directory"
|
||||
Visibility="{x:Bind IsFolder, Mode=OneTime}"
|
||||
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
|
||||
FontSize="12" />
|
||||
<TextBlock Grid.Column="2"
|
||||
<TextBlock Grid.Column="3"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
|
||||
Text="{x:Bind Size, Mode=OneTime}" />
|
||||
|
@ -115,37 +123,64 @@
|
|||
</Grid>
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="5*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0"
|
||||
Content="Logout" Margin="6 6 0 6"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
Visibility="{x:Bind ViewModel.CanLogout, Mode=OneWay}"
|
||||
Command="{x:Bind ViewModel.Logout, Mode=OneWay}" />
|
||||
<Button Grid.Column="1"
|
||||
Content="Delete" Margin="6 6 3 6"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="Delete" Margin="6 6 0 3"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
Command="{x:Bind ViewModel.DeleteSelectedFile, Mode=OneWay}" />
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="10">
|
||||
<StackPanel Grid.Column="1" 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="3"
|
||||
Content="Upload" Margin="6 6 0 6"
|
||||
<Button Grid.Column="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="Upload" Margin="6 6 0 3"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
Command="{x:Bind ViewModel.UploadToCurrentPath, Mode=OneWay}" />
|
||||
<Button Grid.Column="4"
|
||||
Content="Download" Margin="6"
|
||||
<Button Grid.Column="3"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="Download" Margin="6 6 6 3"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
Command="{x:Bind ViewModel.DownloadSelectedFile, Mode=OneWay}" />
|
||||
</Grid>
|
||||
<Grid Grid.Row="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="5*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="Logout" Margin="6 3 0 6"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
Command="{x:Bind ViewModel.Logout, Mode=OneWay}" />
|
||||
<Button Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Content="Unselect" Margin="6 3 0 6"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
Command="{x:Bind ViewModel.UnselectFile, Mode=OneWay}" />
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="10">
|
||||
<TextBlock Text="Refreshing in:"
|
||||
Margin="0 0 3 0" TextTrimming="CharacterEllipsis"
|
||||
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}" />
|
||||
<TextBlock Text="{x:Bind ViewModel.RefreshingIn, Mode=OneWay}"
|
||||
Foreground="{ThemeResource AppBarSeparatorForegroundThemeBrush}" />
|
||||
</StackPanel>
|
||||
<Button Grid.Column="3" Margin="6 3 6 6"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{x:Bind ViewModel.Refresh, Mode=OneWay}"
|
||||
Content="Refresh" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Visibility="{x:Bind ViewModel.Auth.IsAnonymous, Mode=OneWay}"
|
||||
Background="{ThemeResource SystemControlChromeLowAcrylicWindowBrush}">
|
||||
|
|
|
@ -54,9 +54,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="System.Reactive" Version="4.1.2" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2" />
|
||||
<PackageReference Include="ReactiveUI.AndroidSupport">
|
||||
<Version>9.5.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ReactiveUI.AndroidSupport" Version="9.8.23"/>
|
||||
<PackageReference Include="Xamarin.Forms" Version="3.4.0.1008975" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0" />
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReactiveUI.XamForms" Version="9.5.1" />
|
||||
<PackageReference Include="ReactiveUI.XamForms" Version="9.8.23" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="3.4.0.1008975" />
|
||||
<PackageReference Include="Xam.Plugin.Iconize" Version="3.4.0.103" />
|
||||
<PackageReference Include="Xam.Plugin.Iconize.FontAwesome" Version="3.4.0.103" />
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReactiveUI" Version="9.5.1" />
|
||||
<PackageReference Include="ReactiveUI.Fody" Version="9.5.1" />
|
||||
<PackageReference Include="ReactiveUI" Version="9.8.23" />
|
||||
<PackageReference Include="ReactiveUI.Fody" Version="9.8.23" />
|
||||
<PackageReference Include="DynamicData" Version="6.7.1.2534" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers>
|
||||
<ReactiveUI />
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<ReactiveUI />
|
||||
</Weavers>
|
|
@ -18,6 +18,8 @@ namespace Camelotia.Presentation.Interfaces
|
|||
ICommand UploadToCurrentPath { get; }
|
||||
|
||||
ICommand DeleteSelectedFile { get; }
|
||||
|
||||
ICommand UnselectFile { get; }
|
||||
|
||||
ICommand Refresh { get; }
|
||||
|
||||
|
@ -37,6 +39,8 @@ namespace Camelotia.Presentation.Interfaces
|
|||
|
||||
bool CanLogout { get; }
|
||||
|
||||
int RefreshingIn { get; }
|
||||
|
||||
string CurrentPath { get; }
|
||||
|
||||
string Description { get; }
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Camelotia.Presentation.Interfaces;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using Camelotia.Services.Models;
|
||||
|
@ -30,6 +30,7 @@ namespace Camelotia.Presentation.ViewModels
|
|||
private readonly ObservableAsPropertyHelper<bool> _isLoading;
|
||||
private readonly ObservableAsPropertyHelper<bool> _canLogout;
|
||||
private readonly ObservableAsPropertyHelper<bool> _isReady;
|
||||
private readonly ReactiveCommand<Unit, Unit> _unselectFile;
|
||||
private readonly ReactiveCommand<Unit, string> _back;
|
||||
private readonly ReactiveCommand<Unit, string> _open;
|
||||
private readonly ReactiveCommand<Unit, Unit> _logout;
|
||||
|
@ -53,6 +54,7 @@ namespace Camelotia.Presentation.ViewModels
|
|||
.ThenBy(file => file.Name)
|
||||
.ToList())
|
||||
.StartWithEmpty()
|
||||
.Where(files => Files == null || !files.SequenceEqual(Files))
|
||||
.ToProperty(this, x => x.Files, scheduler: currentThread);
|
||||
|
||||
_isLoading = _refresh
|
||||
|
@ -98,7 +100,7 @@ namespace Camelotia.Presentation.ViewModels
|
|||
|
||||
_isCurrentPathEmpty = this
|
||||
.WhenAnyValue(x => x.Files)
|
||||
.Skip(2)
|
||||
.Skip(1)
|
||||
.Where(files => files != null)
|
||||
.Select(files => !files.Any())
|
||||
.ToProperty(this, x => x.IsCurrentPathEmpty, scheduler: currentThread);
|
||||
|
@ -112,7 +114,7 @@ namespace Camelotia.Presentation.ViewModels
|
|||
var canUploadToCurrentPath = this
|
||||
.WhenAnyValue(x => x.CurrentPath)
|
||||
.Select(path => path != null)
|
||||
.DistinctUntilChanged();
|
||||
.CombineLatest(_refresh.IsExecuting, (up, loading) => up && !loading);
|
||||
|
||||
_uploadToCurrentPath = ReactiveCommand.CreateFromObservable(
|
||||
() => Observable
|
||||
|
@ -128,7 +130,7 @@ namespace Camelotia.Presentation.ViewModels
|
|||
var canDownloadSelectedFile = this
|
||||
.WhenAnyValue(x => x.SelectedFile)
|
||||
.Select(file => file != null && !file.IsFolder)
|
||||
.DistinctUntilChanged();
|
||||
.CombineLatest(_refresh.IsExecuting, (down, loading) => down && !loading);
|
||||
|
||||
_downloadSelectedFile = ReactiveCommand.CreateFromObservable(
|
||||
() => Observable
|
||||
|
@ -144,15 +146,6 @@ namespace Camelotia.Presentation.ViewModels
|
|||
.Merge(_downloadSelectedFile.ThrownExceptions)
|
||||
.Merge(_refresh.ThrownExceptions)
|
||||
.Subscribe(Console.WriteLine);
|
||||
|
||||
this.WhenAnyValue(x => x.SelectedFile)
|
||||
.Where(file => file != null && file.IsFolder)
|
||||
.Buffer(2, 1)
|
||||
.Select(files => (files.First().Path, files.Last().Path))
|
||||
.DistinctUntilChanged()
|
||||
.Where(x => x.Item1 == x.Item2)
|
||||
.Select(ignore => Unit.Default)
|
||||
.InvokeCommand(_open);
|
||||
|
||||
var isAuthEnabled = provider.SupportsDirectAuth || provider.SupportsOAuth;
|
||||
var canLogout = provider
|
||||
|
@ -167,13 +160,23 @@ namespace Camelotia.Presentation.ViewModels
|
|||
|
||||
var canDeleteSelection = this
|
||||
.WhenAnyValue(x => x.SelectedFile)
|
||||
.Select(file => file != null && !file.IsFolder);
|
||||
.Select(file => file != null && !file.IsFolder)
|
||||
.CombineLatest(_refresh.IsExecuting, (del, loading) => del && !loading);
|
||||
|
||||
_deleteSelectedFile = ReactiveCommand.CreateFromTask(
|
||||
() => provider.Delete(SelectedFile),
|
||||
canDeleteSelection);
|
||||
|
||||
_deleteSelectedFile.InvokeCommand(Refresh);
|
||||
|
||||
var canUnselectFile = this
|
||||
.WhenAnyValue(x => x.SelectedFile)
|
||||
.Select(selection => selection != null)
|
||||
.CombineLatest(_refresh.IsExecuting, (sel, loading) => sel && !loading);
|
||||
|
||||
_unselectFile = ReactiveCommand.Create(
|
||||
() => { SelectedFile = null; },
|
||||
canUnselectFile);
|
||||
|
||||
Auth = authViewModel;
|
||||
Activator = new ViewModelActivator();
|
||||
|
@ -184,6 +187,30 @@ namespace Camelotia.Presentation.ViewModels
|
|||
.Select(ignore => Unit.Default)
|
||||
.InvokeCommand(_refresh)
|
||||
.DisposeWith(disposable);
|
||||
|
||||
var interval = TimeSpan.FromSeconds(1);
|
||||
var tick = Observable
|
||||
.Timer(interval, interval)
|
||||
.Select(value => Unit.Default)
|
||||
.ObserveOn(mainThread);
|
||||
|
||||
tick.Select(unit => RefreshingIn - 1)
|
||||
.Where(value => value >= 0)
|
||||
.Subscribe(x => RefreshingIn = x)
|
||||
.DisposeWith(disposable);
|
||||
|
||||
this.WhenAnyValue(x => x.RefreshingIn)
|
||||
.Skip(1)
|
||||
.Where(refreshing => refreshing == 0)
|
||||
.Select(value => Unit.Default)
|
||||
.InvokeCommand(_refresh)
|
||||
.DisposeWith(disposable);
|
||||
|
||||
const int refreshPeriod = 30;
|
||||
_refresh.Select(results => refreshPeriod)
|
||||
.StartWith(refreshPeriod)
|
||||
.Subscribe(x => RefreshingIn = x)
|
||||
.DisposeWith(disposable);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -193,6 +220,8 @@ namespace Camelotia.Presentation.ViewModels
|
|||
|
||||
[Reactive] public FileModel SelectedFile { get; set; }
|
||||
|
||||
[Reactive] public int RefreshingIn { get; private set; }
|
||||
|
||||
public string CurrentPath => _currentPath?.Value ?? _provider.InitialPath;
|
||||
|
||||
public ICommand DownloadSelectedFile => _downloadSelectedFile;
|
||||
|
@ -203,10 +232,12 @@ namespace Camelotia.Presentation.ViewModels
|
|||
|
||||
public bool IsCurrentPathEmpty => _isCurrentPathEmpty.Value;
|
||||
|
||||
public IEnumerable<FileModel> Files => _files.Value;
|
||||
public IEnumerable<FileModel> Files => _files?.Value;
|
||||
|
||||
public string Description => _provider.Description;
|
||||
|
||||
public ICommand UnselectFile => _unselectFile;
|
||||
|
||||
public bool CanLogout => _canLogout.Value;
|
||||
|
||||
public bool IsLoading => _isLoading.Value;
|
||||
|
|
|
@ -2,6 +2,16 @@ namespace Camelotia.Services.Models
|
|||
{
|
||||
public sealed class FileModel
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public string Path { get; }
|
||||
|
||||
public bool IsFolder { get; }
|
||||
|
||||
public bool IsFile => !IsFolder;
|
||||
|
||||
public string Size { get; }
|
||||
|
||||
public FileModel(string name, string path, bool isFolder, string size)
|
||||
{
|
||||
Name = name;
|
||||
|
@ -9,13 +19,18 @@ namespace Camelotia.Services.Models
|
|||
IsFolder = isFolder;
|
||||
Size = size;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public string Path { get; }
|
||||
public override int GetHashCode() => (Name, Path, IsFolder, Size).GetHashCode();
|
||||
|
||||
public bool IsFolder { get; }
|
||||
|
||||
public string Size { get; }
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var file = obj as FileModel;
|
||||
return
|
||||
file != null &&
|
||||
file.Name == Name &&
|
||||
file.Path == Path &&
|
||||
file.IsFolder == IsFolder &&
|
||||
file.Size == Size;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
[![Build Status](https://worldbeater.visualstudio.com/Camelotia/_apis/build/status/Camelotia-CI)](https://worldbeater.visualstudio.com/Camelotia/_build/latest?definitionId=1) [![Pull Requests](https://img.shields.io/github/issues-pr/worldbeater/camelotia.svg)](https://github.com/worldbeater/Camelotia/pulls) [![Issues](https://img.shields.io/github/issues/worldbeater/camelotia.svg)](https://github.com/worldbeater/Camelotia/issues) ![License](https://img.shields.io/github/license/worldbeater/camelotia.svg) ![Size](https://img.shields.io/github/repo-size/worldbeater/camelotia.svg)
|
||||
|
||||
The app runs on Windows, Linux, MacOS, XBox, Surface Hub and HoloLens.
|
||||
The app runs on Windows, Linux, MacOS, XBox, Surface Hub and HoloLens. Built with [ReactiveUI](https://github.com/reactiveui/ReactiveUI).
|
||||
|
||||
## Compiling Avalonia app
|
||||
|
||||
|
|
Двоичные данные
UiAvalonia.png
Двоичные данные
UiAvalonia.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 92 KiB После Ширина: | Высота: | Размер: 95 KiB |
Двоичные данные
UiWindows.jpg
Двоичные данные
UiWindows.jpg
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 117 KiB После Ширина: | Высота: | Размер: 116 KiB |
Загрузка…
Ссылка в новой задаче