diff --git a/Wintor/WinTorrent.sln b/Wintor/WinTorrent.sln
index a8a57f4..7d2bb15 100644
--- a/Wintor/WinTorrent.sln
+++ b/Wintor/WinTorrent.sln
@@ -7,16 +7,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinTorrent", "WinTorrent\Wi
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
+ {88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Debug|Any CPU.ActiveCfg = Debug|x86
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Debug|ARM.ActiveCfg = Debug|ARM
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Debug|ARM.Build.0 = Debug|ARM
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Debug|ARM.Deploy.0 = Debug|ARM
@@ -29,6 +32,7 @@ Global
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Debug|x86.ActiveCfg = Debug|x86
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Debug|x86.Build.0 = Debug|x86
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Debug|x86.Deploy.0 = Debug|x86
+ {88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Release|Any CPU.ActiveCfg = Release|x86
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Release|ARM.ActiveCfg = Release|ARM
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Release|ARM.Build.0 = Release|ARM
{88F8E34F-0129-4856-A1F7-4A89DA892C9B}.Release|ARM.Deploy.0 = Release|ARM
diff --git a/Wintor/WinTorrent/Dialogs/AddTorrentDialog.xaml b/Wintor/WinTorrent/Dialogs/AddTorrentDialog.xaml
index 3f824bf..c20492e 100644
--- a/Wintor/WinTorrent/Dialogs/AddTorrentDialog.xaml
+++ b/Wintor/WinTorrent/Dialogs/AddTorrentDialog.xaml
@@ -2,16 +2,38 @@
x:Class="WinTorrent.Dialogs.AddTorrentDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="using:WinTorrent.Dialogs"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
- Title="TITLE"
- PrimaryButtonText="Button1"
- SecondaryButtonText="Button2"
+ Title="Add new torrent"
+ PrimaryButtonText="Add"
+ CloseButtonText="Cancel"
+ DefaultButton="Primary"
+ IsPrimaryButtonEnabled="False"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick"
- SecondaryButtonClick="ContentDialog_SecondaryButtonClick">
+ Loaded="ContentDialog_Loaded">
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Wintor/WinTorrent/Dialogs/AddTorrentDialog.xaml.cs b/Wintor/WinTorrent/Dialogs/AddTorrentDialog.xaml.cs
index ac4f436..5c5de5c 100644
--- a/Wintor/WinTorrent/Dialogs/AddTorrentDialog.xaml.cs
+++ b/Wintor/WinTorrent/Dialogs/AddTorrentDialog.xaml.cs
@@ -1,35 +1,121 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices.WindowsRuntime;
-using Windows.Foundation;
-using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Controls.Primitives;
-using Windows.UI.Xaml.Data;
-using Windows.UI.Xaml.Input;
-using Windows.UI.Xaml.Media;
-using Windows.UI.Xaml.Navigation;
-
-// The Content Dialog item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
+using Windows.Storage;
+using Windows.Storage.Pickers;
+using WinTorrent.Utils;
+using MonoTorrent;
+using System.Security.Cryptography;
namespace WinTorrent.Dialogs
{
public sealed partial class AddTorrentDialog : ContentDialog
{
+ private StorageFile File { get; set; }
+ private Uri MagnetUrl { get; set; }
+
+ public StorageFolder DestinationFolder { get; set; }
+
+ public Torrent Torrent { get; private set; }
+
public AddTorrentDialog()
{
- this.InitializeComponent();
+ InitializeComponent();
+ RequestedTheme = Settings.Theme switch
+ {
+ 0 => ElementTheme.Light,
+ 1 => ElementTheme.Dark,
+ _ => ElementTheme.Default
+ };
}
- private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ private void RadioButton_Checked(object sender, RoutedEventArgs e)
{
+ bool useFile = ((RadioButton)sender).Tag as string == "file";
+
+ filePathField.IsEnabled = useFile;
+ filePickerButton.IsEnabled = useFile;
+
+ urlField.IsEnabled = !useFile;
+
+ if (useFile)
+ IsPrimaryButtonEnabled = File != null;
+ else
+ IsPrimaryButtonEnabled = MagnetUrl != null;
+
+ IsPrimaryButtonEnabled = DestinationFolder == null ? false : IsPrimaryButtonEnabled;
}
- private void ContentDialog_SecondaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ private async void FilePickerButton_Click(object sender, RoutedEventArgs e)
{
+ FileOpenPicker picker = new FileOpenPicker
+ {
+ CommitButtonText = "Open",
+ SuggestedStartLocation = PickerLocationId.Downloads,
+ };
+ picker.FileTypeFilter.Add(".torrent");
+
+ File = await picker.PickSingleFileAsync();
+
+ if (File == null)
+ return;
+
+ filePathField.Text = File.Path;
+ IsPrimaryButtonEnabled = DestinationFolder != null;
+ }
+
+ private async void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ {
+ var defferal = args.GetDeferral();
+ try
+ {
+ if (selectFile.IsChecked.Value)
+ {
+ StorageFile cachedFile = await File.CopyAsync(ApplicationData.Current.LocalFolder, File.Name, NameCollisionOption.GenerateUniqueName);
+ Torrent = await Torrent.LoadAsync(cachedFile.Path);
+ }
+ else
+ Torrent = await Torrent.LoadAsync(MagnetUrl, ApplicationData.Current.LocalFolder.Path);
+ }
+ catch (Exception e)
+ {
+ args.Cancel = true;
+ await new ContentDialog
+ {
+ Title = "Something went wrong...",
+ Content = "We can't load information for source. It may be corrupted or unavailable." +
+ "\n" + e.GetType() +
+ "\n" + e.Message,
+ PrimaryButtonText = "Close",
+ DefaultButton = ContentDialogButton.Primary
+ }.ShowAsync();
+ }
+
+ defferal.Complete();
+ }
+
+ private void ContentDialog_Loaded(object sender, RoutedEventArgs e)
+ {
+ selectFile.Checked += RadioButton_Checked;
+ selectUrl.Checked += RadioButton_Checked;
+ }
+
+ private async void SavePickerButton_Click(object sender, RoutedEventArgs e)
+ {
+ FolderPicker folderPicker = new FolderPicker
+ {
+ SuggestedStartLocation = PickerLocationId.Downloads,
+ CommitButtonText = "Choose folder"
+ };
+ folderPicker.FileTypeFilter.Add("*");
+ DestinationFolder = await folderPicker.PickSingleFolderAsync();
+
+ if (DestinationFolder == null)
+ return;
+
+ destinationPath.Text = DestinationFolder.Path;
+ IsPrimaryButtonEnabled = MagnetUrl != null || File != null;
}
}
}
diff --git a/Wintor/WinTorrent/Models/DataSize.cs b/Wintor/WinTorrent/Models/DataSize.cs
deleted file mode 100644
index c741f22..0000000
--- a/Wintor/WinTorrent/Models/DataSize.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace WinTorrent.Models
-{
- public struct DataSize : IComparable, IEquatable, IComparer
- {
- public long ByteSize { get; set; }
-
- public DataSize(long sizeInBytes) =>
- ByteSize = sizeInBytes;
-
- public override string ToString() =>
- $"{ByteSize} B";
-
- public int CompareTo(DataSize other) =>
- (int)Math.Clamp(ByteSize - other.ByteSize, -1, 1);
-
- public bool Equals(DataSize other) =>
- ByteSize == other.ByteSize;
-
- public int Compare(DataSize x, DataSize y) =>
- (int)Math.Clamp(x.ByteSize - y.ByteSize, -1, 1);
-
- public static double operator /(DataSize s1, DataSize s2) =>
- s1.ByteSize / s2.ByteSize;
- public static bool operator ==(DataSize s1, DataSize s2) =>
- s1.ByteSize == s2.ByteSize;
- public static bool operator !=(DataSize s1, DataSize s2) =>
- s1.ByteSize != s2.ByteSize;
- public static bool operator ==(DataSize s1, int s2) =>
- s1.ByteSize == s2;
- public static bool operator !=(DataSize s1, int s2) =>
- s1.ByteSize != s2;
- }
-
- public struct DownloadSpeed : IComparable, IEquatable, IComparer
- {
- public long BytesPerSecond { get; set; }
-
- public DownloadSpeed(long bps) =>
- BytesPerSecond = bps;
-
- public override string ToString() =>
- $"{BytesPerSecond} B/s";
-
- public int CompareTo(DownloadSpeed other) =>
- (int)Math.Clamp(BytesPerSecond - other.BytesPerSecond, -1, 1);
-
- public bool Equals(DownloadSpeed other) =>
- BytesPerSecond == other.BytesPerSecond;
-
- public int Compare(DownloadSpeed x, DownloadSpeed y) =>
- (int)Math.Clamp(x.BytesPerSecond - y.BytesPerSecond, -1, 1);
-
- public static double operator /(DownloadSpeed s1, DownloadSpeed s2) =>
- s1.BytesPerSecond / s2.BytesPerSecond;
- public static bool operator ==(DownloadSpeed s1, DownloadSpeed s2) =>
- s1.BytesPerSecond == s2.BytesPerSecond;
- public static bool operator !=(DownloadSpeed s1, DownloadSpeed s2) =>
- s1.BytesPerSecond != s2.BytesPerSecond;
- }
-}
diff --git a/Wintor/WinTorrent/Models/PointerHoverStateTrigger.cs b/Wintor/WinTorrent/Models/PointerHoverStateTrigger.cs
index cdca01f..411280a 100644
--- a/Wintor/WinTorrent/Models/PointerHoverStateTrigger.cs
+++ b/Wintor/WinTorrent/Models/PointerHoverStateTrigger.cs
@@ -1,4 +1,5 @@
-using Windows.UI.Xaml;
+using MonoTorrent.Client;
+using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using WinTorrent.Pages;
@@ -6,7 +7,7 @@ namespace WinTorrent.Models
{
class PointerHoverStateTrigger : StateTriggerBase
{
- public TorrentItem TargetItem
+ public TorrentManager TargetItem
{
get => _targetItem;
set
@@ -26,7 +27,7 @@ namespace WinTorrent.Models
_targetElement.PointerExited += PointerExited;
}
}
- private TorrentItem _targetItem;
+ private TorrentManager _targetItem;
private FrameworkElement _targetElement;
private void PointerExited(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e) =>
diff --git a/Wintor/WinTorrent/Models/TorrentItem.cs b/Wintor/WinTorrent/Models/TorrentItem.cs
deleted file mode 100644
index 5bfa2f6..0000000
--- a/Wintor/WinTorrent/Models/TorrentItem.cs
+++ /dev/null
@@ -1,133 +0,0 @@
-using System;
-using System.ComponentModel;
-using Windows.Storage;
-using WinTorrent.Utils;
-
-namespace WinTorrent.Models
-{
- public enum TorrentState
- {
- Initializing = 0,
- Downloading = 1,
- Cancelling = 2,
- Pausing = 3,
- Paused = 4,
- Resuming = 5,
- Completed = 6,
- Seeding = 7,
- Error = 8
- }
-
- public class TorrentItem : INotifyPropertyChanged
- {
- public event TorrentStateChangedEventHandler StateChanged;
- public event PropertyChangedEventHandler PropertyChanged;
-
- public string Title
- {
- get => _title;
- set
- {
- if (_title == value)
- return;
-
- _title = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Title)));
- }
- }
- private string _title;
-
- public TorrentState State
- {
- get => _state;
- set
- {
- if (_state == value)
- return;
-
- TorrentState previousState = _state;
- _state = value;
- StateChanged?.Invoke(this, previousState);
- TorrentClient.OnItemStateChanged(this, previousState);
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(State)));
- }
- }
- private TorrentState _state = TorrentState.Initializing;
-
- public DownloadSpeed TransmissionSpeed
- {
- get => _transmissionSpeed;
- set
- {
- if (_transmissionSpeed == value)
- return;
-
- _transmissionSpeed = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TransmissionSpeed)));
- }
- }
- private DownloadSpeed _transmissionSpeed;
-
- public DataSize Downloaded
- {
- get => _downloaded;
- set
- {
- if (_downloaded == value)
- return;
-
- _downloaded = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Downloaded)));
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Progress)));
- }
- }
- private DataSize _downloaded;
-
- public DataSize TotalSize
- {
- get => _totalSize;
- set
- {
- if (_totalSize == value)
- return;
-
- _totalSize = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TotalSize)));
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Progress)));
- }
- }
- private DataSize _totalSize;
-
- public double Progress => TotalSize != 0 ? ((double)Downloaded.ByteSize / TotalSize.ByteSize) : 0;
-
- public int SeedCount
- {
- get => _seedCount;
- set
- {
- if (_seedCount == value)
- return;
-
- _seedCount = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SeedCount)));
- }
- }
- private int _seedCount;
-
- public TimeSpan RemainingTime
- {
- get => _remainingTime;
- set
- {
- if (_remainingTime == value)
- return;
-
- _remainingTime = value;
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SeedCount)));
- }
- }
- private TimeSpan _remainingTime;
-
- public IStorageItem Files { get; set; }
- }
-}
diff --git a/Wintor/WinTorrent/Models/TorrentMetadataInfo.cs b/Wintor/WinTorrent/Models/TorrentMetadataInfo.cs
new file mode 100644
index 0000000..9312eb0
--- /dev/null
+++ b/Wintor/WinTorrent/Models/TorrentMetadataInfo.cs
@@ -0,0 +1,10 @@
+namespace WinTorrent.Models
+{
+ public class TorrentMetadataInfo
+ {
+ public string TorrentFileName { get; set; }
+ public string DestinationFolderFALToken { get; set; }
+ public string TorrentHash { get; set; }
+ public bool IsActive { get; set; }
+ }
+}
diff --git a/Wintor/WinTorrent/Models/TorrentStateDataTrigger.cs b/Wintor/WinTorrent/Models/TorrentStateDataTrigger.cs
deleted file mode 100644
index 40f4df8..0000000
--- a/Wintor/WinTorrent/Models/TorrentStateDataTrigger.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using Windows.UI.Xaml;
-
-namespace WinTorrent.Models
-{
- public class TorrentStateDataTrigger : StateTriggerBase
- {
- public TorrentState TargetState
- {
- get => _targetState;
- set
- {
- if (_targetState == value)
- return;
-
- _targetState = value;
- UpdateTrigger();
- }
- }
- private TorrentState _targetState;
-
- public TorrentItem TargetElement
- {
- get => _targetElement;
- set
- {
- if (_targetElement == value)
- return;
-
- if (_targetElement != null)
- _targetElement.StateChanged -= TargetElementStateChanged;
-
- _targetElement = value;
- _targetElement.StateChanged += TargetElementStateChanged;
-
- UpdateTrigger();
- }
- }
- private TorrentItem _targetElement;
-
- private void UpdateTrigger() =>
- SetActive(TargetElement?.State == TargetState);
-
- private void TargetElementStateChanged(TorrentItem sender, TorrentState previousState) =>
- UpdateTrigger();
- }
-}
diff --git a/Wintor/WinTorrent/Models/TorrentStateValuesEntry.cs b/Wintor/WinTorrent/Models/TorrentStateValuesEntry.cs
new file mode 100644
index 0000000..23e6d72
--- /dev/null
+++ b/Wintor/WinTorrent/Models/TorrentStateValuesEntry.cs
@@ -0,0 +1,16 @@
+using MonoTorrent.Client;
+
+namespace WinTorrent.Models
+{
+ public class TorrentStateValuesEntry
+ {
+ public object Value { get; set; }
+ public TorrentState[] AppliedTo { get; set; }
+
+ public TorrentStateValuesEntry(object value, params TorrentState[] states)
+ {
+ Value = value;
+ AppliedTo = states;
+ }
+ }
+}
diff --git a/Wintor/WinTorrent/Package.appxmanifest b/Wintor/WinTorrent/Package.appxmanifest
index 9b36fa4..c88a18d 100644
--- a/Wintor/WinTorrent/Package.appxmanifest
+++ b/Wintor/WinTorrent/Package.appxmanifest
@@ -4,7 +4,8 @@
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
- IgnorableNamespaces="uap mp">
+ xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
+ IgnorableNamespaces="uap mp rescap">
-
+
+
\ No newline at end of file
diff --git a/Wintor/WinTorrent/Pages/MainPage.xaml b/Wintor/WinTorrent/Pages/MainPage.xaml
index 5b50e08..7046473 100644
--- a/Wintor/WinTorrent/Pages/MainPage.xaml
+++ b/Wintor/WinTorrent/Pages/MainPage.xaml
@@ -4,18 +4,23 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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" xmlns:models="using:WinTorrent.Models"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:converters="using:WinTorrent.ValueConverters"
+ xmlns:client="using:MonoTorrent.Client"
+ xmlns:models="using:WinTorrent.Models"
mc:Ignorable="d">
+
+
-
+
@@ -101,172 +106,13 @@
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -309,24 +155,45 @@
-
+
-
-
-
-
- of
-
-
- remaining
+
+
+
+
+
+
+
+
+
+ of
-
-
+
diff --git a/Wintor/WinTorrent/Pages/MainPage.xaml.cs b/Wintor/WinTorrent/Pages/MainPage.xaml.cs
index 49c1221..998d1a7 100644
--- a/Wintor/WinTorrent/Pages/MainPage.xaml.cs
+++ b/Wintor/WinTorrent/Pages/MainPage.xaml.cs
@@ -1,10 +1,13 @@
-using System;
+using MonoTorrent.Client;
+using System;
+using System.IO;
+using Windows.Storage;
+using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;
using WinTorrent.Dialogs;
-using WinTorrent.Models;
using WinTorrent.Utils;
namespace WinTorrent.Pages
@@ -19,7 +22,9 @@ namespace WinTorrent.Pages
search.Translation += new System.Numerics.Vector3(0, 0, 10);
navigationList.SelectedIndex = 0;
- TorrentClient.TorrentItemStateChanged += (s, e) => NavigationViewList_SelectionChanged(this, null);
+
+ //File.Create("E://FUCKYOU.txt");
+ //File.WriteAllText("E://FUCKYOU.txt", "FUCK YOU!");
}
protected override void OnNavigatedTo(NavigationEventArgs e)
@@ -32,17 +37,27 @@ namespace WinTorrent.Pages
private void OpenSettings(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) =>
Frame.Navigate(typeof(SettingsPage), null, new SlideNavigationTransitionInfo { Effect = SlideNavigationTransitionEffect.FromLeft });
- private async void AddTorrent(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) =>
- await new AddTorrentDialog().ShowAsync();
+ private async void AddTorrent(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
+ {
+ AddTorrentDialog addDialog = new AddTorrentDialog();
+ await addDialog.ShowAsync();
+
+ if (addDialog.Torrent == null)
+ return;
+
+ TorrentClient.AddTorrent(addDialog.Torrent, addDialog.DestinationFolder);
+
+ // TODO: Configure torrent
+ }
private void NavigationViewList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
list.ItemsSource = (navigationList.SelectedItem as NavigationViewItem)?.Tag as string switch
{
- "downloading" => TorrentClient.Torrents.FindAll(i => i.State.BelongsTo(TorrentState.Downloading, TorrentState.Cancelling, TorrentState.Error, TorrentState.Initializing, TorrentState.Pausing)),
+ "downloading" => TorrentClient.Torrents.FindAll(i => i.State.BelongsTo(TorrentState.Downloading, TorrentState.Hashing, TorrentState.Error, TorrentState.Metadata, TorrentState.Starting, TorrentState.Stopping)),
"seeding" => TorrentClient.Torrents.FindAll(i => i.State.BelongsTo(TorrentState.Seeding)),
- "completed" => TorrentClient.Torrents.FindAll(i => i.State.BelongsTo(TorrentState.Completed, TorrentState.Seeding)),
- "paused" => TorrentClient.Torrents.FindAll(i => i.State.BelongsTo(TorrentState.Paused, TorrentState.Resuming)),
+ "completed" => TorrentClient.Torrents.FindAll(i => i.State.BelongsTo(TorrentState.Stopped, TorrentState.Seeding)),
+ "paused" => TorrentClient.Torrents.FindAll(i => i.State.BelongsTo(TorrentState.Paused, TorrentState.HashingPaused)),
_ => TorrentClient.Torrents
};
search.ItemsSource = null;
@@ -56,8 +71,8 @@ namespace WinTorrent.Pages
sender.ItemsSource = null;
navigationList.SelectedIndex = 0;
var result = TorrentClient.Torrents.FindAll(i =>
- i.Title.ToLowerInvariant().Contains(sender.Text.ToLowerInvariant()) ||
- (i.Files?.Path.ToLowerInvariant().Contains(sender.Text.ToLowerInvariant()) ?? false) ||
+ i.Torrent.Name.ToLowerInvariant().Contains(sender.Text.ToLowerInvariant()) ||
+ (i?.SavePath.ToLowerInvariant().Contains(sender.Text.ToLowerInvariant()) ?? false) ||
i.State.ToString().ToLowerInvariant().Contains(sender.Text.ToLowerInvariant()));
list.ItemsSource = result;
@@ -88,12 +103,12 @@ namespace WinTorrent.Pages
}
private void list_ItemClick(object sender, ItemClickEventArgs e) =>
- OpenItem(e.ClickedItem as TorrentItem);
+ OpenItem(e.ClickedItem as TorrentManager);
private void ViewItem(object sender, RoutedEventArgs e) =>
- OpenItem(list.ItemFromContainer(((sender as FrameworkElement).Parent as FrameworkElement).Parent) as TorrentItem);
+ OpenItem(list.ItemFromContainer(((sender as FrameworkElement).Parent as FrameworkElement).Parent) as TorrentManager);
- private void OpenItem(TorrentItem item)
+ private void OpenItem(TorrentManager item)
{
if (list.ContainerFromItem(item) as ListViewItem != null)
list.PrepareConnectedAnimation("ca1", item, "caTarget");
diff --git a/Wintor/WinTorrent/Pages/TorrentDetailsPage.xaml.cs b/Wintor/WinTorrent/Pages/TorrentDetailsPage.xaml.cs
index 4526af9..1c885ed 100644
--- a/Wintor/WinTorrent/Pages/TorrentDetailsPage.xaml.cs
+++ b/Wintor/WinTorrent/Pages/TorrentDetailsPage.xaml.cs
@@ -1,4 +1,5 @@
-using Windows.UI.Xaml;
+using MonoTorrent.Client;
+using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;
@@ -8,7 +9,7 @@ namespace WinTorrent.Pages
{
public sealed partial class TorrentDetailsPage : Page
{
- public TorrentItem Item { get; private set; }
+ public TorrentManager Item { get; private set; }
public TorrentDetailsPage()
{
@@ -20,7 +21,7 @@ namespace WinTorrent.Pages
{
base.OnNavigatedTo(e);
- Item = e.Parameter as TorrentItem;
+ Item = e.Parameter as TorrentManager;
if (ConnectedAnimationService.GetForCurrentView().GetAnimation("ca1") is ConnectedAnimation animation)
animation.TryStart(caTarget);
diff --git a/Wintor/WinTorrent/Utils/Settings.cs b/Wintor/WinTorrent/Utils/Settings.cs
index 125c1dc..624713c 100644
--- a/Wintor/WinTorrent/Utils/Settings.cs
+++ b/Wintor/WinTorrent/Utils/Settings.cs
@@ -62,7 +62,7 @@ namespace WinTorrent.Utils
public static async Task GetDefaultFolder()
{
if (string.IsNullOrWhiteSpace(DefaultFolder))
- return await DownloadsFolder.CreateFolderAsync(Package.Current.DisplayName, CreationCollisionOption.OpenIfExists);
+ return null;
else
return await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(DefaultFolder);
}
diff --git a/Wintor/WinTorrent/Utils/TorrentClient.cs b/Wintor/WinTorrent/Utils/TorrentClient.cs
index dc96393..0633731 100644
--- a/Wintor/WinTorrent/Utils/TorrentClient.cs
+++ b/Wintor/WinTorrent/Utils/TorrentClient.cs
@@ -1,140 +1,317 @@
-using System;
+using MonoTorrent;
+using MonoTorrent.BEncoding;
+using MonoTorrent.Client;
+using Newtonsoft.Json;
+using System;
using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.Storage;
+using Windows.Storage.AccessCache;
+using Windows.UI.Xaml.Controls;
using WinTorrent.Models;
namespace WinTorrent.Utils
{
- public delegate void TorrentStateChangedEventHandler(TorrentItem sender, TorrentState previousState);
-
public static class TorrentClient
{
- public static event TorrentStateChangedEventHandler TorrentItemStateChanged;
+ private static ApplicationDataContainer LocalSettings { get; } = ApplicationData.Current.LocalSettings;
+ private static StorageFolder LocalStorage { get; } = ApplicationData.Current.LocalFolder;
- public static List Torrents { get; }
+ private static ClientEngine Engine { get; set; }
+ public static EngineSettings Settings => Engine?.Settings;
+
+ public static List Torrents { get; } = new List();
+
+ private static BEncodedDictionary FastResumeData { get; set; } = new BEncodedDictionary();
+ private static List TorrentsMetadata { get; set; }
static TorrentClient()
{
- Torrents = new List
+ #region TestData
+ //Torrents = new List
+ //{
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Downloading,
+ // SeedCount = 15
+ // },
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Completed,
+ // SeedCount = 15
+ // },
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Paused,
+ // SeedCount = 15
+ // },
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Seeding,
+ // SeedCount = 15
+ // },
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Cancelling,
+ // SeedCount = 15
+ // },
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Initializing,
+ // SeedCount = 15
+ // },
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Pausing,
+ // SeedCount = 15
+ // },
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Resuming,
+ // SeedCount = 15
+ // },
+ // new TorrentItem
+ // {
+ // Title = "Microsoft Edge",
+ // TotalSize = new DataSize(3221225472),
+ // Downloaded = new DataSize(125829120),
+ // TransmissionSpeed = new DownloadSpeed(33554432),
+ // RemainingTime = TimeSpan.FromSeconds(36),
+ // State = Models.TorrentState.Error,
+ // SeedCount = 15
+ // }
+ //};
+ #endregion
+
+ EngineSettings engineSettings = new EngineSettings
{
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Downloading,
- SeedCount = 15
- },
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Completed,
- SeedCount = 15
- },
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Paused,
- SeedCount = 15
- },
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Seeding,
- SeedCount = 15
- },
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Cancelling,
- SeedCount = 15
- },
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Initializing,
- SeedCount = 15
- },
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Pausing,
- SeedCount = 15
- },
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Resuming,
- SeedCount = 15
- },
- new TorrentItem
- {
- Title = "Microsoft Edge",
- TotalSize = new DataSize(3221225472),
- Downloaded = new DataSize(125829120),
- TransmissionSpeed = new DownloadSpeed(33554432),
- RemainingTime = TimeSpan.FromSeconds(36),
- State = TorrentState.Error,
- SeedCount = 15
- }
+ SavePath = ApplicationData.Current.LocalFolder.Path,
+ MaximumDownloadSpeed = 0, // Set from settings
+ MaximumUploadSpeed = 0
};
+
+ Engine = new ClientEngine(engineSettings);
+
+ Restore();
}
- public static void AddTorrent()
+ public static async void AddTorrent(Torrent torrent, StorageFolder destinationFolder)
{
+ TorrentMetadataInfo meta = new TorrentMetadataInfo
+ {
+ DestinationFolderFALToken = StorageApplicationPermissions.FutureAccessList.Add(destinationFolder),
+ TorrentFileName = new FileInfo(torrent.TorrentPath).Name
+ };
+ TorrentManager manager = new TorrentManager(torrent, destinationFolder.Path);
+ meta.TorrentHash = manager.InfoHash.ToHex();
+
+ if (TorrentsMetadata.Any(i => i.TorrentHash == meta.TorrentHash))
+ {
+ ContentDialog alert = new ContentDialog
+ {
+ Title = "Duplicate torrent",
+ Content = "You have previously added this torrent to the queue. Do you want to discard it and start a new download?",
+ PrimaryButtonText = "Yes",
+ CloseButtonText = "No",
+ DefaultButton = ContentDialogButton.Close
+ };
+
+ if (await alert.ShowAsync() == ContentDialogResult.Primary)
+ {
+ FastResumeData.Remove(meta.TorrentHash);
+ TorrentsMetadata.RemoveAll(i => i.TorrentHash == meta.TorrentHash);
+ foreach(TorrentManager t in Torrents.FindAll(i => i.InfoHash.ToHex() == meta.TorrentHash))
+ {
+ await t.StopAsync();
+ await Engine.Unregister(t);
+ }
+ Torrents.RemoveAll(i => i.InfoHash.ToHex() == meta.TorrentHash);
+ }
+ else
+ return;
+ //return null;
+ }
+
+ TorrentsMetadata.Add(meta);
+ SaveData();
+
+ if (FastResumeData.ContainsKey(meta.TorrentHash))
+ manager.LoadFastResume(new FastResume((BEncodedDictionary)FastResumeData[torrent.InfoHash.ToHex()]));
+
+ await Engine.Register(manager);
+
+ Torrents.Add(manager);
+
+ await manager.StartAsync();
+
+ //return manager;
}
- public static void PauseTorrent()
+ public static async void Restore()
{
+ await Engine.EnablePortForwardingAsync(CancellationToken.None);
+ TorrentsMetadata = JsonConvert.DeserializeObject>(LocalSettings.Values["TorrentsMetadata"] as string ?? "") ?? new List();
+ try
+ {
+ StorageFile fastResumeFile = await LocalStorage.CreateFileAsync("TorrentFastResume.data", CreationCollisionOption.OpenIfExists);
+ FastResumeData = BEncodedValue.Decode(await fastResumeFile.OpenStreamForReadAsync());
+ }
+ catch { }
+
+ foreach (TorrentMetadataInfo meta in TorrentsMetadata)
+ RestoreTorrent(meta);
}
- public static void CancelTorrent()
+ private static async void RestoreTorrent(TorrentMetadataInfo meta)
{
+ try
+ {
+ StorageFile torrentFile = await LocalStorage.GetFileAsync(meta.TorrentFileName);
+ Torrent torrent = await Torrent.LoadAsync(await torrentFile.OpenStreamForReadAsync());
+ StorageFolder destinationFolder = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(meta.DestinationFolderFALToken);
+ TorrentManager manager = new TorrentManager(torrent, destinationFolder.Path);
+
+ if (FastResumeData.ContainsKey(meta.TorrentHash))
+ manager.LoadFastResume(new FastResume((BEncodedDictionary)FastResumeData[meta.TorrentHash]));
+
+ await Engine.Register(manager);
+
+ Torrents.Add(manager);
+
+ if (meta.IsActive)
+ await manager.StartAsync();
+ }
+ catch
+ {
+ TorrentsMetadata.Remove(meta);
+ SaveData();
+ }
}
- public static void ResumeTorrent()
+ public static async Task Suspend()
{
+ SaveData();
+ BEncodedDictionary fastResume = new BEncodedDictionary();
+ foreach (TorrentManager item in Torrents)
+ {
+ await item.StopAsync();
+ if (item.HashChecked)
+ fastResume.Add(item.InfoHash.ToHex(), item.SaveFastResume().Encode());
+ }
+
+ StorageFile fastResumeFile = await LocalStorage.CreateFileAsync("TorrentFastResume.data", CreationCollisionOption.OpenIfExists);
+ while (true)
+ try
+ {
+ await File.WriteAllBytesAsync(fastResumeFile.Path, fastResume.Encode());
+ break;
+ }
+ catch { }
+
+ Engine.Dispose();
}
- public static void SeedTorrent()
+ private static void SaveData()
{
-
+ foreach (TorrentManager item in Torrents)
+ TorrentsMetadata.Find(i => i.TorrentHash == item.InfoHash.ToHex()).IsActive = !item.State.BelongsTo(TorrentState.Paused, TorrentState.HashingPaused, TorrentState.Error, TorrentState.Stopped, TorrentState.Stopping);
+ LocalSettings.Values["TorrentsMetadata"] = JsonConvert.SerializeObject(TorrentsMetadata);
}
- public static void OnItemStateChanged(TorrentItem item, TorrentState previousState) =>
- TorrentItemStateChanged?.Invoke(item, previousState);
+ public static async void PauseTorrent(TorrentManager torrent)
+ {
+ await torrent.PauseAsync();
+ if (!torrent.HashChecked)
+ return;
+
+ if (FastResumeData.ContainsKey(torrent.InfoHash.ToHex()))
+ FastResumeData[torrent.InfoHash.ToHex()] = torrent.SaveFastResume().Encode();
+ else
+ FastResumeData.Add(torrent.InfoHash.ToHex(), torrent.SaveFastResume().Encode());
+
+ try
+ {
+ StorageFile fastResumeFile = await LocalStorage.CreateFileAsync("TorrentFastResume.data", CreationCollisionOption.OpenIfExists);
+ await File.WriteAllBytesAsync(fastResumeFile.Path, FastResumeData.Encode());
+ }
+ catch { }
+ }
+
+ public static async void RemoveTorrent(TorrentManager torrent, bool removeFiles = false)
+ {
+ await torrent.StopAsync();
+ TorrentMetadataInfo meta = TorrentsMetadata.Find(i => i.TorrentHash == torrent.InfoHash.ToHex());
+
+ if (removeFiles)
+ {
+ StorageFolder destinationFolder = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(meta.DestinationFolderFALToken);
+ foreach (TorrentFile file in torrent.Torrent.Files)
+ await (await destinationFolder.GetFileAsync(file.Path)).DeleteAsync(StorageDeleteOption.PermanentDelete);
+ }
+
+ StorageApplicationPermissions.FutureAccessList.Remove(meta.DestinationFolderFALToken);
+ await (await LocalStorage.GetFileAsync(meta.TorrentFileName))?.DeleteAsync(StorageDeleteOption.PermanentDelete);
+
+ FastResumeData.Remove(meta.TorrentHash);
+
+ TorrentsMetadata.RemoveAll(i => i.TorrentHash == torrent.InfoHash.ToHex());
+
+ SaveData();
+
+ try
+ {
+ StorageFile fastResumeFile = await LocalStorage.CreateFileAsync("TorrentFastResume.data", CreationCollisionOption.OpenIfExists);
+ await File.WriteAllBytesAsync(fastResumeFile.Path, FastResumeData.Encode());
+ }
+ catch { }
+ }
}
}
\ No newline at end of file
diff --git a/Wintor/WinTorrent/ValueConverters/EstimatesValueConverter.cs b/Wintor/WinTorrent/ValueConverters/EstimatesValueConverter.cs
new file mode 100644
index 0000000..62aa3b8
--- /dev/null
+++ b/Wintor/WinTorrent/ValueConverters/EstimatesValueConverter.cs
@@ -0,0 +1,25 @@
+using MonoTorrent.Client;
+using System;
+using Windows.UI.Xaml.Data;
+
+namespace WinTorrent.ValueConverters
+{
+ public class EstimatesValueConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ TorrentManager item = value as TorrentManager;
+ try
+ {
+ return TimeSpan.FromSeconds((item.Torrent.Size - item.Monitor.DataBytesDownloaded) / item.Monitor.DownloadSpeed);
+ }
+ catch(DivideByZeroException)
+ {
+ return "";
+ }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language) =>
+ null;
+ }
+}
diff --git a/Wintor/WinTorrent/ValueConverters/TorrentStateValueConverter.cs b/Wintor/WinTorrent/ValueConverters/TorrentStateValueConverter.cs
new file mode 100644
index 0000000..a971ec1
--- /dev/null
+++ b/Wintor/WinTorrent/ValueConverters/TorrentStateValueConverter.cs
@@ -0,0 +1,143 @@
+using MonoTorrent;
+using MonoTorrent.Client;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.UI;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Media;
+using WinTorrent.Models;
+
+namespace WinTorrent.ValueConverters
+{
+ public class TorrentStateValueConverter : IValueConverter
+ {
+ private static Dictionary StateDictionary { get; } = new Dictionary
+ {
+ {
+ "AccentColor",
+ new []
+ {
+ new TorrentStateValuesEntry(new SolidColorBrush(Colors.DeepSkyBlue),
+ TorrentState.Downloading),
+ new TorrentStateValuesEntry(new SolidColorBrush(Colors.Orange),
+ TorrentState.Hashing,
+ TorrentState.Metadata,
+ TorrentState.Starting,
+ TorrentState.Stopping),
+ new TorrentStateValuesEntry(new SolidColorBrush(Colors.Gray),
+ TorrentState.HashingPaused,
+ TorrentState.Paused,
+ TorrentState.Stopped),
+ new TorrentStateValuesEntry(new SolidColorBrush(Color.FromArgb(255, 85, 187, 85)),
+ TorrentState.Seeding),
+ new TorrentStateValuesEntry(new SolidColorBrush(Colors.Red),
+ TorrentState.Error),
+ }
+ },
+ {
+ "ProgressIndeterminate",
+ new [] { new TorrentStateValuesEntry(true,
+ TorrentState.Stopping,
+ TorrentState.Hashing,
+ TorrentState.Metadata,
+ TorrentState.Starting) }
+ },
+ {
+ "StatsVisibility",
+ new [] { new TorrentStateValuesEntry(Visibility.Visible, TorrentState.Downloading) }
+ },
+ {
+ "ErrorVisibility",
+ new [] { new TorrentStateValuesEntry(Visibility.Visible, TorrentState.Error) }
+ },
+ {
+ "ProgressValue",
+ new [] { new TorrentStateValuesEntry(1, TorrentState.Error,
+ TorrentState.Seeding,
+ TorrentState.Stopped) }
+ },
+ {
+ "PauseButtonVisibility",
+ new [] { new TorrentStateValuesEntry(Visibility.Visible,
+ TorrentState.Downloading,
+ TorrentState.Error,
+ TorrentState.Paused,
+ TorrentState.HashingPaused,
+ TorrentState.Stopped) }
+ },
+ {
+ "PauseButtonTooltip",
+ new []
+ {
+ new TorrentStateValuesEntry("Pause", TorrentState.Downloading),
+ new TorrentStateValuesEntry("Retry", TorrentState.Error),
+ new TorrentStateValuesEntry("Resume", TorrentState.Paused, TorrentState.HashingPaused),
+ new TorrentStateValuesEntry("Start", TorrentState.Stopped)
+ }
+ },
+ {
+ "PauseButtonIcon",
+ new []
+ {
+ new TorrentStateValuesEntry("\xE103", TorrentState.Downloading),
+ new TorrentStateValuesEntry("\xE149", TorrentState.Error),
+ new TorrentStateValuesEntry("\xE102", TorrentState.Paused,
+ TorrentState.HashingPaused,
+ TorrentState.Stopped)
+ }
+ },
+ {
+ "StatusLabel",
+ new []
+ {
+ new TorrentStateValuesEntry("Downloading", TorrentState.Downloading),
+ new TorrentStateValuesEntry("Error", TorrentState.Error),
+ new TorrentStateValuesEntry("Hashing", TorrentState.Hashing),
+ new TorrentStateValuesEntry("Hashing paused", TorrentState.HashingPaused),
+ new TorrentStateValuesEntry("Metadata", TorrentState.Metadata),
+ new TorrentStateValuesEntry("Paused", TorrentState.Paused),
+ new TorrentStateValuesEntry("Seeding", TorrentState.Seeding),
+ new TorrentStateValuesEntry("Starting", TorrentState.Starting),
+ new TorrentStateValuesEntry("Stopped", TorrentState.Stopped),
+ new TorrentStateValuesEntry("Stopping", TorrentState.Stopping),
+ }
+ },
+ {
+ "StatusIcon",
+ new []
+ {
+ new TorrentStateValuesEntry("\xE121",
+ TorrentState.Stopping,
+ TorrentState.Starting,
+ TorrentState.Metadata,
+ TorrentState.Hashing),
+ new TorrentStateValuesEntry("\xE103",
+ TorrentState.HashingPaused,
+ TorrentState.Paused),
+ new TorrentStateValuesEntry("\xE118",
+ TorrentState.Downloading),
+ new TorrentStateValuesEntry("\xE11C",
+ TorrentState.Seeding),
+ new TorrentStateValuesEntry("\xE7BA",
+ TorrentState.Error),
+ new TorrentStateValuesEntry("\xE15B",
+ TorrentState.Stopped)
+ }
+ }
+ };
+
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ try { return StateDictionary[parameter as string].FirstOrDefault(i => i.AppliedTo.Contains((TorrentState)value))?.Value; }
+ catch { return value; }
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language) =>
+ null;
+ }
+}
diff --git a/Wintor/WinTorrent/WinTorrent.csproj b/Wintor/WinTorrent/WinTorrent.csproj
index 7c38e01..61d8234 100644
--- a/Wintor/WinTorrent/WinTorrent.csproj
+++ b/Wintor/WinTorrent/WinTorrent.csproj
@@ -123,9 +123,9 @@
AddTorrentDialog.xaml
-
-
+
+
TorrentDetailsPage.xaml
@@ -141,7 +141,8 @@
-
+
+
@@ -265,6 +266,9 @@
Visual C++ 2015 Runtime for Universal Windows Platform Apps
+
+
+
14.0