Skip to content

Commit

Permalink
#137 Draft of Avalonia realization. Not completed, but partial realiz…
Browse files Browse the repository at this point in the history
…ed. Has some bugs of bindings Uri and empty data.
  • Loading branch information
MonkAlex committed Jun 9, 2019
1 parent 1ee90c7 commit 2fe6083
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 5 deletions.
3 changes: 3 additions & 0 deletions MangaReader.Avalonia/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<DataTemplate DataType="c:MangaSettingsViewModel">
<view:MangaSettings/>
</DataTemplate>
<DataTemplate DataType="c:ProxySettingSelectorModel">
<view:ProxySetting/>
</DataTemplate>
<DataTemplate DataType="c:MangaModel">
<view:MangaView/>
</DataTemplate>
Expand Down
81 changes: 81 additions & 0 deletions MangaReader.Avalonia/View/ProxySetting.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="MangaReader.Avalonia.View.ProxySetting">
<StackPanel>
<Grid>
<Grid.Styles>
<Style Selector="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="4"/>
</Style>
<Style Selector="TextBox">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="4"/>
</Style>
<Style Selector="TextBox:disabled">
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}"/>
</Style>
</Grid.Styles>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Column="0" Grid.Row="0"
Items="{Binding ProxySettingModels}" SelectedItem="{Binding SelectedProxySettingModel}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Column="0" Grid.Row="1"
Orientation="Horizontal">
<Button Content="+" Command="{Binding Add}"/>
<Button Content="-" Command="{Binding Remove}"/>
</StackPanel>
<Grid Grid.Column="1" Grid.Row="0" DataContext="{Binding SelectedProxySettingModel}">
<Grid.RowDefinitions>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>
<RowDefinition Height="2*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="30*"></ColumnDefinition>
</Grid.ColumnDefinitions>

<TextBlock Grid.Row="0" Grid.Column="0" Text="Название: " />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Name}" IsEnabled="{Binding IsManual}"/>


<TextBlock Grid.Row="1" Grid.Column="0" Text="Адрес прокси: " />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Address}" IsEnabled="{Binding IsManual}"/>

<TextBlock Grid.Row="2" Grid.Column="0" Text="Имя пользователя: " />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding UserName}" IsEnabled="{Binding IsManual}"/>

<TextBlock Grid.Row="3" Grid.Column="0"
Text="Пароль: " />
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Password}" IsEnabled="{Binding IsManual}"/>
</Grid>
<Grid Grid.Column="1" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding TestAddress}"/>
<Button Grid.Column="1"
Command="{Binding Test}"
Content="Проверить"/>
</Grid>
</Grid>
</StackPanel>
</UserControl>
19 changes: 19 additions & 0 deletions MangaReader.Avalonia/View/ProxySetting.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace MangaReader.Avalonia.View
{
public class ProxySetting : UserControl
{
public ProxySetting()
{
this.InitializeComponent();
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}
7 changes: 6 additions & 1 deletion MangaReader.Avalonia/ViewModel/Command/DelegateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,10 @@ public DelegateCommand(Func<Task> execute, Func<bool> canExecute)
this.taskExecute = execute;
this.canExecute = canExecute;
}

public DelegateCommand(Func<Task> execute, Func<bool> canExecute, Action<DelegateCommand> action) : this(execute, canExecute)
{
action(this);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public Compression.CompressionMode Compression
public override async Task OnUnselected(ExplorerTabViewModel newModel)
{
await base.OnUnselected(newModel).ConfigureAwait(true);
if (!(newModel is SettingsViewModel || newModel is MangaSettingsViewModel))
if (!(newModel is SettingsViewModel || newModel is MangaSettingsViewModel || newModel is ProxySettingSelectorModel))
{
foreach (var tab in ExplorerViewModel.Instance.Tabs.OfType<MangaSettingsViewModel>().ToList())
ExplorerViewModel.Instance.Tabs.Remove(tab);
Expand Down
64 changes: 64 additions & 0 deletions MangaReader.Avalonia/ViewModel/Explorer/ProxySettingModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using MangaReader.Core.Account;

namespace MangaReader.Avalonia.ViewModel.Explorer
{
public class ProxySettingModel : ViewModelBase
{
public ProxySettingType SettingType { get; set; }

public int Id
{
get => id;
set => this.RaiseAndSetIfChanged(ref id, value);
}

private int id;

public string Name
{
get => name;
set => this.RaiseAndSetIfChanged(ref name, value);
}

private string name;

public Uri Address
{
get => address;
set => this.RaiseAndSetIfChanged(ref address, value);
}

private Uri address;

public string UserName
{
get => userName;
set => this.RaiseAndSetIfChanged(ref userName, value);
}

private string userName;

public string Password
{
get => password;
set => this.RaiseAndSetIfChanged(ref password, value);
}

private string password;

public bool IsManual { get; private set; }

public ProxySettingModel(ProxySetting setting)
{
Id = setting.Id;
Name = setting.Name;
Address = setting.Address;
UserName = setting.UserName;
Password = setting.Password;
SettingType = setting.SettingType;
IsManual = setting.SettingType == ProxySettingType.Manual;
}

}
}
144 changes: 144 additions & 0 deletions MangaReader.Avalonia/ViewModel/Explorer/ProxySettingSelectorModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using MangaReader.Avalonia.ViewModel.Command;
using MangaReader.Core.Account;
using MangaReader.Core.NHibernate;
using MangaReader.Core.Services;

namespace MangaReader.Avalonia.ViewModel.Explorer
{
public class ProxySettingSelectorModel : ExplorerTabViewModel
{

public ProxySettingModel SelectedProxySettingModel
{
get => selectedProxySettingModel;
set => this.RaiseAndSetIfChanged(ref selectedProxySettingModel, value);
}

private ProxySettingModel selectedProxySettingModel;

public ObservableCollection<ProxySettingModel> ProxySettingModels
{
get => proxySettingModels;
set => this.RaiseAndSetIfChanged(ref proxySettingModels, value);
}

private ObservableCollection<ProxySettingModel> proxySettingModels;

public string TestAddress
{
get => testAddress;
set => this.RaiseAndSetIfChanged(ref testAddress, value);
}

private string testAddress;

public DelegateCommand Add { get; }

public DelegateCommand Remove { get; }

public DelegateCommand Test { get; }

public ICommand Save { get; }

public ICommand Undo { get; }

public override Task OnSelected(ExplorerTabViewModel previousModel)
{
using (var context = Repository.GetEntityContext())
{
this.ProxySettingModels = new ObservableCollection<ProxySettingModel>(context
.Get<ProxySetting>()
.Select(s => new ProxySettingModel(s)));
this.SelectedProxySettingModel = this.ProxySettingModels.FirstOrDefault();
}
return base.OnSelected(previousModel);
}

public ProxySettingSelectorModel()
{
this.Name = "Прокси";
this.Priority = 600;
this.Add = new DelegateCommand(() =>
{
var newProxy = new ProxySettingModel(new ProxySetting(ProxySettingType.Manual));
this.ProxySettingModels.Add(newProxy);
this.SelectedProxySettingModel = newProxy;
});
this.Remove = new DelegateCommand(() =>
{
var selected = this.SelectedProxySettingModel;
var models = this.ProxySettingModels;
var index = models.IndexOf(selected);
var next = models.Count > index + 1 ? models[index + 1] : models[index - 1];
models.Remove(selected);
this.SelectedProxySettingModel = next;
return Task.CompletedTask;
}, () => this.SelectedProxySettingModel?.IsManual == true, SubscribeToCommand(nameof(SelectedProxySettingModel)));
this.Test = new DelegateCommand(TestAddressImpl, () => !string.IsNullOrWhiteSpace(this.TestAddress), SubscribeToCommand(nameof(TestAddress)));
this.Save = new DelegateCommand(SaveImpl, () => true);
this.testAddress = "https://github.com/MonkAlex/MangaReader";
}

private async Task SaveImpl()
{
if (ProxySettingModels == null)
return;

using (var context = Repository.GetEntityContext())
{
var manualProxies = await context.Get<ProxySetting>().ToListAsync().ConfigureAwait(true);
foreach (var model in ProxySettingModels.Where(m => m.IsManual))
{
var setting = model.Id == 0 ? new ProxySetting(ProxySettingType.Manual) : manualProxies.Single(p => p.Id == model.Id);
setting.Name = model.Name;
setting.Address = model.Address;
setting.UserName = model.UserName;
setting.Password = model.Password;
setting.SettingType = model.SettingType;
await context.Save(setting).ConfigureAwait(true);
model.Id = setting.Id;
}

var toRemove = manualProxies.Where(p => ProxySettingModels.All(m => m.Id != p.Id)).ToList();
foreach (var setting in toRemove)
{
await context.Delete(setting).ConfigureAwait(true);
}
}
}

private async Task TestAddressImpl()
{
try
{
var selected = this.SelectedProxySettingModel;
var address = this.TestAddress;

var setting = new ProxySetting(selected.SettingType)
{
Address = selected.Address,
UserName = selected.UserName,
Password = selected.Password
};
var proxy = setting.GetProxy();
var client = new TestCoockieClient() { Proxy = proxy };
await client.DownloadStringTaskAsync(address).ConfigureAwait(true);
Log.Add("Успешно.");
}
catch (Exception e)
{
Log.Exception(e, "Произошла ошибка.");
}
}

private class TestCoockieClient : CookieClient
{

}
}
}
5 changes: 3 additions & 2 deletions MangaReader.Avalonia/ViewModel/Explorer/SettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,15 @@ public override async Task OnSelected(ExplorerTabViewModel previousModel)
await ReloadConfig().ConfigureAwait(true);
var settings = await context.Get<MangaSetting>().ToListAsync().ConfigureAwait(true);
ExplorerViewModel.Instance.Tabs.AddRange(settings.Select(s => new MangaSettingsViewModel(s)));
ExplorerViewModel.Instance.Tabs.Add(new ProxySettingSelectorModel());
}
}
}

public override async Task OnUnselected(ExplorerTabViewModel newModel)
{
await base.OnUnselected(newModel).ConfigureAwait(true);
if (!(newModel is SettingsViewModel || newModel is MangaSettingsViewModel))
if (!(newModel is SettingsViewModel || newModel is MangaSettingsViewModel || newModel is ProxySettingSelectorModel))
{
foreach (var tab in ExplorerViewModel.Instance.Tabs.OfType<MangaSettingsViewModel>().ToList())
ExplorerViewModel.Instance.Tabs.Remove(tab);
Expand Down Expand Up @@ -149,4 +150,4 @@ public SettingsViewModel()
this.UndoChanged = new DelegateCommand(ReloadConfig, () => true);
}
}
}
}
13 changes: 12 additions & 1 deletion MangaReader.Avalonia/ViewModel/ViewModelBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using MangaReader.Avalonia.ViewModel.Command;
using ReactiveUI;

namespace MangaReader.Avalonia.ViewModel
Expand All @@ -16,5 +17,15 @@ public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
IReactiveObjectExtensions.RaisePropertyChanged(this, propertyName);
}

protected System.Action<DelegateCommand> SubscribeToCommand(string propertyName)
{
return command =>
this.PropertyChanged += (sender, args) =>
{
if (args.PropertyName == propertyName)
command.OnCanExecuteChanged();
};
}
}
}
}

0 comments on commit 2fe6083

Please sign in to comment.