Upgrade packages, refactor solution structure (#26)
* Upgrade most packages to latest versions * Move solution files to /src * Use .NET Core 2.2 SDK (MSBuild 16 included) * Use separate sln file for each framework
|
@ -1,14 +0,0 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Camelotia.Presentation.Avalonia
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
base.Initialize();
|
||||
}
|
||||
}
|
||||
}
|
12
README.md
|
@ -1,4 +1,4 @@
|
|||
<p align="left"><img src="assets/horizontal.png" alt="Camelotia" height="80px"></p>
|
||||
<p align="left"><img src="images/horizontal.png" alt="Camelotia" height="80px"></p>
|
||||
|
||||
[![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) [![Code Coverage](https://img.shields.io/azure-devops/coverage/worldbeater/Camelotia/1.svg)](https://worldbeater.visualstudio.com/Camelotia/_build/latest?definitionId=1)
|
||||
|
||||
|
@ -8,12 +8,12 @@ File manager for cloud storages. Supports Yandex Disk, Google Drive, VK Document
|
|||
|
||||
You can compile .NET Standard libraries, run tests and run an Avalonia application on Windows, Linux and macOS operating systems. Make sure you have latest [.NET Core SDK](https://dot.net/) installed.
|
||||
|
||||
<img src="assets/UiAvalonia.png" width="550">
|
||||
<img src="images/UiAvalonia.png" width="550">
|
||||
|
||||
```sh
|
||||
# Linux or MacOS shell
|
||||
git clone https://github.com/worldbeater/Camelotia
|
||||
cd Camelotia/Camelotia.Presentation.Avalonia
|
||||
cd src/Camelotia/Camelotia.Presentation.Avalonia
|
||||
dotnet run
|
||||
```
|
||||
|
||||
|
@ -23,7 +23,7 @@ On Windows, double-click the `./run.bat` file.
|
|||
|
||||
You can compile Universal Windows Platform Camelotia app only on latest Windows 10. Make sure you have latest [Microsoft Visual Studio](https://visualstudio.microsoft.com/) installed. Make sure the "Universal Application Development" section is checked in [Visual Studio Installer](https://visualstudio.microsoft.com/ru/vs/).
|
||||
|
||||
<img src="assets/UiWindows1.png" width="600">
|
||||
<img src="images/UiWindows1.png" width="600">
|
||||
|
||||
Supports light and dark themes!
|
||||
|
||||
|
@ -31,11 +31,11 @@ Supports light and dark themes!
|
|||
|
||||
To compile the Xamarin Forms Android application, you need to install appropriate Android SDK v8.1. This can be achieved by using [Visual Studio Installer](https://visualstudio.microsoft.com/ru/vs/) and selecting "Mobile Development" section there.
|
||||
|
||||
<img src="assets/UiAndroid1.png" width="220"> <img src="assets/UiAndroid2.png" width="220"> <img src="assets/UiAndroid3.png" width="220">
|
||||
<img src="images/UiAndroid1.png" width="220"> <img src="images/UiAndroid2.png" width="220"> <img src="images/UiAndroid3.png" width="220">
|
||||
|
||||
### Adding Custom Providers
|
||||
|
||||
File system providers are located at `./Camelotia.Services/Providers/`. To add a custom file system provider, you need to create a separate class and implement the [IProvider](https://github.com/worldbeater/Camelotia/blob/master/Camelotia.Services/Interfaces/IProvider.cs) interface. Then, add your provider to composition root for each platform that should support it.
|
||||
File system providers are located at `./src/Camelotia.Services/Providers/`. To add a custom file system provider, you need to create a separate class and implement the [IProvider](https://github.com/worldbeater/Camelotia/blob/master/Camelotia.Services/Interfaces/IProvider.cs) interface. Then, add your provider to composition root for each platform that should support it.
|
||||
|
||||
### Technologies and Tools Used
|
||||
|
||||
|
|
|
@ -5,9 +5,12 @@ jobs:
|
|||
variables:
|
||||
buildConfiguration: 'Release'
|
||||
steps:
|
||||
- script: dotnet build --configuration $(buildConfiguration) $(Build.SourcesDirectory)/Camelotia.Presentation.Avalonia/Camelotia.Presentation.Avalonia.csproj
|
||||
- task: DotNetCoreInstaller@0
|
||||
inputs:
|
||||
version: '2.2.203'
|
||||
- script: dotnet build --configuration $(buildConfiguration) $(Build.SourcesDirectory)/src/Camelotia.Presentation.Avalonia/Camelotia.Presentation.Avalonia.csproj
|
||||
displayName: 'Linux Build'
|
||||
- script: dotnet test --logger trx Camelotia.Presentation.Tests
|
||||
- script: dotnet test --logger trx src/Camelotia.Presentation.Tests
|
||||
displayName: 'Linux Unit Tests'
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
|
@ -16,16 +19,19 @@ jobs:
|
|||
|
||||
- job: Windows
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
buildConfiguration: 'Release'
|
||||
steps:
|
||||
- script: dotnet build --configuration $(buildConfiguration) $(Build.SourcesDirectory)/Camelotia.Presentation.Avalonia/Camelotia.Presentation.Avalonia.csproj
|
||||
- task: DotNetCoreInstaller@0
|
||||
inputs:
|
||||
version: '2.2.203'
|
||||
- script: dotnet build --configuration $(buildConfiguration) $(Build.SourcesDirectory)/src/Camelotia.Presentation.Avalonia/Camelotia.Presentation.Avalonia.csproj
|
||||
displayName: 'Windows Build'
|
||||
- script: |
|
||||
mkdir $(Build.SourcesDirectory)\results
|
||||
dotnet test --logger trx /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:Exclude=[xunit.*]* Camelotia.Presentation.Tests
|
||||
copy $(Build.SourcesDirectory)\Camelotia.Presentation.Tests\coverage.cobertura.xml $(Build.SourcesDirectory)\results
|
||||
dotnet test --logger trx /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:Exclude=[xunit.*]* src/Camelotia.Presentation.Tests
|
||||
copy $(Build.SourcesDirectory)\src\Camelotia.Presentation.Tests\coverage.cobertura.xml $(Build.SourcesDirectory)\results
|
||||
dotnet tool install dotnet-reportgenerator-globaltool --tool-path . --version 4.0.0-rc4
|
||||
reportgenerator "-reports:$(Build.SourcesDirectory)\results\coverage.cobertura.xml" "-targetdir:results" "-reporttypes:HTMLInline;HTMLChart"
|
||||
displayName: 'Windows Unit Tests'
|
||||
|
|
До Ширина: | Высота: | Размер: 130 KiB После Ширина: | Высота: | Размер: 130 KiB |
До Ширина: | Высота: | Размер: 120 KiB После Ширина: | Высота: | Размер: 120 KiB |
До Ширина: | Высота: | Размер: 145 KiB После Ширина: | Высота: | Размер: 145 KiB |
До Ширина: | Высота: | Размер: 140 KiB После Ширина: | Высота: | Размер: 140 KiB |
До Ширина: | Высота: | Размер: 608 KiB После Ширина: | Высота: | Размер: 608 KiB |
До Ширина: | Высота: | Размер: 12 KiB После Ширина: | Высота: | Размер: 12 KiB |
До Ширина: | Высота: | Размер: 3.7 KiB После Ширина: | Высота: | Размер: 3.7 KiB |
До Ширина: | Высота: | Размер: 9.0 KiB После Ширина: | Высота: | Размер: 9.0 KiB |
2
run.bat
|
@ -1,6 +1,6 @@
|
|||
@echo off
|
||||
echo Starting app...
|
||||
cd Camelotia.Presentation.Avalonia
|
||||
cd src\Camelotia.Presentation.Avalonia
|
||||
dotnet clean
|
||||
dotnet restore
|
||||
dotnet build
|
||||
|
|
2
run.sh
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
cd Camelotia.Presentation.Avalonia
|
||||
cd src/Camelotia.Presentation.Avalonia
|
||||
dotnet run
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.168
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Camelotia.Services", "Camelotia.Services\Camelotia.Services.csproj", "{283B8F56-AB9F-4556-AB93-AAC54171841C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Camelotia.Presentation", "Camelotia.Presentation\Camelotia.Presentation.csproj", "{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Camelotia.Presentation.Avalonia", "Camelotia.Presentation.Avalonia\Camelotia.Presentation.Avalonia.csproj", "{557CB17D-8989-48E5-82FD-3C2106EE4BAE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Camelotia.Presentation.Tests", "Camelotia.Presentation.Tests\Camelotia.Presentation.Tests.csproj", "{AE41666B-41D1-4044-9752-7CD4460C1A90}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{283B8F56-AB9F-4556-AB93-AAC54171841C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{777FBFA6-ECFA-42F5-AC5F-EFC4B2D4AE6B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{557CB17D-8989-48E5-82FD-3C2106EE4BAE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AE41666B-41D1-4044-9752-7CD4460C1A90}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0CB49554-419C-45F0-B5EB-B36357AF2018}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -17,5 +17,11 @@
|
|||
<Setter Property="Padding" Value="7"/>
|
||||
<Setter Property="Margin" Value="5"/>
|
||||
</Style>
|
||||
<Style Selector="Button.Rounded:pointerover">
|
||||
<Setter Property="Background" Value="#002979"/>
|
||||
</Style>
|
||||
<Style Selector="Button.Rounded:pressed">
|
||||
<Setter Property="Background" Value="#001261"/>
|
||||
</Style>
|
||||
</Application.Styles>
|
||||
</Application>
|
|
@ -1,69 +1,71 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Concurrency;
|
||||
using Camelotia.Presentation.Avalonia.Views;
|
||||
using Camelotia.Presentation.Avalonia.Services;
|
||||
using Camelotia.Presentation.Interfaces;
|
||||
using Camelotia.Presentation.ViewModels;
|
||||
using Camelotia.Services.Providers;
|
||||
using Camelotia.Services.Storages;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using Camelotia.Services.Models;
|
||||
using ReactiveUI;
|
||||
using Avalonia;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Camelotia.Presentation.Avalonia
|
||||
{
|
||||
public sealed class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
AppBuilder
|
||||
.Configure<App>()
|
||||
.UseReactiveUI()
|
||||
.UsePlatformDetect()
|
||||
.Start<MainView>(BuildMainViewModel);
|
||||
}
|
||||
|
||||
private static IMainViewModel BuildMainViewModel()
|
||||
{
|
||||
var current = CurrentThreadScheduler.Instance;
|
||||
var main = RxApp.MainThreadScheduler;
|
||||
|
||||
Akavache.BlobCache.ApplicationName = "Camelotia";
|
||||
var cache = Akavache.BlobCache.UserAccount;
|
||||
var login = new AvaloniaYandexAuthenticator();
|
||||
var files = new AvaloniaFileManager();
|
||||
|
||||
return new MainViewModel(
|
||||
(provider, auth) => new ProviderViewModel(
|
||||
model => new CreateFolderViewModel(model, provider, current, main),
|
||||
model => new RenameFileViewModel(model, provider, current, main),
|
||||
(file, model) => new FileViewModel(model, file),
|
||||
auth, files, provider, current, main
|
||||
),
|
||||
provider => new AuthViewModel(
|
||||
new DirectAuthViewModel(provider, current, main),
|
||||
new HostAuthViewModel(provider, current, main),
|
||||
new OAuthViewModel(provider, current, main),
|
||||
provider, current, main
|
||||
),
|
||||
new ProviderStorage(
|
||||
new Dictionary<string, Func<ProviderModel, IProvider>>
|
||||
{
|
||||
["Local File System"] = id => new LocalProvider(id),
|
||||
["Vkontakte Docs"] = id => new VkDocsProvider(id, cache),
|
||||
["Yandex Disk"] = id => new YandexDiskProvider(id, login, cache),
|
||||
["FTP"] = id => new FtpProvider(id),
|
||||
["SFTP"] = id => new SftpProvider(id),
|
||||
["GitHub"] = id => new GitHubProvider(id, cache),
|
||||
["Google Drive"] = id => new GoogleDriveProvider(id, cache)
|
||||
},
|
||||
cache
|
||||
),
|
||||
current, main
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
using Avalonia;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Camelotia.Presentation.Avalonia.Services;
|
||||
using Camelotia.Presentation.Avalonia.Views;
|
||||
using Camelotia.Presentation.ViewModels;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using Camelotia.Services.Models;
|
||||
using Camelotia.Services.Providers;
|
||||
using Camelotia.Services.Storages;
|
||||
using ReactiveUI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Concurrency;
|
||||
|
||||
namespace Camelotia.Presentation.Avalonia
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
var current = CurrentThreadScheduler.Instance;
|
||||
var main = RxApp.MainThreadScheduler;
|
||||
|
||||
Akavache.BlobCache.ApplicationName = "Camelotia";
|
||||
var cache = Akavache.BlobCache.UserAccount;
|
||||
|
||||
var window = new MainView();
|
||||
var login = new AvaloniaYandexAuthenticator();
|
||||
var files = new AvaloniaFileManager(window);
|
||||
|
||||
var context = new MainViewModel(
|
||||
(provider, auth) => new ProviderViewModel(
|
||||
model => new CreateFolderViewModel(model, provider, current, main),
|
||||
model => new RenameFileViewModel(model, provider, current, main),
|
||||
(file, model) => new FileViewModel(model, file),
|
||||
auth, files, provider, current, main
|
||||
),
|
||||
provider => new AuthViewModel(
|
||||
new DirectAuthViewModel(provider, current, main),
|
||||
new HostAuthViewModel(provider, current, main),
|
||||
new OAuthViewModel(provider, current, main),
|
||||
provider, current, main
|
||||
),
|
||||
new ProviderStorage(
|
||||
new Dictionary<string, Func<ProviderModel, IProvider>>
|
||||
{
|
||||
["Local File System"] = id => new LocalProvider(id),
|
||||
["Vkontakte Docs"] = id => new VkDocsProvider(id, cache),
|
||||
["Yandex Disk"] = id => new YandexDiskProvider(id, login, cache),
|
||||
["FTP"] = id => new FtpProvider(id),
|
||||
["SFTP"] = id => new SftpProvider(id),
|
||||
["GitHub"] = id => new GitHubProvider(id, cache),
|
||||
["Google Drive"] = id => new GoogleDriveProvider(id, cache)
|
||||
},
|
||||
cache
|
||||
),
|
||||
current, main
|
||||
);
|
||||
|
||||
window.DataContext = context;
|
||||
window.Show();
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +1,27 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.8.1-cibuild0002371-beta" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.8.1-cibuild0002371-beta" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.8.1-cibuild0002371-beta" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Camelotia.Presentation\Camelotia.Presentation.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="**\*.xaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="**\*.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.8.999-cibuild0003269-beta" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.8.999-cibuild0003269-beta" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.8.999-cibuild0003269-beta" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Camelotia.Presentation\Camelotia.Presentation.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="**\*.xaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="**\*.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,17 @@
|
|||
using Avalonia;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Logging.Serilog;
|
||||
|
||||
namespace Camelotia.Presentation.Avalonia
|
||||
{
|
||||
public sealed class Program
|
||||
{
|
||||
public static void Main(string[] args) => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UseReactiveUI()
|
||||
.UsePlatformDetect()
|
||||
.LogToDebug();
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Camelotia.Services.Interfaces;
|
||||
|
||||
|
@ -10,10 +9,14 @@ namespace Camelotia.Presentation.Avalonia.Services
|
|||
{
|
||||
public sealed class AvaloniaFileManager : IFileManager
|
||||
{
|
||||
private readonly Window _window;
|
||||
|
||||
public AvaloniaFileManager(Window window) => _window = window;
|
||||
|
||||
public async Task<Stream> OpenWrite(string name)
|
||||
{
|
||||
var fileDialog = new OpenFolderDialog();
|
||||
var folder = await fileDialog.ShowAsync(Application.Current.MainWindow);
|
||||
var folder = await fileDialog.ShowAsync(_window);
|
||||
var path = Path.Combine(folder, name);
|
||||
return File.Create(path);
|
||||
}
|
||||
|
@ -21,7 +24,7 @@ namespace Camelotia.Presentation.Avalonia.Services
|
|||
public async Task<(string Name, Stream Stream)> OpenRead()
|
||||
{
|
||||
var fileDialog = new OpenFileDialog {AllowMultiple = false};
|
||||
var files = await fileDialog.ShowAsync(Application.Current.MainWindow);
|
||||
var files = await fileDialog.ShowAsync(_window);
|
||||
var path = files.First();
|
||||
|
||||
var attributes = File.GetAttributes(path);
|
|
@ -1,62 +1,62 @@
|
|||
using System.Reactive.Concurrency;
|
||||
using System.Reactive.Subjects;
|
||||
using Camelotia.Presentation.Interfaces;
|
||||
using Camelotia.Presentation.ViewModels;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Reactive.Testing;
|
||||
using NSubstitute;
|
||||
using ReactiveUI.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Camelotia.Presentation.Tests
|
||||
{
|
||||
public sealed class AuthViewModelTests
|
||||
{
|
||||
private readonly IDirectAuthViewModel _directAuthViewModel = Substitute.For<IDirectAuthViewModel>();
|
||||
private readonly IHostAuthViewModel _hostAuthViewModel = Substitute.For<IHostAuthViewModel>();
|
||||
private readonly IOAuthViewModel _oAuthViewModel = Substitute.For<IOAuthViewModel>();
|
||||
private readonly IProvider _provider = Substitute.For<IProvider>();
|
||||
|
||||
[Fact]
|
||||
public void IsAuthenticatedPropertyShouldDependOnFileProvider() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
var authorized = new Subject<bool>();
|
||||
_provider.IsAuthorized.Returns(authorized);
|
||||
var model = BuildAuthViewModel(scheduler);
|
||||
|
||||
model.IsAuthenticated.Should().BeFalse();
|
||||
authorized.OnNext(true);
|
||||
|
||||
scheduler.AdvanceBy(2);
|
||||
model.IsAuthenticated.Should().BeTrue();
|
||||
});
|
||||
|
||||
[Fact]
|
||||
public void SupportsPropsShouldDependOnProvider() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
var model = BuildAuthViewModel(scheduler);
|
||||
model.SupportsDirectAuth.Should().BeFalse();
|
||||
model.SupportsOAuth.Should().BeFalse();
|
||||
|
||||
_provider.SupportsDirectAuth.Returns(true);
|
||||
_provider.SupportsOAuth.Returns(true);
|
||||
|
||||
model.SupportsDirectAuth.Should().BeTrue();
|
||||
model.SupportsOAuth.Should().BeTrue();
|
||||
});
|
||||
|
||||
[Fact]
|
||||
public void ShouldReturnInjectedAuthViewModelTypes() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
var model = BuildAuthViewModel(scheduler);
|
||||
model.DirectAuth.Should().Be(_directAuthViewModel);
|
||||
model.OAuth.Should().Be(_oAuthViewModel);
|
||||
});
|
||||
|
||||
private AuthViewModel BuildAuthViewModel(IScheduler scheduler)
|
||||
{
|
||||
return new AuthViewModel(_directAuthViewModel, _hostAuthViewModel, _oAuthViewModel, _provider, scheduler, scheduler);
|
||||
}
|
||||
}
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Reactive.Subjects;
|
||||
using Camelotia.Presentation.Interfaces;
|
||||
using Camelotia.Presentation.ViewModels;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Reactive.Testing;
|
||||
using NSubstitute;
|
||||
using ReactiveUI.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Camelotia.Presentation.Tests
|
||||
{
|
||||
public sealed class AuthViewModelTests
|
||||
{
|
||||
private readonly IDirectAuthViewModel _directAuthViewModel = Substitute.For<IDirectAuthViewModel>();
|
||||
private readonly IHostAuthViewModel _hostAuthViewModel = Substitute.For<IHostAuthViewModel>();
|
||||
private readonly IOAuthViewModel _oAuthViewModel = Substitute.For<IOAuthViewModel>();
|
||||
private readonly IProvider _provider = Substitute.For<IProvider>();
|
||||
|
||||
[Fact]
|
||||
public void IsAuthenticatedPropertyShouldDependOnFileProvider() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
var authorized = new Subject<bool>();
|
||||
_provider.IsAuthorized.Returns(authorized);
|
||||
var model = BuildAuthViewModel(scheduler);
|
||||
|
||||
model.IsAuthenticated.Should().BeFalse();
|
||||
authorized.OnNext(true);
|
||||
|
||||
scheduler.AdvanceBy(2);
|
||||
model.IsAuthenticated.Should().BeTrue();
|
||||
});
|
||||
|
||||
[Fact]
|
||||
public void SupportsPropsShouldDependOnProvider() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
var model = BuildAuthViewModel(scheduler);
|
||||
model.SupportsDirectAuth.Should().BeFalse();
|
||||
model.SupportsOAuth.Should().BeFalse();
|
||||
|
||||
_provider.SupportsDirectAuth.Returns(true);
|
||||
_provider.SupportsOAuth.Returns(true);
|
||||
|
||||
model.SupportsDirectAuth.Should().BeTrue();
|
||||
model.SupportsOAuth.Should().BeTrue();
|
||||
});
|
||||
|
||||
[Fact]
|
||||
public void ShouldReturnInjectedAuthViewModelTypes() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
var model = BuildAuthViewModel(scheduler);
|
||||
model.DirectAuth.Should().Be(_directAuthViewModel);
|
||||
model.OAuth.Should().Be(_oAuthViewModel);
|
||||
});
|
||||
|
||||
private AuthViewModel BuildAuthViewModel(IScheduler scheduler)
|
||||
{
|
||||
return new AuthViewModel(_directAuthViewModel, _hostAuthViewModel, _oAuthViewModel, _provider, scheduler, scheduler);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +1,34 @@
|
|||
using Camelotia.Presentation.Extensions;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace Camelotia.Presentation.Tests
|
||||
{
|
||||
public sealed class ByteConverterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(0, "0B")]
|
||||
[InlineData(520400, "520.4KB")]
|
||||
[InlineData(520040000, "520MB")]
|
||||
[InlineData(520068000, "520.1MB")]
|
||||
[InlineData(520185000000, "520.2GB")]
|
||||
public void ByteConverterShouldCalculateWithNoPrecisionSupplied(long byteCount, string expectedValue)
|
||||
{
|
||||
var stringValue = byteCount.ByteSizeToString();
|
||||
stringValue.Should().Be(expectedValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(115, 1, "115B")]
|
||||
[InlineData(115, 3, "115B")]
|
||||
[InlineData(520348, 3, "520.348KB")]
|
||||
[InlineData(520462400, 3, "520.462MB")]
|
||||
[InlineData(520573990000, 3, "520.574GB")]
|
||||
[InlineData(520124960000, 3, "520.125GB")]
|
||||
public void ByteConverterShouldCalculate(long byteCount, int precision, string expectedValue)
|
||||
{
|
||||
var stringValue = byteCount.ByteSizeToString(precision);
|
||||
stringValue.Should().Be(expectedValue);
|
||||
}
|
||||
}
|
||||
using Camelotia.Presentation.Extensions;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace Camelotia.Presentation.Tests
|
||||
{
|
||||
public sealed class ByteConverterTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(0, "0B")]
|
||||
[InlineData(520400, "520.4KB")]
|
||||
[InlineData(520040000, "520MB")]
|
||||
[InlineData(520068000, "520.1MB")]
|
||||
[InlineData(520185000000, "520.2GB")]
|
||||
public void ByteConverterShouldCalculateWithNoPrecisionSupplied(long byteCount, string expectedValue)
|
||||
{
|
||||
var stringValue = byteCount.ByteSizeToString();
|
||||
stringValue.Should().Be(expectedValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(115, 1, "115B")]
|
||||
[InlineData(115, 3, "115B")]
|
||||
[InlineData(520348, 3, "520.348KB")]
|
||||
[InlineData(520462400, 3, "520.462MB")]
|
||||
[InlineData(520573990000, 3, "520.574GB")]
|
||||
[InlineData(520124960000, 3, "520.125GB")]
|
||||
public void ByteConverterShouldCalculate(long byteCount, int precision, string expectedValue)
|
||||
{
|
||||
var stringValue = byteCount.ByteSizeToString(precision);
|
||||
stringValue.Should().Be(expectedValue);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,14 +5,14 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.msbuild" Version="2.6.1">
|
||||
<PackageReference Include="coverlet.msbuild" Version="2.6.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="5.6.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.1.0" />
|
||||
<PackageReference Include="ReactiveUI.Testing" Version="9.12.1" />
|
||||
<PackageReference Include="NSubstitute" Version="4.2.0" />
|
||||
<PackageReference Include="FluentAssertions" Version="5.7.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
|
||||
<PackageReference Include="ReactiveUI.Testing" Version="9.19.5" />
|
||||
<PackageReference Include="NSubstitute" Version="4.2.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
|
@ -1,76 +1,76 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using Camelotia.Services.Models;
|
||||
using Camelotia.Services.Providers;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace Camelotia.Presentation.Tests
|
||||
{
|
||||
public sealed class LocalFileSystemProviderTests
|
||||
{
|
||||
private static readonly Guid LocalIdentifier = Guid.NewGuid();
|
||||
private static readonly string Separator = Path.DirectorySeparatorChar.ToString();
|
||||
private readonly IProvider _provider = new LocalProvider(new ProviderModel
|
||||
{
|
||||
Id = LocalIdentifier,
|
||||
Created = DateTime.Now,
|
||||
Type = "Local"
|
||||
});
|
||||
|
||||
[Fact]
|
||||
public void ShouldExposeCorrectId()
|
||||
{
|
||||
_provider.Name.Should().Be("Local");
|
||||
_provider.Id.Should().Be(LocalIdentifier);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LocalFileSystemShouldNotSupportAuth()
|
||||
{
|
||||
_provider.SupportsHostAuth.Should().BeFalse();
|
||||
_provider.SupportsDirectAuth.Should().BeFalse();
|
||||
_provider.SupportsOAuth.Should().BeFalse();
|
||||
await _provider.DirectAuth(string.Empty, string.Empty);
|
||||
await _provider.OAuth();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldReturnFilesFromSpecificPath()
|
||||
{
|
||||
var real = await _provider.Get(Separator);
|
||||
var expected = Directory.GetFileSystemEntries(Separator);
|
||||
foreach (var model in real)
|
||||
expected.Should().Contain(path =>
|
||||
model.Path == path &&
|
||||
model.Name == Path.GetFileName(path) &&
|
||||
model.IsFolder == File
|
||||
.GetAttributes(path)
|
||||
.HasFlag(FileAttributes.Directory));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldReturnDrivesFromAnEmptyPath()
|
||||
{
|
||||
var real = await _provider.Get(_provider.InitialPath);
|
||||
var expected = DriveInfo
|
||||
.GetDrives()
|
||||
.Where(p => p.DriveType != DriveType.CDRom && p.IsReady)
|
||||
.ToList();
|
||||
|
||||
foreach (var model in real)
|
||||
expected.Should().Contain(drive =>
|
||||
model.Name == drive.Name && model.IsFolder);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldImplementNonNullInitialPath()
|
||||
{
|
||||
_provider.InitialPath.Should().NotBeNull();
|
||||
_provider.InitialPath.Should().Be(string.Empty);
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using Camelotia.Services.Models;
|
||||
using Camelotia.Services.Providers;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace Camelotia.Presentation.Tests
|
||||
{
|
||||
public sealed class LocalFileSystemProviderTests
|
||||
{
|
||||
private static readonly Guid LocalIdentifier = Guid.NewGuid();
|
||||
private static readonly string Separator = Path.DirectorySeparatorChar.ToString();
|
||||
private readonly IProvider _provider = new LocalProvider(new ProviderModel
|
||||
{
|
||||
Id = LocalIdentifier,
|
||||
Created = DateTime.Now,
|
||||
Type = "Local"
|
||||
});
|
||||
|
||||
[Fact]
|
||||
public void ShouldExposeCorrectId()
|
||||
{
|
||||
_provider.Name.Should().Be("Local");
|
||||
_provider.Id.Should().Be(LocalIdentifier);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LocalFileSystemShouldNotSupportAuth()
|
||||
{
|
||||
_provider.SupportsHostAuth.Should().BeFalse();
|
||||
_provider.SupportsDirectAuth.Should().BeFalse();
|
||||
_provider.SupportsOAuth.Should().BeFalse();
|
||||
await _provider.DirectAuth(string.Empty, string.Empty);
|
||||
await _provider.OAuth();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldReturnFilesFromSpecificPath()
|
||||
{
|
||||
var real = await _provider.Get(Separator);
|
||||
var expected = Directory.GetFileSystemEntries(Separator);
|
||||
foreach (var model in real)
|
||||
expected.Should().Contain(path =>
|
||||
model.Path == path &&
|
||||
model.Name == Path.GetFileName(path) &&
|
||||
model.IsFolder == File
|
||||
.GetAttributes(path)
|
||||
.HasFlag(FileAttributes.Directory));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShouldReturnDrivesFromAnEmptyPath()
|
||||
{
|
||||
var real = await _provider.Get(_provider.InitialPath);
|
||||
var expected = DriveInfo
|
||||
.GetDrives()
|
||||
.Where(p => p.DriveType != DriveType.CDRom && p.IsReady)
|
||||
.ToList();
|
||||
|
||||
foreach (var model in real)
|
||||
expected.Should().Contain(drive =>
|
||||
model.Name == drive.Name && model.IsFolder);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldImplementNonNullInitialPath()
|
||||
{
|
||||
_provider.InitialPath.Should().NotBeNull();
|
||||
_provider.InitialPath.Should().Be(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,55 +1,55 @@
|
|||
using System;
|
||||
using System.Reactive.Concurrency;
|
||||
using Camelotia.Presentation.ViewModels;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Reactive.Testing;
|
||||
using NSubstitute;
|
||||
using ReactiveUI.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Camelotia.Presentation.Tests
|
||||
{
|
||||
public sealed class OAuthViewModelTests
|
||||
{
|
||||
private readonly IProvider _provider = Substitute.For<IProvider>();
|
||||
|
||||
[Fact]
|
||||
public void ShouldBeBusyWhenLoggingIn() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
var model = BuildOAuthViewModel(scheduler);
|
||||
model.IsBusy.Should().BeFalse();
|
||||
model.Login.CanExecute(null).Should().BeTrue();
|
||||
model.Login.Execute(null);
|
||||
|
||||
scheduler.AdvanceBy(2);
|
||||
model.IsBusy.Should().BeTrue();
|
||||
|
||||
scheduler.AdvanceBy(2);
|
||||
model.IsBusy.Should().BeFalse();
|
||||
});
|
||||
|
||||
[Fact]
|
||||
public void HasErrorsShouldTriggerWhenProviderBreaks() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
_provider.OAuth().Returns(x => throw new Exception("example"));
|
||||
|
||||
var model = BuildOAuthViewModel(scheduler);
|
||||
model.ErrorMessage.Should().BeNullOrEmpty();
|
||||
model.HasErrors.Should().BeFalse();
|
||||
|
||||
model.Login.CanExecute(null).Should().BeTrue();
|
||||
model.Login.Execute(null);
|
||||
scheduler.AdvanceBy(2);
|
||||
|
||||
model.HasErrors.Should().BeTrue();
|
||||
model.ErrorMessage.Should().NotBeNullOrEmpty();
|
||||
model.ErrorMessage.Should().Be("example");
|
||||
});
|
||||
|
||||
private OAuthViewModel BuildOAuthViewModel(IScheduler scheduler)
|
||||
{
|
||||
return new OAuthViewModel(_provider, scheduler, scheduler);
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Reactive.Concurrency;
|
||||
using Camelotia.Presentation.ViewModels;
|
||||
using Camelotia.Services.Interfaces;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Reactive.Testing;
|
||||
using NSubstitute;
|
||||
using ReactiveUI.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Camelotia.Presentation.Tests
|
||||
{
|
||||
public sealed class OAuthViewModelTests
|
||||
{
|
||||
private readonly IProvider _provider = Substitute.For<IProvider>();
|
||||
|
||||
[Fact]
|
||||
public void ShouldBeBusyWhenLoggingIn() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
var model = BuildOAuthViewModel(scheduler);
|
||||
model.IsBusy.Should().BeFalse();
|
||||
model.Login.CanExecute(null).Should().BeTrue();
|
||||
model.Login.Execute(null);
|
||||
|
||||
scheduler.AdvanceBy(2);
|
||||
model.IsBusy.Should().BeTrue();
|
||||
|
||||
scheduler.AdvanceBy(2);
|
||||
model.IsBusy.Should().BeFalse();
|
||||
});
|
||||
|
||||
[Fact]
|
||||
public void HasErrorsShouldTriggerWhenProviderBreaks() => new TestScheduler().With(scheduler =>
|
||||
{
|
||||
_provider.OAuth().Returns(x => throw new Exception("example"));
|
||||
|
||||
var model = BuildOAuthViewModel(scheduler);
|
||||
model.ErrorMessage.Should().BeNullOrEmpty();
|
||||
model.HasErrors.Should().BeFalse();
|
||||
|
||||
model.Login.CanExecute(null).Should().BeTrue();
|
||||
model.Login.Execute(null);
|
||||
scheduler.AdvanceBy(2);
|
||||
|
||||
model.HasErrors.Should().BeTrue();
|
||||
model.ErrorMessage.Should().NotBeNullOrEmpty();
|
||||
model.ErrorMessage.Should().Be("example");
|
||||
});
|
||||
|
||||
private OAuthViewModel BuildOAuthViewModel(IScheduler scheduler)
|
||||
{
|
||||
return new OAuthViewModel(_provider, scheduler, scheduler);
|
||||
}
|
||||
}
|
||||
}
|
До Ширина: | Высота: | Размер: 1.4 KiB После Ширина: | Высота: | Размер: 1.4 KiB |
До Ширина: | Высота: | Размер: 7.5 KiB После Ширина: | Высота: | Размер: 7.5 KiB |
До Ширина: | Высота: | Размер: 2.9 KiB После Ширина: | Высота: | Размер: 2.9 KiB |
До Ширина: | Высота: | Размер: 1.6 KiB После Ширина: | Высота: | Размер: 1.6 KiB |
До Ширина: | Высота: | Размер: 1.2 KiB После Ширина: | Высота: | Размер: 1.2 KiB |
До Ширина: | Высота: | Размер: 1.4 KiB После Ширина: | Высота: | Размер: 1.4 KiB |
До Ширина: | Высота: | Размер: 3.1 KiB После Ширина: | Высота: | Размер: 3.1 KiB |
|
@ -35,7 +35,7 @@
|
|||
<BundleAssemblies>false</BundleAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
|
@ -43,6 +43,10 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
<EnableLLVM>false</EnableLLVM>
|
||||
<BundleAssemblies>false</BundleAssemblies>
|
||||
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
|
@ -52,18 +56,16 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Reactive" Version="4.1.3" />
|
||||
<PackageReference Include="System.Reactive" Version="4.1.5" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2" />
|
||||
<PackageReference Include="ReactiveUI.AndroidSupport" Version="9.12.1" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="3.6.0.264807" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.MediaRouter" Version="28.0.0" />
|
||||
<PackageReference Include="Xamarin.Plugin.FilePicker">
|
||||
<Version>2.0.135</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ReactiveUI.AndroidSupport" Version="9.19.5" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="4.1.0.618606" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.CardView" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.MediaRouter" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Plugin.FilePicker" Version="2.1.18" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Threading.Tasks.Extensions">
|
До Ширина: | Высота: | Размер: 4.6 KiB После Ширина: | Высота: | Размер: 4.6 KiB |
До Ширина: | Высота: | Размер: 11 KiB После Ширина: | Высота: | Размер: 11 KiB |
До Ширина: | Высота: | Размер: 2.7 KiB После Ширина: | Высота: | Размер: 2.7 KiB |